Back to index

openldap  2.4.31
at.c
Go to the documentation of this file.
00001 /* at.c - routines for dealing with attribute types */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 
00017 #include "portable.h"
00018 
00019 #include <stdio.h>
00020 
00021 #include <ac/ctype.h>
00022 #include <ac/errno.h>
00023 #include <ac/socket.h>
00024 #include <ac/string.h>
00025 #include <ac/time.h>
00026 
00027 #include "slap.h"
00028 
00029 
00030 const char *
00031 at_syntax(
00032        AttributeType *at )
00033 {
00034        for ( ; at != NULL; at = at->sat_sup ) {
00035               if ( at->sat_syntax_oid ) {
00036                      return at->sat_syntax_oid;
00037               }
00038        }
00039 
00040        assert( 0 );
00041 
00042        return NULL;
00043 }
00044 
00045 int
00046 is_at_syntax(
00047        AttributeType *at,
00048        const char    *oid )
00049 {
00050        const char *syn_oid = at_syntax( at );
00051 
00052        if ( syn_oid ) {
00053               return strcmp( syn_oid, oid ) == 0;
00054        }
00055 
00056        return 0;
00057 }
00058 
00059 int is_at_subtype(
00060        AttributeType *sub,
00061        AttributeType *sup )
00062 {
00063        for( ; sub != NULL; sub = sub->sat_sup ) {
00064               if( sub == sup ) return 1;
00065        }
00066 
00067        return 0;
00068 }
00069 
00070 struct aindexrec {
00071        struct berval air_name;
00072        AttributeType *air_at;
00073 };
00074 
00075 static Avlnode       *attr_index = NULL;
00076 static Avlnode       *attr_cache = NULL;
00077 static LDAP_STAILQ_HEAD(ATList, AttributeType) attr_list
00078        = LDAP_STAILQ_HEAD_INITIALIZER(attr_list);
00079 
00080 /* Last hardcoded attribute registered */
00081 AttributeType *at_sys_tail;
00082 
00083 int at_oc_cache;
00084 
00085 static int
00086 attr_index_cmp(
00087     const void       *v_air1,
00088     const void       *v_air2 )
00089 {
00090        const struct aindexrec      *air1 = v_air1;
00091        const struct aindexrec      *air2 = v_air2;
00092        int i = air1->air_name.bv_len - air2->air_name.bv_len;
00093        if (i) return i;
00094        return (strcasecmp( air1->air_name.bv_val, air2->air_name.bv_val ));
00095 }
00096 
00097 static int
00098 attr_index_name_cmp(
00099     const void       *v_type,
00100     const void       *v_air )
00101 {
00102     const struct berval    *type = v_type;
00103     const struct aindexrec *air  = v_air;
00104        int i = type->bv_len - air->air_name.bv_len;
00105        if (i) return i;
00106        return (strncasecmp( type->bv_val, air->air_name.bv_val, type->bv_len ));
00107 }
00108 
00109 AttributeType *
00110 at_find( const char *name )
00111 {
00112        struct berval bv;
00113 
00114        bv.bv_val = (char *)name;
00115        bv.bv_len = strlen( name );
00116 
00117        return at_bvfind( &bv );
00118 }
00119 
00120 AttributeType *
00121 at_bvfind( struct berval *name )
00122 {
00123        struct aindexrec *air;
00124 
00125        if ( attr_cache ) {
00126               air = avl_find( attr_cache, name, attr_index_name_cmp );
00127               if ( air ) return air->air_at;
00128        }
00129 
00130        air = avl_find( attr_index, name, attr_index_name_cmp );
00131 
00132        if ( air ) {
00133               if ( air->air_at->sat_flags & SLAP_AT_DELETED ) {
00134                      air = NULL;
00135               } else if (( slapMode & SLAP_TOOL_MODE ) && at_oc_cache ) {
00136                      avl_insert( &attr_cache, (caddr_t) air,
00137                             attr_index_cmp, avl_dup_error );
00138               }
00139        }
00140 
00141        return air != NULL ? air->air_at : NULL;
00142 }
00143 
00144 int
00145 at_append_to_list(
00146     AttributeType    *sat,
00147     AttributeType    ***listp )
00148 {
00149        AttributeType **list;
00150        AttributeType **list1;
00151        int           size;
00152 
00153        list = *listp;
00154        if ( !list ) {
00155               size = 2;
00156               list = ch_calloc(size, sizeof(AttributeType *));
00157               if ( !list ) {
00158                      return -1;
00159               }
00160        } else {
00161               size = 0;
00162               list1 = *listp;
00163               while ( *list1 ) {
00164                      size++;
00165                      list1++;
00166               }
00167               size += 2;
00168               list1 = ch_realloc(list, size*sizeof(AttributeType *));
00169               if ( !list1 ) {
00170                      return -1;
00171               }
00172               list = list1;
00173        }
00174        list[size-2] = sat;
00175        list[size-1] = NULL;
00176        *listp = list;
00177        return 0;
00178 }
00179 
00180 int
00181 at_delete_from_list(
00182     int                     pos,
00183     AttributeType    ***listp )
00184 {
00185        AttributeType **list;
00186        AttributeType **list1;
00187        int           i;
00188        int           j;
00189 
00190        if ( pos < 0 ) {
00191               return -2;
00192        }
00193        list = *listp;
00194        for ( i=0; list[i]; i++ )
00195               ;
00196        if ( pos >= i ) {
00197               return -2;
00198        }
00199        for ( i=pos, j=pos+1; list[j]; i++, j++ ) {
00200               list[i] = list[j];
00201        }
00202        list[i] = NULL;
00203        /* Tell the runtime this can be shrinked */
00204        list1 = ch_realloc(list, (i+1)*sizeof(AttributeType **));
00205        if ( !list1 ) {
00206               return -1;
00207        }
00208        *listp = list1;
00209        return 0;
00210 }
00211 
00212 int
00213 at_find_in_list(
00214     AttributeType    *sat,
00215     AttributeType    **list )
00216 {
00217        int    i;
00218 
00219        if ( !list ) {
00220               return -1;
00221        }
00222        for ( i=0; list[i]; i++ ) {
00223               if ( sat == list[i] ) {
00224                      return i;
00225               }
00226        }
00227        return -1;
00228 }
00229 
00230 static void
00231 at_delete_names( AttributeType *at )
00232 {
00233        char                 **names = at->sat_names;
00234 
00235        if (!names) return;
00236 
00237        while (*names) {
00238               struct aindexrec     tmpair, *air;
00239 
00240               ber_str2bv( *names, 0, 0, &tmpair.air_name );
00241               tmpair.air_at = at;
00242               air = (struct aindexrec *)avl_delete( &attr_index,
00243                      (caddr_t)&tmpair, attr_index_cmp );
00244               assert( air != NULL );
00245               ldap_memfree( air );
00246               names++;
00247        }
00248 }
00249 
00250 /* Mark the attribute as deleted, remove from list, and remove all its
00251  * names from the AVL tree. Leave the OID in the tree.
00252  */
00253 void
00254 at_delete( AttributeType *at )
00255 {
00256        at->sat_flags |= SLAP_AT_DELETED;
00257 
00258        LDAP_STAILQ_REMOVE(&attr_list, at, AttributeType, sat_next);
00259 
00260        at_delete_names( at );
00261 }
00262 
00263 static void
00264 at_clean( AttributeType *a )
00265 {
00266        if ( a->sat_equality ) {
00267               MatchingRule  *mr;
00268 
00269               mr = mr_find( a->sat_equality->smr_oid );
00270               assert( mr != NULL );
00271               if ( mr != a->sat_equality ) {
00272                      ch_free( a->sat_equality );
00273                      a->sat_equality = NULL;
00274               }
00275        }
00276 
00277        assert( a->sat_syntax != NULL );
00278        if ( a->sat_syntax != NULL ) {
00279               Syntax        *syn;
00280 
00281               syn = syn_find( a->sat_syntax->ssyn_oid );
00282               assert( syn != NULL );
00283               if ( syn != a->sat_syntax ) {
00284                      ch_free( a->sat_syntax );
00285                      a->sat_syntax = NULL;
00286               }
00287        }
00288 
00289        if ( a->sat_oidmacro ) {
00290               ldap_memfree( a->sat_oidmacro );
00291               a->sat_oidmacro = NULL;
00292        }
00293        if ( a->sat_soidmacro ) {
00294               ldap_memfree( a->sat_soidmacro );
00295               a->sat_soidmacro = NULL;
00296        }
00297        if ( a->sat_subtypes ) {
00298               ldap_memfree( a->sat_subtypes );
00299               a->sat_subtypes = NULL;
00300        }
00301 }
00302 
00303 static void
00304 at_destroy_one( void *v )
00305 {
00306        struct aindexrec *air = v;
00307        AttributeType *a = air->air_at;
00308 
00309        at_clean( a );
00310        ad_destroy(a->sat_ad);
00311        ldap_pvt_thread_mutex_destroy(&a->sat_ad_mutex);
00312        ldap_attributetype_free((LDAPAttributeType *)a);
00313        ldap_memfree(air);
00314 }
00315 
00316 void
00317 at_destroy( void )
00318 {
00319        AttributeType *a;
00320 
00321        while( !LDAP_STAILQ_EMPTY(&attr_list) ) {
00322               a = LDAP_STAILQ_FIRST(&attr_list);
00323               LDAP_STAILQ_REMOVE_HEAD(&attr_list, sat_next);
00324 
00325               at_delete_names( a );
00326        }
00327 
00328        avl_free(attr_index, at_destroy_one);
00329 
00330        if ( slap_schema.si_at_undefined ) {
00331               ad_destroy(slap_schema.si_at_undefined->sat_ad);
00332        }
00333 
00334        if ( slap_schema.si_at_proxied ) {
00335               ad_destroy(slap_schema.si_at_proxied->sat_ad);
00336        }
00337 }
00338 
00339 int
00340 at_start( AttributeType **at )
00341 {
00342        assert( at != NULL );
00343 
00344        *at = LDAP_STAILQ_FIRST(&attr_list);
00345 
00346        return (*at != NULL);
00347 }
00348 
00349 int
00350 at_next( AttributeType **at )
00351 {
00352        assert( at != NULL );
00353 
00354 #if 0  /* pedantic check: don't use this */
00355        {
00356               AttributeType *tmp = NULL;
00357 
00358               LDAP_STAILQ_FOREACH(tmp,&attr_list,sat_next) {
00359                      if ( tmp == *at ) {
00360                             break;
00361                      }
00362               }
00363 
00364               assert( tmp != NULL );
00365        }
00366 #endif
00367 
00368        *at = LDAP_STAILQ_NEXT(*at,sat_next);
00369 
00370        return (*at != NULL);
00371 }
00372 
00373 /*
00374  * check whether the two attributeTypes actually __are__ identical,
00375  * or rather inconsistent
00376  */
00377 static int
00378 at_check_dup(
00379        AttributeType        *sat,
00380        AttributeType        *new_sat )
00381 {
00382        if ( new_sat->sat_oid != NULL ) {
00383               if ( sat->sat_oid == NULL ) {
00384                      return SLAP_SCHERR_ATTR_INCONSISTENT;
00385               }
00386 
00387               if ( strcmp( sat->sat_oid, new_sat->sat_oid ) != 0 ) {
00388                      return SLAP_SCHERR_ATTR_INCONSISTENT;
00389               }
00390 
00391        } else {
00392               if ( sat->sat_oid != NULL ) {
00393                      return SLAP_SCHERR_ATTR_INCONSISTENT;
00394               }
00395        }
00396 
00397        if ( new_sat->sat_names ) {
00398               int    i;
00399 
00400               if ( sat->sat_names == NULL ) {
00401                      return SLAP_SCHERR_ATTR_INCONSISTENT;
00402               }
00403 
00404               for ( i = 0; new_sat->sat_names[ i ]; i++ ) {
00405                      if ( sat->sat_names[ i ] == NULL ) {
00406                             return SLAP_SCHERR_ATTR_INCONSISTENT;
00407                      }
00408                      
00409                      if ( strcasecmp( sat->sat_names[ i ],
00410                                    new_sat->sat_names[ i ] ) != 0 )
00411                      {
00412                             return SLAP_SCHERR_ATTR_INCONSISTENT;
00413                      }
00414               }
00415        } else {
00416               if ( sat->sat_names != NULL ) {
00417                      return SLAP_SCHERR_ATTR_INCONSISTENT;
00418               }
00419        }
00420 
00421        return SLAP_SCHERR_ATTR_DUP;
00422 }
00423 
00424 static struct aindexrec *air_old;
00425 
00426 static int
00427 at_dup_error( void *left, void *right )
00428 {
00429        air_old = left;
00430        return -1;
00431 }
00432 
00433 static int
00434 at_insert(
00435     AttributeType    **rat,
00436        AttributeType *prev,
00437     const char              **err )
00438 {
00439        struct aindexrec     *air;
00440        char                 **names = NULL;
00441        AttributeType *sat = *rat;
00442 
00443        if ( sat->sat_oid ) {
00444               air = (struct aindexrec *)
00445                      ch_calloc( 1, sizeof(struct aindexrec) );
00446               ber_str2bv( sat->sat_oid, 0, 0, &air->air_name );
00447               air->air_at = sat;
00448               air_old = NULL;
00449 
00450               if ( avl_insert( &attr_index, (caddr_t) air,
00451                                attr_index_cmp, at_dup_error ) )
00452               {
00453                      AttributeType *old_sat;
00454                      int           rc;
00455 
00456                      *err = sat->sat_oid;
00457 
00458                      assert( air_old != NULL );
00459                      old_sat = air_old->air_at;
00460 
00461                      /* replacing a deleted definition? */
00462                      if ( old_sat->sat_flags & SLAP_AT_DELETED ) {
00463                             AttributeType tmp;
00464                             AttributeDescription *ad;
00465                             
00466                             /* Keep old oid, free new oid;
00467                              * Keep old ads, free new ads;
00468                              * Keep old ad_mutex, free new ad_mutex;
00469                              * Keep new everything else, free old
00470                              */
00471                             tmp = *old_sat;
00472                             *old_sat = *sat;
00473                             old_sat->sat_oid = tmp.sat_oid;
00474                             tmp.sat_oid = sat->sat_oid;
00475                             old_sat->sat_ad = tmp.sat_ad;
00476                             tmp.sat_ad = sat->sat_ad;
00477                             old_sat->sat_ad_mutex = tmp.sat_ad_mutex;
00478                             tmp.sat_ad_mutex = sat->sat_ad_mutex;
00479                             *sat = tmp;
00480 
00481                             /* Check for basic ad pointing at old cname */
00482                             for ( ad = old_sat->sat_ad; ad; ad=ad->ad_next ) {
00483                                    if ( ad->ad_cname.bv_val == sat->sat_cname.bv_val ) {
00484                                           ad->ad_cname = old_sat->sat_cname;
00485                                           break;
00486                                    }
00487                             }
00488 
00489                             at_clean( sat );
00490                             at_destroy_one( air );
00491 
00492                             air = air_old;
00493                             sat = old_sat;
00494                             *rat = sat;
00495                      } else {
00496                             ldap_memfree( air );
00497 
00498                             rc = at_check_dup( old_sat, sat );
00499 
00500                             return rc;
00501                      }
00502               }
00503               /* FIX: temporal consistency check */
00504               at_bvfind( &air->air_name );
00505        }
00506 
00507        names = sat->sat_names;
00508        if ( names ) {
00509               while ( *names ) {
00510                      air = (struct aindexrec *)
00511                             ch_calloc( 1, sizeof(struct aindexrec) );
00512                      ber_str2bv( *names, 0, 0, &air->air_name );
00513                      air->air_at = sat;
00514                      if ( avl_insert( &attr_index, (caddr_t) air,
00515                                       attr_index_cmp, avl_dup_error ) )
00516                      {
00517                             AttributeType *old_sat;
00518                             int           rc;
00519 
00520                             *err = *names;
00521 
00522                             old_sat = at_bvfind( &air->air_name );
00523                             assert( old_sat != NULL );
00524                             rc = at_check_dup( old_sat, sat );
00525 
00526                             ldap_memfree(air);
00527 
00528                             while ( names > sat->sat_names ) {
00529                                    struct aindexrec     tmpair;
00530 
00531                                    names--;
00532                                    ber_str2bv( *names, 0, 0, &tmpair.air_name );
00533                                    tmpair.air_at = sat;
00534                                    air = (struct aindexrec *)avl_delete( &attr_index,
00535                                           (caddr_t)&tmpair, attr_index_cmp );
00536                                    assert( air != NULL );
00537                                    ldap_memfree( air );
00538                             }
00539 
00540                             if ( sat->sat_oid ) {
00541                                    struct aindexrec     tmpair;
00542 
00543                                    ber_str2bv( sat->sat_oid, 0, 0, &tmpair.air_name );
00544                                    tmpair.air_at = sat;
00545                                    air = (struct aindexrec *)avl_delete( &attr_index,
00546                                           (caddr_t)&tmpair, attr_index_cmp );
00547                                    assert( air != NULL );
00548                                    ldap_memfree( air );
00549                             }
00550 
00551                             return rc;
00552                      }
00553                      /* FIX: temporal consistency check */
00554                      at_bvfind(&air->air_name);
00555                      names++;
00556               }
00557        }
00558 
00559        if ( sat->sat_oid ) {
00560               slap_ad_undef_promote( sat->sat_oid, sat );
00561        }
00562 
00563        names = sat->sat_names;
00564        if ( names ) {
00565               while ( *names ) {
00566                      slap_ad_undef_promote( *names, sat );
00567                      names++;
00568               }
00569        }
00570 
00571        if ( sat->sat_flags & SLAP_AT_HARDCODE ) {
00572               prev = at_sys_tail;
00573               at_sys_tail = sat;
00574        }
00575        if ( prev ) {
00576               LDAP_STAILQ_INSERT_AFTER( &attr_list, prev, sat, sat_next );
00577        } else {
00578               LDAP_STAILQ_INSERT_TAIL( &attr_list, sat, sat_next );
00579        }
00580 
00581        return 0;
00582 }
00583 
00584 int
00585 at_add(
00586        LDAPAttributeType    *at,
00587        int                  user,
00588        AttributeType        **rsat,
00589        AttributeType *prev,
00590        const char           **err )
00591 {
00592        AttributeType *sat = NULL;
00593        MatchingRule  *mr = NULL;
00594        Syntax        *syn = NULL;
00595        int           i;
00596        int           code = LDAP_SUCCESS;
00597        char          *cname = NULL;
00598        char          *oidm = NULL;
00599        char          *soidm = NULL;
00600 
00601        if ( !at->at_oid ) {
00602               *err = "";
00603               return SLAP_SCHERR_ATTR_INCOMPLETE;
00604        }
00605 
00606        if ( !OID_LEADCHAR( at->at_oid[0] )) {
00607               char   *oid;
00608 
00609               /* Expand OID macros */
00610               oid = oidm_find( at->at_oid );
00611               if ( !oid ) {
00612                      *err = at->at_oid;
00613                      return SLAP_SCHERR_OIDM;
00614               }
00615               if ( oid != at->at_oid ) {
00616                      oidm = at->at_oid;
00617                      at->at_oid = oid;
00618               }
00619        }
00620 
00621        if ( at->at_syntax_oid && !OID_LEADCHAR( at->at_syntax_oid[0] )) {
00622               char   *oid;
00623 
00624               /* Expand OID macros */
00625               oid = oidm_find( at->at_syntax_oid );
00626               if ( !oid ) {
00627                      *err = at->at_syntax_oid;
00628                      code = SLAP_SCHERR_OIDM;
00629                      goto error_return;
00630               }
00631               if ( oid != at->at_syntax_oid ) {
00632                      soidm = at->at_syntax_oid;
00633                      at->at_syntax_oid = oid;
00634               }
00635        }
00636 
00637        if ( at->at_names && at->at_names[0] ) {
00638               int i;
00639 
00640               for( i=0; at->at_names[i]; i++ ) {
00641                      if( !slap_valid_descr( at->at_names[i] ) ) {
00642                             *err = at->at_names[i];
00643                             code = SLAP_SCHERR_BAD_DESCR;
00644                             goto error_return;
00645                      }
00646               }
00647 
00648               cname = at->at_names[0];
00649 
00650        } else {
00651               cname = at->at_oid;
00652 
00653        }
00654 
00655        *err = cname;
00656 
00657        if ( !at->at_usage && at->at_no_user_mod ) {
00658               /* user attribute must be modifable */
00659               code = SLAP_SCHERR_ATTR_BAD_USAGE;
00660               goto error_return;
00661        }
00662 
00663        if ( at->at_collective ) {
00664               if( at->at_usage ) {
00665                      /* collective attributes cannot be operational */
00666                      code = SLAP_SCHERR_ATTR_BAD_USAGE;
00667                      goto error_return;
00668               }
00669 
00670               if( at->at_single_value ) {
00671                      /* collective attributes cannot be single-valued */
00672                      code = SLAP_SCHERR_ATTR_BAD_USAGE;
00673                      goto error_return;
00674               }
00675        }
00676 
00677        sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) );
00678        AC_MEMCPY( &sat->sat_atype, at, sizeof(LDAPAttributeType));
00679 
00680        sat->sat_cname.bv_val = cname;
00681        sat->sat_cname.bv_len = strlen( cname );
00682        sat->sat_oidmacro = oidm;
00683        sat->sat_soidmacro = soidm;
00684        ldap_pvt_thread_mutex_init(&sat->sat_ad_mutex);
00685 
00686        if ( at->at_sup_oid ) {
00687               AttributeType *supsat = at_find(at->at_sup_oid);
00688 
00689               if ( supsat == NULL ) {
00690                      *err = at->at_sup_oid;
00691                      code = SLAP_SCHERR_ATTR_NOT_FOUND;
00692                      goto error_return;
00693               }
00694 
00695               sat->sat_sup = supsat;
00696 
00697               if ( at_append_to_list(sat, &supsat->sat_subtypes) ) {
00698                      code = SLAP_SCHERR_OUTOFMEM;
00699                      goto error_return;
00700               }
00701 
00702               if ( sat->sat_usage != supsat->sat_usage ) {
00703                      /* subtypes must have same usage as their SUP */
00704                      code = SLAP_SCHERR_ATTR_BAD_USAGE;
00705                      goto error_return;
00706               }
00707 
00708               if ( supsat->sat_obsolete && !sat->sat_obsolete ) {
00709                      /* subtypes must be obsolete if super is */
00710                      code = SLAP_SCHERR_ATTR_BAD_SUP;
00711                      goto error_return;
00712               }
00713 
00714               if ( sat->sat_flags & SLAP_AT_FINAL ) {
00715                      /* cannot subtype a "final" attribute type */
00716                      code = SLAP_SCHERR_ATTR_BAD_SUP;
00717                      goto error_return;
00718               }
00719        }
00720 
00721        /*
00722         * Inherit definitions from superiors.  We only check the
00723         * direct superior since that one has already inherited from
00724         * its own superiorss
00725         */
00726        if ( sat->sat_sup ) {
00727               Syntax *syn = syn_find(sat->sat_sup->sat_syntax->ssyn_oid);
00728               if ( syn != sat->sat_sup->sat_syntax ) {
00729                      sat->sat_syntax = ch_malloc( sizeof( Syntax ));
00730                      *sat->sat_syntax = *sat->sat_sup->sat_syntax;
00731               } else {
00732                      sat->sat_syntax = sat->sat_sup->sat_syntax;
00733               }
00734               if ( sat->sat_sup->sat_equality ) {
00735                      MatchingRule *mr = mr_find( sat->sat_sup->sat_equality->smr_oid );
00736                      if ( mr != sat->sat_sup->sat_equality ) {
00737                             sat->sat_equality = ch_malloc( sizeof( MatchingRule ));
00738                             *sat->sat_equality = *sat->sat_sup->sat_equality;
00739                      } else {
00740                             sat->sat_equality = sat->sat_sup->sat_equality;
00741                      }
00742               }
00743               sat->sat_approx = sat->sat_sup->sat_approx;
00744               sat->sat_ordering = sat->sat_sup->sat_ordering;
00745               sat->sat_substr = sat->sat_sup->sat_substr;
00746        }
00747 
00748        /*
00749         * check for X-ORDERED attributes
00750         */
00751        if ( sat->sat_extensions ) {
00752               for (i=0; sat->sat_extensions[i]; i++) {
00753                      if (!strcasecmp( sat->sat_extensions[i]->lsei_name,
00754                             "X-ORDERED" ) && sat->sat_extensions[i]->lsei_values ) {
00755                             if ( !strcasecmp( sat->sat_extensions[i]->lsei_values[0],
00756                                    "VALUES" )) {
00757                                    sat->sat_flags |= SLAP_AT_ORDERED_VAL;
00758                                    break;
00759                             } else if ( !strcasecmp( sat->sat_extensions[i]->lsei_values[0],
00760                                    "SIBLINGS" )) {
00761                                    sat->sat_flags |= SLAP_AT_ORDERED_SIB;
00762                                    break;
00763                             }
00764                      }
00765               }
00766        }
00767 
00768        if ( !user )
00769               sat->sat_flags |= SLAP_AT_HARDCODE;
00770 
00771        if ( at->at_syntax_oid ) {
00772               syn = syn_find(sat->sat_syntax_oid);
00773               if ( syn == NULL ) {
00774                      *err = sat->sat_syntax_oid;
00775                      code = SLAP_SCHERR_SYN_NOT_FOUND;
00776                      goto error_return;
00777               }
00778 
00779               if ( sat->sat_syntax != NULL && sat->sat_syntax != syn ) {
00780                      /* BEWARE: no loop detection! */
00781                      if ( syn_is_sup( sat->sat_syntax, syn ) ) {
00782                             code = SLAP_SCHERR_ATTR_BAD_SUP;
00783                             goto error_return;
00784                      }
00785               }
00786 
00787               sat->sat_syntax = syn;
00788 
00789        } else if ( sat->sat_syntax == NULL ) {
00790               code = SLAP_SCHERR_ATTR_INCOMPLETE;
00791               goto error_return;
00792        }
00793 
00794        if ( sat->sat_equality_oid ) {
00795               mr = mr_find(sat->sat_equality_oid);
00796 
00797               if( mr == NULL ) {
00798                      *err = sat->sat_equality_oid;
00799                      code = SLAP_SCHERR_MR_NOT_FOUND;
00800                      goto error_return;
00801               }
00802 
00803               if(( mr->smr_usage & SLAP_MR_EQUALITY ) != SLAP_MR_EQUALITY ) {
00804                      *err = sat->sat_equality_oid;
00805                      code = SLAP_SCHERR_ATTR_BAD_MR;
00806                      goto error_return;
00807               }
00808 
00809               if( sat->sat_syntax != mr->smr_syntax ) {
00810                      if( mr->smr_compat_syntaxes == NULL ) {
00811                             *err = sat->sat_equality_oid;
00812                             code = SLAP_SCHERR_ATTR_BAD_MR;
00813                             goto error_return;
00814                      }
00815 
00816                      for(i=0; mr->smr_compat_syntaxes[i]; i++) {
00817                             if( sat->sat_syntax == mr->smr_compat_syntaxes[i] ) {
00818                                    i = -1;
00819                                    break;
00820                             }
00821                      }
00822 
00823                      if( i >= 0 ) {
00824                             *err = sat->sat_equality_oid;
00825                             code = SLAP_SCHERR_ATTR_BAD_MR;
00826                             goto error_return;
00827                      }
00828               }
00829 
00830               sat->sat_equality = mr;
00831               sat->sat_approx = mr->smr_associated;
00832        }
00833 
00834        if ( sat->sat_ordering_oid ) {
00835               if( !sat->sat_equality ) {
00836                      *err = sat->sat_ordering_oid;
00837                      code = SLAP_SCHERR_ATTR_BAD_MR;
00838                      goto error_return;
00839               }
00840 
00841               mr = mr_find(sat->sat_ordering_oid);
00842 
00843               if( mr == NULL ) {
00844                      *err = sat->sat_ordering_oid;
00845                      code = SLAP_SCHERR_MR_NOT_FOUND;
00846                      goto error_return;
00847               }
00848 
00849               if(( mr->smr_usage & SLAP_MR_ORDERING ) != SLAP_MR_ORDERING ) {
00850                      *err = sat->sat_ordering_oid;
00851                      code = SLAP_SCHERR_ATTR_BAD_MR;
00852                      goto error_return;
00853               }
00854 
00855               if( sat->sat_syntax != mr->smr_syntax ) {
00856                      if( mr->smr_compat_syntaxes == NULL ) {
00857                             *err = sat->sat_ordering_oid;
00858                             code = SLAP_SCHERR_ATTR_BAD_MR;
00859                             goto error_return;
00860                      }
00861 
00862                      for(i=0; mr->smr_compat_syntaxes[i]; i++) {
00863                             if( sat->sat_syntax == mr->smr_compat_syntaxes[i] ) {
00864                                    i = -1;
00865                                    break;
00866                             }
00867                      }
00868 
00869                      if( i >= 0 ) {
00870                             *err = sat->sat_ordering_oid;
00871                             code = SLAP_SCHERR_ATTR_BAD_MR;
00872                             goto error_return;
00873                      }
00874               }
00875 
00876               sat->sat_ordering = mr;
00877        }
00878 
00879        if ( sat->sat_substr_oid ) {
00880               if( !sat->sat_equality ) {
00881                      *err = sat->sat_substr_oid;
00882                      code = SLAP_SCHERR_ATTR_BAD_MR;
00883                      goto error_return;
00884               }
00885 
00886               mr = mr_find(sat->sat_substr_oid);
00887 
00888               if( mr == NULL ) {
00889                      *err = sat->sat_substr_oid;
00890                      code = SLAP_SCHERR_MR_NOT_FOUND;
00891                      goto error_return;
00892               }
00893 
00894               if(( mr->smr_usage & SLAP_MR_SUBSTR ) != SLAP_MR_SUBSTR ) {
00895                      *err = sat->sat_substr_oid;
00896                      code = SLAP_SCHERR_ATTR_BAD_MR;
00897                      goto error_return;
00898               }
00899 
00900               /* due to funky LDAP builtin substring rules,
00901                * we check against the equality rule assertion
00902                * syntax and compat syntaxes instead of those
00903                * associated with the substrings rule.
00904                */
00905               if( sat->sat_syntax != sat->sat_equality->smr_syntax ) {
00906                      if( sat->sat_equality->smr_compat_syntaxes == NULL ) {
00907                             *err = sat->sat_substr_oid;
00908                             code = SLAP_SCHERR_ATTR_BAD_MR;
00909                             goto error_return;
00910                      }
00911 
00912                      for(i=0; sat->sat_equality->smr_compat_syntaxes[i]; i++) {
00913                             if( sat->sat_syntax ==
00914                                    sat->sat_equality->smr_compat_syntaxes[i] )
00915                             {
00916                                    i = -1;
00917                                    break;
00918                             }
00919                      }
00920 
00921                      if( i >= 0 ) {
00922                             *err = sat->sat_substr_oid;
00923                             code = SLAP_SCHERR_ATTR_BAD_MR;
00924                             goto error_return;
00925                      }
00926               }
00927 
00928               sat->sat_substr = mr;
00929        }
00930 
00931        code = at_insert( &sat, prev, err );
00932        if ( code != 0 ) {
00933 error_return:;
00934               if ( sat ) {
00935                      ldap_pvt_thread_mutex_destroy( &sat->sat_ad_mutex );
00936                      ch_free( sat );
00937               }
00938 
00939               if ( oidm ) {
00940                      SLAP_FREE( at->at_oid );
00941                      at->at_oid = oidm;
00942               }
00943 
00944               if ( soidm ) {
00945                      SLAP_FREE( at->at_syntax_oid );
00946                      at->at_syntax_oid = soidm;
00947               }
00948 
00949        } else if ( rsat ) {
00950               *rsat = sat;
00951        }
00952 
00953        return code;
00954 }
00955 
00956 #ifdef LDAP_DEBUG
00957 #ifdef SLAPD_UNUSED
00958 static int
00959 at_index_printnode( void *v_air, void *ignore )
00960 {
00961        struct aindexrec *air = v_air;
00962        printf("%s = %s\n",
00963               air->air_name.bv_val,
00964               ldap_attributetype2str(&air->air_at->sat_atype) );
00965        return( 0 );
00966 }
00967 
00968 static void
00969 at_index_print( void )
00970 {
00971        printf("Printing attribute type index:\n");
00972        (void) avl_apply( attr_index, at_index_printnode, 0, -1, AVL_INORDER );
00973 }
00974 #endif
00975 #endif
00976 
00977 void
00978 at_unparse( BerVarray *res, AttributeType *start, AttributeType *end, int sys )
00979 {
00980        AttributeType *at;
00981        int i, num;
00982        struct berval bv, *bva = NULL, idx;
00983        char ibuf[32];
00984 
00985        if ( !start )
00986               start = LDAP_STAILQ_FIRST( &attr_list );
00987 
00988        /* count the result size */
00989        i = 0;
00990        for ( at=start; at; at=LDAP_STAILQ_NEXT(at, sat_next)) {
00991               if ( sys && !(at->sat_flags & SLAP_AT_HARDCODE)) break;
00992               i++;
00993               if ( at == end ) break;
00994        }
00995        if (!i) return;
00996 
00997        num = i;
00998        bva = ch_malloc( (num+1) * sizeof(struct berval) );
00999        BER_BVZERO( bva );
01000        idx.bv_val = ibuf;
01001        if ( sys ) {
01002               idx.bv_len = 0;
01003               ibuf[0] = '\0';
01004        }
01005        i = 0;
01006        for ( at=start; at; at=LDAP_STAILQ_NEXT(at, sat_next)) {
01007               LDAPAttributeType lat, *latp;
01008               if ( sys && !(at->sat_flags & SLAP_AT_HARDCODE)) break;
01009               if ( at->sat_oidmacro || at->sat_soidmacro ) {
01010                      lat = at->sat_atype;
01011                      if ( at->sat_oidmacro )
01012                             lat.at_oid = at->sat_oidmacro;
01013                      if ( at->sat_soidmacro )
01014                             lat.at_syntax_oid = at->sat_soidmacro;
01015                      latp = &lat;
01016               } else {
01017                      latp = &at->sat_atype;
01018               }
01019               if ( ldap_attributetype2bv( latp, &bv ) == NULL ) {
01020                      ber_bvarray_free( bva );
01021               }
01022               if ( !sys ) {
01023                      idx.bv_len = sprintf(idx.bv_val, "{%d}", i);
01024               }
01025               bva[i].bv_len = idx.bv_len + bv.bv_len;
01026               bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
01027               strcpy( bva[i].bv_val, ibuf );
01028               strcpy( bva[i].bv_val + idx.bv_len, bv.bv_val );
01029               i++;
01030               bva[i].bv_val = NULL;
01031               ldap_memfree( bv.bv_val );
01032               if ( at == end ) break;
01033        }
01034        *res = bva;
01035 }
01036 
01037 int
01038 at_schema_info( Entry *e )
01039 {
01040        AttributeDescription *ad_attributeTypes = slap_schema.si_ad_attributeTypes;
01041        AttributeType *at;
01042        struct berval val;
01043        struct berval nval;
01044 
01045        LDAP_STAILQ_FOREACH(at,&attr_list,sat_next) {
01046               if( at->sat_flags & SLAP_AT_HIDE ) continue;
01047 
01048               if ( ldap_attributetype2bv( &at->sat_atype, &val ) == NULL ) {
01049                      return -1;
01050               }
01051 
01052               ber_str2bv( at->sat_oid, 0, 0, &nval );
01053 
01054               if( attr_merge_one( e, ad_attributeTypes, &val, &nval ) )
01055               {
01056                      return -1;
01057               }
01058               ldap_memfree( val.bv_val );
01059        }
01060        return 0;
01061 }
01062 
01063 int
01064 register_at( const char *def, AttributeDescription **rad, int dupok )
01065 {
01066        LDAPAttributeType *at;
01067        int code, freeit = 0;
01068        const char *err;
01069        AttributeDescription *ad = NULL;
01070 
01071        at = ldap_str2attributetype( def, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
01072        if ( !at ) {
01073               Debug( LDAP_DEBUG_ANY,
01074                      "register_at: AttributeType \"%s\": %s, %s\n",
01075                             def, ldap_scherr2str(code), err );
01076               return code;
01077        }
01078 
01079        code = at_add( at, 0, NULL, NULL, &err );
01080        if ( code ) {
01081               if ( code == SLAP_SCHERR_ATTR_DUP && dupok ) {
01082                      freeit = 1;
01083 
01084               } else {
01085                      Debug( LDAP_DEBUG_ANY,
01086                             "register_at: AttributeType \"%s\": %s, %s\n",
01087                             def, scherr2str(code), err );
01088                      ldap_attributetype_free( at );
01089                      return code;
01090               }
01091        }
01092        code = slap_str2ad( at->at_names[0], &ad, &err );
01093        if ( freeit || code ) {
01094               ldap_attributetype_free( at );
01095        } else {
01096               ldap_memfree( at );
01097        }
01098        if ( code ) {
01099               Debug( LDAP_DEBUG_ANY, "register_at: AttributeType \"%s\": %s\n",
01100                      def, err, 0 );
01101        }
01102        if ( rad ) *rad = ad;
01103        return code;
01104 }