~ttx/openldap/lucid-gssapi-495418

« back to all changes in this revision

Viewing changes to servers/slapd/oc.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2008-07-10 14:45:49 UTC
  • Revision ID: james.westby@ubuntu.com-20080710144549-wck73med0e72gfyo
Tags: upstream-2.4.10
ImportĀ upstreamĀ versionĀ 2.4.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}