Back to index

openldap  2.4.31
cr.c
Go to the documentation of this file.
00001 /* cr.c - content rule routines */
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/string.h>
00023 #include <ac/socket.h>
00024 
00025 #include "slap.h"
00026 
00027 struct cindexrec {
00028        struct berval cir_name;
00029        ContentRule   *cir_cr;
00030 };
00031 
00032 static Avlnode       *cr_index = NULL;
00033 static LDAP_STAILQ_HEAD(CRList, ContentRule) cr_list
00034        = LDAP_STAILQ_HEAD_INITIALIZER(cr_list);
00035 
00036 static int
00037 cr_index_cmp(
00038     const void       *v_cir1,
00039     const void       *v_cir2 )
00040 {
00041        const struct cindexrec      *cir1 = v_cir1;
00042        const struct cindexrec      *cir2 = v_cir2;
00043        int i = cir1->cir_name.bv_len - cir2->cir_name.bv_len;
00044        if (i) return i;
00045        return strcasecmp( cir1->cir_name.bv_val, cir2->cir_name.bv_val );
00046 }
00047 
00048 static int
00049 cr_index_name_cmp(
00050     const void       *v_name,
00051     const void       *v_cir )
00052 {
00053        const struct berval    *name = v_name;
00054        const struct cindexrec *cir  = v_cir;
00055        int i = name->bv_len - cir->cir_name.bv_len;
00056        if (i) return i;
00057        return strncasecmp( name->bv_val, cir->cir_name.bv_val, name->bv_len );
00058 }
00059 
00060 ContentRule *
00061 cr_find( const char *crname )
00062 {
00063        struct berval bv;
00064 
00065        bv.bv_val = (char *)crname;
00066        bv.bv_len = strlen( crname );
00067 
00068        return( cr_bvfind( &bv ) );
00069 }
00070 
00071 ContentRule *
00072 cr_bvfind( struct berval *crname )
00073 {
00074        struct cindexrec     *cir;
00075 
00076        cir = avl_find( cr_index, crname, cr_index_name_cmp );
00077 
00078        if ( cir != NULL ) {
00079               return( cir->cir_cr );
00080        }
00081 
00082        return( NULL );
00083 }
00084 
00085 static int
00086 cr_destroy_one( ContentRule *c )
00087 {
00088        assert( c != NULL );
00089 
00090        if (c->scr_auxiliaries) ldap_memfree(c->scr_auxiliaries);
00091        if (c->scr_required) ldap_memfree(c->scr_required);
00092        if (c->scr_allowed) ldap_memfree(c->scr_allowed);
00093        if (c->scr_precluded) ldap_memfree(c->scr_precluded);
00094        ldap_contentrule_free((LDAPContentRule *)c);
00095 
00096        return 0;
00097 }
00098 
00099 void
00100 cr_destroy( void )
00101 {
00102        ContentRule *c;
00103 
00104        avl_free(cr_index, ldap_memfree);
00105 
00106        while( !LDAP_STAILQ_EMPTY(&cr_list) ) {
00107               c = LDAP_STAILQ_FIRST(&cr_list);
00108               LDAP_STAILQ_REMOVE_HEAD(&cr_list, scr_next);
00109 
00110               cr_destroy_one( c );
00111        }
00112 }
00113 
00114 static int
00115 cr_insert(
00116     ContentRule             *scr,
00117     const char              **err
00118 )
00119 {
00120        struct cindexrec     *cir;
00121        char                 **names;
00122 
00123        assert( scr != NULL );
00124 
00125        if ( scr->scr_oid ) {
00126               cir = (struct cindexrec *)
00127                      ch_calloc( 1, sizeof(struct cindexrec) );
00128               cir->cir_name.bv_val = scr->scr_oid;
00129               cir->cir_name.bv_len = strlen( scr->scr_oid );
00130               cir->cir_cr = scr;
00131 
00132               if ( avl_insert( &cr_index, (caddr_t) cir,
00133                                cr_index_cmp, avl_dup_error ) )
00134               {
00135                      *err = scr->scr_oid;
00136                      ldap_memfree(cir);
00137                      return SLAP_SCHERR_CR_DUP;
00138               }
00139 
00140               /* FIX: temporal consistency check */
00141               assert( cr_bvfind(&cir->cir_name) != NULL );
00142        }
00143 
00144        if ( (names = scr->scr_names) ) {
00145               while ( *names ) {
00146                      cir = (struct cindexrec *)
00147                             ch_calloc( 1, sizeof(struct cindexrec) );
00148                      cir->cir_name.bv_val = *names;
00149                      cir->cir_name.bv_len = strlen( *names );
00150                      cir->cir_cr = scr;
00151 
00152                      if ( avl_insert( &cr_index, (caddr_t) cir,
00153                                       cr_index_cmp, avl_dup_error ) )
00154                      {
00155                             *err = *names;
00156                             ldap_memfree(cir);
00157                             return SLAP_SCHERR_CR_DUP;
00158                      }
00159 
00160                      /* FIX: temporal consistency check */
00161                      assert( cr_bvfind(&cir->cir_name) != NULL );
00162 
00163                      names++;
00164               }
00165        }
00166 
00167        LDAP_STAILQ_INSERT_TAIL(&cr_list, scr, scr_next);
00168 
00169        return 0;
00170 }
00171 
00172 static int
00173 cr_add_auxiliaries(
00174     ContentRule             *scr,
00175        int                  *op,
00176     const char              **err )
00177 {
00178        int naux;
00179 
00180        if( scr->scr_oc_oids_aux == NULL ) return 0;
00181        
00182        for( naux=0; scr->scr_oc_oids_aux[naux]; naux++ ) {
00183               /* count them */ ;
00184        }
00185 
00186        scr->scr_auxiliaries = ch_calloc( naux+1, sizeof(ObjectClass *));
00187 
00188        for( naux=0; scr->scr_oc_oids_aux[naux]; naux++ ) {
00189               ObjectClass *soc = scr->scr_auxiliaries[naux]
00190                      = oc_find(scr->scr_oc_oids_aux[naux]);
00191               if ( !soc ) {
00192                      *err = scr->scr_oc_oids_aux[naux];
00193                      return SLAP_SCHERR_CLASS_NOT_FOUND;
00194               }
00195 
00196               if( soc->soc_flags & SLAP_OC_OPERATIONAL &&
00197                      soc != slap_schema.si_oc_extensibleObject )
00198               {
00199                      (*op)++;
00200               }
00201 
00202               if( soc->soc_kind != LDAP_SCHEMA_AUXILIARY ) {
00203                      *err = scr->scr_oc_oids_aux[naux];
00204                      return SLAP_SCHERR_CR_BAD_AUX;
00205               }
00206        }
00207 
00208        scr->scr_auxiliaries[naux] = NULL;
00209        return 0;
00210 }
00211 
00212 static int
00213 cr_create_required(
00214     ContentRule             *scr,
00215        int                  *op,
00216     const char              **err )
00217 {
00218     char             **attrs = scr->scr_at_oids_must;
00219        char          **attrs1;
00220        AttributeType *sat;
00221 
00222        if ( attrs ) {
00223               attrs1 = attrs;
00224               while ( *attrs1 ) {
00225                      sat = at_find(*attrs1);
00226                      if ( !sat ) {
00227                             *err = *attrs1;
00228                             return SLAP_SCHERR_ATTR_NOT_FOUND;
00229                      }
00230 
00231                      if( is_at_operational( sat )) (*op)++;
00232 
00233                      if ( at_find_in_list(sat, scr->scr_required) < 0) {
00234                             if ( at_append_to_list(sat, &scr->scr_required) ) {
00235                                    *err = *attrs1;
00236                                    return SLAP_SCHERR_OUTOFMEM;
00237                             }
00238                      } else {
00239                             *err = *attrs1;
00240                             return SLAP_SCHERR_CR_BAD_AT;
00241                      }
00242                      attrs1++;
00243               }
00244        }
00245        return 0;
00246 }
00247 
00248 static int
00249 cr_create_allowed(
00250     ContentRule             *scr,
00251        int                  *op,
00252     const char              **err )
00253 {
00254     char             **attrs = scr->scr_at_oids_may;
00255        char          **attrs1;
00256        AttributeType *sat;
00257 
00258        if ( attrs ) {
00259               attrs1 = attrs;
00260               while ( *attrs1 ) {
00261                      sat = at_find(*attrs1);
00262                      if ( !sat ) {
00263                             *err = *attrs1;
00264                             return SLAP_SCHERR_ATTR_NOT_FOUND;
00265                      }
00266 
00267                      if( is_at_operational( sat )) (*op)++;
00268 
00269                      if ( at_find_in_list(sat, scr->scr_required) < 0 &&
00270                             at_find_in_list(sat, scr->scr_allowed) < 0 )
00271                      {
00272                             if ( at_append_to_list(sat, &scr->scr_allowed) ) {
00273                                    *err = *attrs1;
00274                                    return SLAP_SCHERR_OUTOFMEM;
00275                             }
00276                      } else {
00277                             *err = *attrs1;
00278                             return SLAP_SCHERR_CR_BAD_AT;
00279                      }
00280                      attrs1++;
00281               }
00282        }
00283        return 0;
00284 }
00285 
00286 static int
00287 cr_create_precluded(
00288     ContentRule             *scr,
00289        int                  *op,
00290     const char              **err )
00291 {
00292     char             **attrs = scr->scr_at_oids_not;
00293        char          **attrs1;
00294        AttributeType *sat;
00295 
00296        if ( attrs ) {
00297               attrs1 = attrs;
00298               while ( *attrs1 ) {
00299                      sat = at_find(*attrs1);
00300                      if ( !sat ) {
00301                             *err = *attrs1;
00302                             return SLAP_SCHERR_ATTR_NOT_FOUND;
00303                      }
00304 
00305                      if( is_at_operational( sat )) (*op)++;
00306 
00307                      /* FIXME: should also make sure attribute type is not
00308                             a required attribute of the structural class or
00309                             any auxiliary class */
00310                      if ( at_find_in_list(sat, scr->scr_required) < 0 &&
00311                             at_find_in_list(sat, scr->scr_allowed) < 0 &&
00312                             at_find_in_list(sat, scr->scr_precluded) < 0 )
00313                      {
00314                             if ( at_append_to_list(sat, &scr->scr_precluded) ) {
00315                                    *err = *attrs1;
00316                                    return SLAP_SCHERR_OUTOFMEM;
00317                             }
00318                      } else {
00319                             *err = *attrs1;
00320                             return SLAP_SCHERR_CR_BAD_AT;
00321                      }
00322                      attrs1++;
00323               }
00324        }
00325        return 0;
00326 }
00327 
00328 int
00329 cr_add(
00330     LDAPContentRule  *cr,
00331        int user,
00332        ContentRule **rscr,
00333     const char              **err
00334 )
00335 {
00336        ContentRule   *scr;
00337        int           code;
00338        int           op = 0;
00339        char   *oidm = NULL;
00340 
00341        if ( cr->cr_names != NULL ) {
00342               int i;
00343 
00344               for( i=0; cr->cr_names[i]; i++ ) {
00345                      if( !slap_valid_descr( cr->cr_names[i] ) ) {
00346                             return SLAP_SCHERR_BAD_DESCR;
00347                      }
00348               }
00349        }
00350 
00351        if ( !OID_LEADCHAR( cr->cr_oid[0] )) {
00352               /* Expand OID macros */
00353               char *oid = oidm_find( cr->cr_oid );
00354               if ( !oid ) {
00355                      *err = cr->cr_oid;
00356                      return SLAP_SCHERR_OIDM;
00357               }
00358               if ( oid != cr->cr_oid ) {
00359                      oidm = cr->cr_oid;
00360                      cr->cr_oid = oid;
00361               }
00362        }
00363 
00364        scr = (ContentRule *) ch_calloc( 1, sizeof(ContentRule) );
00365        AC_MEMCPY( &scr->scr_crule, cr, sizeof(LDAPContentRule) );
00366 
00367        scr->scr_oidmacro = oidm;
00368        scr->scr_sclass = oc_find(cr->cr_oid);
00369        if ( !scr->scr_sclass ) {
00370               *err = cr->cr_oid;
00371               code = SLAP_SCHERR_CLASS_NOT_FOUND;
00372               goto fail;
00373        }
00374 
00375        /* check object class usage */
00376        if( scr->scr_sclass->soc_kind != LDAP_SCHEMA_STRUCTURAL )
00377        {
00378               *err = cr->cr_oid;
00379               code = SLAP_SCHERR_CR_BAD_STRUCT;
00380               goto fail;
00381        }
00382 
00383        if( scr->scr_sclass->soc_flags & SLAP_OC_OPERATIONAL ) op++;
00384 
00385        code = cr_add_auxiliaries( scr, &op, err );
00386        if ( code != 0 ) goto fail;
00387 
00388        code = cr_create_required( scr, &op, err );
00389        if ( code != 0 ) goto fail;
00390 
00391        code = cr_create_allowed( scr, &op, err );
00392        if ( code != 0 ) goto fail;
00393 
00394        code = cr_create_precluded( scr, &op, err );
00395        if ( code != 0 ) goto fail;
00396 
00397        if( user && op ) {
00398               code = SLAP_SCHERR_CR_BAD_AUX;
00399               goto fail;
00400        }
00401 
00402        code = cr_insert(scr,err);
00403        if ( code == 0 && rscr )
00404               *rscr = scr;
00405        return code;
00406 fail:
00407        ch_free( scr );
00408        return code;
00409 }
00410 
00411 void
00412 cr_unparse( BerVarray *res, ContentRule *start, ContentRule *end, int sys )
00413 {
00414        ContentRule *cr;
00415        int i, num;
00416        struct berval bv, *bva = NULL, idx;
00417        char ibuf[32];
00418 
00419        if ( !start )
00420               start = LDAP_STAILQ_FIRST( &cr_list );
00421 
00422        /* count the result size */
00423        i = 0;
00424        for ( cr=start; cr; cr=LDAP_STAILQ_NEXT(cr, scr_next)) {
00425               if ( sys && !(cr->scr_flags & SLAP_CR_HARDCODE)) continue;
00426               i++;
00427               if ( cr == end ) break;
00428        }
00429        if (!i) return;
00430 
00431        num = i;
00432        bva = ch_malloc( (num+1) * sizeof(struct berval) );
00433        BER_BVZERO( bva );
00434        idx.bv_val = ibuf;
00435        if ( sys ) {
00436               idx.bv_len = 0;
00437               ibuf[0] = '\0';
00438        }
00439        i = 0;
00440        for ( cr=start; cr; cr=LDAP_STAILQ_NEXT(cr, scr_next)) {
00441               LDAPContentRule lcr, *lcrp;
00442               if ( sys && !(cr->scr_flags & SLAP_CR_HARDCODE)) continue;
00443               if ( cr->scr_oidmacro ) {
00444                      lcr = cr->scr_crule;
00445                      lcr.cr_oid = cr->scr_oidmacro;
00446                      lcrp = &lcr;
00447               } else {
00448                      lcrp = &cr->scr_crule;
00449               }
00450               if ( ldap_contentrule2bv( lcrp, &bv ) == NULL ) {
00451                      ber_bvarray_free( bva );
00452               }
00453               if ( !sys ) {
00454                      idx.bv_len = sprintf(idx.bv_val, "{%d}", i);
00455               }
00456               bva[i].bv_len = idx.bv_len + bv.bv_len;
00457               bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
00458               strcpy( bva[i].bv_val, ibuf );
00459               strcpy( bva[i].bv_val + idx.bv_len, bv.bv_val );
00460               i++;
00461               bva[i].bv_val = NULL;
00462               ldap_memfree( bv.bv_val );
00463               if ( cr == end ) break;
00464        }
00465        *res = bva;
00466 }
00467 
00468 int
00469 cr_schema_info( Entry *e )
00470 {
00471        AttributeDescription *ad_ditContentRules
00472               = slap_schema.si_ad_ditContentRules;
00473        ContentRule   *cr;
00474 
00475        struct berval val;
00476        struct berval nval;
00477 
00478        LDAP_STAILQ_FOREACH(cr, &cr_list, scr_next) {
00479               if ( ldap_contentrule2bv( &cr->scr_crule, &val ) == NULL ) {
00480                      return -1;
00481               }
00482 
00483 #if 0
00484               if( cr->scr_flags & SLAP_CR_HIDE ) continue;
00485 #endif
00486 #if 0
00487               Debug( LDAP_DEBUG_TRACE, "Merging cr [%ld] %s\n",
00488               (long) val.bv_len, val.bv_val, 0 );
00489 #endif
00490 
00491               nval.bv_val = cr->scr_oid;
00492               nval.bv_len = strlen(cr->scr_oid);
00493 
00494               if( attr_merge_one( e, ad_ditContentRules, &val, &nval ) )
00495               {
00496                      return -1;
00497               }
00498               ldap_memfree( val.bv_val );
00499        }
00500        return 0;
00501 }