~ttx/openldap/lucid-gssapi-495418

« back to all changes in this revision

Viewing changes to servers/slapd/mr.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
/* mr.c - routines to manage matching rule definitions */
 
2
/* $OpenLDAP: pkg/ldap/servers/slapd/mr.c,v 1.64.2.3 2008/02/11 23:26:44 kurt 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
struct mindexrec {
 
28
        struct berval   mir_name;
 
29
        MatchingRule    *mir_mr;
 
30
};
 
31
 
 
32
static Avlnode  *mr_index = NULL;
 
33
static LDAP_SLIST_HEAD(MRList, MatchingRule) mr_list
 
34
        = LDAP_SLIST_HEAD_INITIALIZER(&mr_list);
 
35
static LDAP_SLIST_HEAD(MRUList, MatchingRuleUse) mru_list
 
36
        = LDAP_SLIST_HEAD_INITIALIZER(&mru_list);
 
37
 
 
38
static int
 
39
mr_index_cmp(
 
40
    const void  *v_mir1,
 
41
    const void  *v_mir2
 
42
)
 
43
{
 
44
        const struct mindexrec  *mir1 = v_mir1;
 
45
        const struct mindexrec  *mir2 = v_mir2;
 
46
        int i = mir1->mir_name.bv_len - mir2->mir_name.bv_len;
 
47
        if (i) return i;
 
48
        return (strcasecmp( mir1->mir_name.bv_val, mir2->mir_name.bv_val ));
 
49
}
 
50
 
 
51
static int
 
52
mr_index_name_cmp(
 
53
    const void  *v_name,
 
54
    const void  *v_mir
 
55
)
 
56
{
 
57
        const struct berval    *name = v_name;
 
58
        const struct mindexrec *mir  = v_mir;
 
59
        int i = name->bv_len - mir->mir_name.bv_len;
 
60
        if (i) return i;
 
61
        return (strncasecmp( name->bv_val, mir->mir_name.bv_val, name->bv_len ));
 
62
}
 
63
 
 
64
MatchingRule *
 
65
mr_find( const char *mrname )
 
66
{
 
67
        struct berval bv;
 
68
 
 
69
        bv.bv_val = (char *)mrname;
 
70
        bv.bv_len = strlen( mrname );
 
71
        return mr_bvfind( &bv );
 
72
}
 
73
 
 
74
MatchingRule *
 
75
mr_bvfind( struct berval *mrname )
 
76
{
 
77
        struct mindexrec        *mir = NULL;
 
78
 
 
79
        if ( (mir = avl_find( mr_index, mrname, mr_index_name_cmp )) != NULL ) {
 
80
                return( mir->mir_mr );
 
81
        }
 
82
        return( NULL );
 
83
}
 
84
 
 
85
void
 
86
mr_destroy( void )
 
87
{
 
88
        MatchingRule *m;
 
89
 
 
90
        avl_free(mr_index, ldap_memfree);
 
91
        while( !LDAP_SLIST_EMPTY(&mr_list) ) {
 
92
                m = LDAP_SLIST_FIRST(&mr_list);
 
93
                LDAP_SLIST_REMOVE_HEAD(&mr_list, smr_next);
 
94
                ch_free( m->smr_str.bv_val );
 
95
                ch_free( m->smr_compat_syntaxes );
 
96
                ldap_matchingrule_free((LDAPMatchingRule *)m);
 
97
        }
 
98
}
 
99
 
 
100
static int
 
101
mr_insert(
 
102
    MatchingRule        *smr,
 
103
    const char          **err
 
104
)
 
105
{
 
106
        struct mindexrec        *mir;
 
107
        char                    **names;
 
108
 
 
109
        LDAP_SLIST_NEXT( smr, smr_next ) = NULL;
 
110
        LDAP_SLIST_INSERT_HEAD(&mr_list, smr, smr_next);
 
111
 
 
112
        if ( smr->smr_oid ) {
 
113
                mir = (struct mindexrec *)
 
114
                        ch_calloc( 1, sizeof(struct mindexrec) );
 
115
                mir->mir_name.bv_val = smr->smr_oid;
 
116
                mir->mir_name.bv_len = strlen( smr->smr_oid );
 
117
                mir->mir_mr = smr;
 
118
                if ( avl_insert( &mr_index, (caddr_t) mir,
 
119
                                 mr_index_cmp, avl_dup_error ) ) {
 
120
                        *err = smr->smr_oid;
 
121
                        ldap_memfree(mir);
 
122
                        return SLAP_SCHERR_MR_DUP;
 
123
                }
 
124
                /* FIX: temporal consistency check */
 
125
                mr_bvfind(&mir->mir_name);
 
126
        }
 
127
        if ( (names = smr->smr_names) ) {
 
128
                while ( *names ) {
 
129
                        mir = (struct mindexrec *)
 
130
                                ch_calloc( 1, sizeof(struct mindexrec) );
 
131
                        mir->mir_name.bv_val = *names;
 
132
                        mir->mir_name.bv_len = strlen( *names );
 
133
                        mir->mir_mr = smr;
 
134
                        if ( avl_insert( &mr_index, (caddr_t) mir,
 
135
                                         mr_index_cmp, avl_dup_error ) ) {
 
136
                                *err = *names;
 
137
                                ldap_memfree(mir);
 
138
                                return SLAP_SCHERR_MR_DUP;
 
139
                        }
 
140
                        /* FIX: temporal consistency check */
 
141
                        mr_bvfind(&mir->mir_name);
 
142
                        names++;
 
143
                }
 
144
        }
 
145
        return 0;
 
146
}
 
147
 
 
148
int
 
149
mr_make_syntax_compat_with_mr(
 
150
        Syntax          *syn,
 
151
        MatchingRule    *mr )
 
152
{
 
153
        int             n = 0;
 
154
 
 
155
        assert( syn != NULL );
 
156
        assert( mr != NULL );
 
157
 
 
158
        if ( mr->smr_compat_syntaxes ) {
 
159
                /* count esisting */
 
160
                for ( n = 0;
 
161
                        mr->smr_compat_syntaxes[ n ];
 
162
                        n++ )
 
163
                {
 
164
                        if ( mr->smr_compat_syntaxes[ n ] == syn ) {
 
165
                                /* already compatible; mmmmh... */
 
166
                                return 1;
 
167
                        }
 
168
                }
 
169
        }
 
170
 
 
171
        mr->smr_compat_syntaxes = ch_realloc(
 
172
                mr->smr_compat_syntaxes,
 
173
                sizeof( Syntax * )*(n + 2) );
 
174
        mr->smr_compat_syntaxes[ n ] = syn;
 
175
        mr->smr_compat_syntaxes[ n + 1 ] = NULL;
 
176
 
 
177
        return 0;
 
178
}
 
179
 
 
180
int
 
181
mr_make_syntax_compat_with_mrs(
 
182
        const char *syntax,
 
183
        char *const *mrs )
 
184
{
 
185
        int     r, rc = 0;
 
186
        Syntax  *syn;
 
187
 
 
188
        assert( syntax != NULL );
 
189
        assert( mrs != NULL );
 
190
 
 
191
        syn = syn_find( syntax );
 
192
        if ( syn == NULL ) {
 
193
                return -1;
 
194
        }
 
195
 
 
196
        for ( r = 0; mrs[ r ] != NULL; r++ ) {
 
197
                MatchingRule    *mr = mr_find( mrs[ r ] );
 
198
                if ( mr == NULL ) {
 
199
                        /* matchingRule not found -- ignore by now */
 
200
                        continue;
 
201
                }
 
202
 
 
203
                rc += mr_make_syntax_compat_with_mr( syn, mr );
 
204
        }
 
205
 
 
206
        return rc;
 
207
}
 
208
 
 
209
int
 
210
mr_add(
 
211
    LDAPMatchingRule            *mr,
 
212
    slap_mrule_defs_rec *def,
 
213
        MatchingRule    *amr,
 
214
    const char          **err
 
215
)
 
216
{
 
217
        MatchingRule    *smr;
 
218
        Syntax          *syn;
 
219
        Syntax          **compat_syn = NULL;
 
220
        int             code;
 
221
 
 
222
        if( def->mrd_compat_syntaxes ) {
 
223
                int i;
 
224
                for( i=0; def->mrd_compat_syntaxes[i]; i++ ) {
 
225
                        /* just count em */
 
226
                }
 
227
 
 
228
                compat_syn = ch_malloc( sizeof(Syntax *) * (i+1) );
 
229
 
 
230
                for( i=0; def->mrd_compat_syntaxes[i]; i++ ) {
 
231
                        compat_syn[i] = syn_find( def->mrd_compat_syntaxes[i] );
 
232
                        if( compat_syn[i] == NULL ) {
 
233
                                ch_free( compat_syn );
 
234
                                return SLAP_SCHERR_SYN_NOT_FOUND;
 
235
                        }
 
236
                }
 
237
 
 
238
                compat_syn[i] = NULL;
 
239
        }
 
240
 
 
241
        smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) );
 
242
        AC_MEMCPY( &smr->smr_mrule, mr, sizeof(LDAPMatchingRule));
 
243
 
 
244
        /*
 
245
         * note: smr_bvoid uses the same memory of smr_mrule.mr_oid;
 
246
         * smr_oidlen is #defined as smr_bvoid.bv_len
 
247
         */
 
248
        smr->smr_bvoid.bv_val = smr->smr_mrule.mr_oid;
 
249
        smr->smr_oidlen = strlen( mr->mr_oid );
 
250
        smr->smr_usage = def->mrd_usage;
 
251
        smr->smr_compat_syntaxes = compat_syn;
 
252
        smr->smr_normalize = def->mrd_normalize;
 
253
        smr->smr_match = def->mrd_match;
 
254
        smr->smr_indexer = def->mrd_indexer;
 
255
        smr->smr_filter = def->mrd_filter;
 
256
        smr->smr_associated = amr;
 
257
 
 
258
        if ( smr->smr_syntax_oid ) {
 
259
                if ( (syn = syn_find(smr->smr_syntax_oid)) ) {
 
260
                        smr->smr_syntax = syn;
 
261
                } else {
 
262
                        *err = smr->smr_syntax_oid;
 
263
                        ch_free( smr );
 
264
                        return SLAP_SCHERR_SYN_NOT_FOUND;
 
265
                }
 
266
        } else {
 
267
                *err = "";
 
268
                ch_free( smr );
 
269
                return SLAP_SCHERR_MR_INCOMPLETE;
 
270
        }
 
271
        code = mr_insert(smr,err);
 
272
        return code;
 
273
}
 
274
 
 
275
int
 
276
register_matching_rule(
 
277
        slap_mrule_defs_rec *def )
 
278
{
 
279
        LDAPMatchingRule *mr;
 
280
        MatchingRule *amr = NULL;
 
281
        int             code;
 
282
        const char      *err;
 
283
 
 
284
        if( def->mrd_usage == SLAP_MR_NONE && def->mrd_compat_syntaxes == NULL ) {
 
285
                Debug( LDAP_DEBUG_ANY, "register_matching_rule: not usable %s\n",
 
286
                    def->mrd_desc, 0, 0 );
 
287
 
 
288
                return -1;
 
289
        }
 
290
 
 
291
        if( def->mrd_associated != NULL ) {
 
292
                amr = mr_find( def->mrd_associated );
 
293
                if( amr == NULL ) {
 
294
                        Debug( LDAP_DEBUG_ANY, "register_matching_rule: "
 
295
                                "could not locate associated matching rule %s for %s\n",
 
296
                                def->mrd_associated, def->mrd_desc, 0 );
 
297
 
 
298
                        return -1;
 
299
                }
 
300
 
 
301
                if (( def->mrd_usage & SLAP_MR_EQUALITY ) &&
 
302
                        (( def->mrd_usage & SLAP_MR_SUBTYPE_MASK ) == SLAP_MR_NONE ))
 
303
                {
 
304
                        if (( def->mrd_usage & SLAP_MR_EQUALITY ) &&
 
305
                                (( def->mrd_usage & SLAP_MR_SUBTYPE_MASK ) != SLAP_MR_NONE ))
 
306
                        {
 
307
                                Debug( LDAP_DEBUG_ANY, "register_matching_rule: "
 
308
                                                "inappropriate (approx) association %s for %s\n",
 
309
                                        def->mrd_associated, def->mrd_desc, 0 );
 
310
                                return -1;
 
311
                        }
 
312
 
 
313
                } else if (!( amr->smr_usage & SLAP_MR_EQUALITY )) {
 
314
                                Debug( LDAP_DEBUG_ANY, "register_matching_rule: "
 
315
                                        "inappropriate (equalilty) association %s for %s\n",
 
316
                                        def->mrd_associated, def->mrd_desc, 0 );
 
317
                                return -1;
 
318
                }
 
319
        }
 
320
 
 
321
        mr = ldap_str2matchingrule( def->mrd_desc, &code, &err,
 
322
                LDAP_SCHEMA_ALLOW_ALL );
 
323
        if ( !mr ) {
 
324
                Debug( LDAP_DEBUG_ANY,
 
325
                        "Error in register_matching_rule: %s before %s in %s\n",
 
326
                    ldap_scherr2str(code), err, def->mrd_desc );
 
327
 
 
328
                return -1;
 
329
        }
 
330
 
 
331
 
 
332
        code = mr_add( mr, def, amr, &err );
 
333
 
 
334
        ldap_memfree( mr );
 
335
 
 
336
        if ( code ) {
 
337
                Debug( LDAP_DEBUG_ANY,
 
338
                        "Error in register_matching_rule: %s for %s in %s\n",
 
339
                    scherr2str(code), err, def->mrd_desc );
 
340
 
 
341
                return -1;
 
342
        }
 
343
 
 
344
        return 0;
 
345
}
 
346
 
 
347
void
 
348
mru_destroy( void )
 
349
{
 
350
        MatchingRuleUse *m;
 
351
 
 
352
        while( !LDAP_SLIST_EMPTY(&mru_list) ) {
 
353
                m = LDAP_SLIST_FIRST(&mru_list);
 
354
                LDAP_SLIST_REMOVE_HEAD(&mru_list, smru_next);
 
355
 
 
356
                if ( m->smru_str.bv_val ) {
 
357
                        ch_free( m->smru_str.bv_val );
 
358
                        m->smru_str.bv_val = NULL;
 
359
                }
 
360
                /* memory borrowed from m->smru_mr */
 
361
                m->smru_oid = NULL;
 
362
                m->smru_names = NULL;
 
363
                m->smru_desc = NULL;
 
364
 
 
365
                /* free what's left (basically smru_mruleuse.mru_applies_oids) */
 
366
                ldap_matchingruleuse_free((LDAPMatchingRuleUse *)m);
 
367
        }
 
368
}
 
369
 
 
370
int
 
371
matching_rule_use_init( void )
 
372
{
 
373
        MatchingRule    *mr;
 
374
        MatchingRuleUse **mru_ptr = &LDAP_SLIST_FIRST(&mru_list);
 
375
 
 
376
        Debug( LDAP_DEBUG_TRACE, "matching_rule_use_init\n", 0, 0, 0 );
 
377
 
 
378
        LDAP_SLIST_FOREACH( mr, &mr_list, smr_next ) {
 
379
                AttributeType   *at;
 
380
                MatchingRuleUse mru_storage = { 0 },
 
381
                                *mru = &mru_storage;
 
382
 
 
383
                char            **applies_oids = NULL;
 
384
 
 
385
                mr->smr_mru = NULL;
 
386
 
 
387
                /* hide rules marked as HIDE */
 
388
                if ( mr->smr_usage & SLAP_MR_HIDE ) {
 
389
                        continue;
 
390
                }
 
391
 
 
392
                /* hide rules not marked as designed for extensibility */
 
393
                /* MR_EXT means can be used any attribute type whose
 
394
                 * syntax is same as the assertion syntax.
 
395
                 * Another mechanism is needed where rule can be used
 
396
                 * with attribute of other syntaxes.
 
397
                 * Framework doesn't support this (yet).
 
398
                 */
 
399
 
 
400
                if (!( ( mr->smr_usage & SLAP_MR_EXT )
 
401
                        || mr->smr_compat_syntaxes ) )
 
402
                {
 
403
                        continue;
 
404
                }
 
405
 
 
406
                /*
 
407
                 * Note: we're using the same values of the corresponding 
 
408
                 * MatchingRule structure; maybe we'd copy them ...
 
409
                 */
 
410
                mru->smru_mr = mr;
 
411
                mru->smru_obsolete = mr->smr_obsolete;
 
412
                mru->smru_applies_oids = NULL;
 
413
                LDAP_SLIST_NEXT(mru, smru_next) = NULL;
 
414
                mru->smru_oid = mr->smr_oid;
 
415
                mru->smru_names = mr->smr_names;
 
416
                mru->smru_desc = mr->smr_desc;
 
417
 
 
418
                Debug( LDAP_DEBUG_TRACE, "    %s (%s): ", 
 
419
                                mru->smru_oid, 
 
420
                                mru->smru_names ? mru->smru_names[ 0 ] : "", 0 );
 
421
 
 
422
                at = NULL;
 
423
                for ( at_start( &at ); at; at_next( &at ) ) {
 
424
                        if( at->sat_flags & SLAP_AT_HIDE ) continue;
 
425
 
 
426
                        if( mr_usable_with_at( mr, at )) {
 
427
                                ldap_charray_add( &applies_oids, at->sat_cname.bv_val );
 
428
                        }
 
429
                }
 
430
 
 
431
                /*
 
432
                 * Note: the matchingRules that are not used
 
433
                 * by any attributeType are not listed as
 
434
                 * matchingRuleUse
 
435
                 */
 
436
                if ( applies_oids != NULL ) {
 
437
                        mru->smru_applies_oids = applies_oids;
 
438
                        {
 
439
                                char *str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
 
440
                                Debug( LDAP_DEBUG_TRACE, "matchingRuleUse: %s\n", str, 0, 0 );
 
441
                                ldap_memfree( str );
 
442
                        }
 
443
 
 
444
                        mru = (MatchingRuleUse *)ber_memalloc( sizeof( MatchingRuleUse ) );
 
445
                        /* call-forward from MatchingRule to MatchingRuleUse */
 
446
                        mr->smr_mru = mru;
 
447
                        /* copy static data to newly allocated struct */
 
448
                        *mru = mru_storage;
 
449
                        /* append the struct pointer to the end of the list */
 
450
                        *mru_ptr = mru;
 
451
                        /* update the list head pointer */
 
452
                        mru_ptr = &LDAP_SLIST_NEXT(mru,smru_next);
 
453
                }
 
454
        }
 
455
 
 
456
        return( 0 );
 
457
}
 
458
 
 
459
int
 
460
mr_usable_with_at(
 
461
        MatchingRule    *mr,
 
462
        AttributeType   *at )
 
463
{
 
464
        if ( ( mr->smr_usage & SLAP_MR_EXT ) && (
 
465
                mr->smr_syntax == at->sat_syntax ||
 
466
                mr == at->sat_equality ||
 
467
                mr == at->sat_approx ||
 
468
                syn_is_sup( at->sat_syntax, mr->smr_syntax ) ) )
 
469
        {
 
470
                return 1;
 
471
        }
 
472
 
 
473
        if ( mr->smr_compat_syntaxes ) {
 
474
                int i;
 
475
                for( i=0; mr->smr_compat_syntaxes[i]; i++ ) {
 
476
                        if( at->sat_syntax == mr->smr_compat_syntaxes[i] ) {
 
477
                                return 1;
 
478
                        }
 
479
                }
 
480
        }
 
481
        return 0;
 
482
}
 
483
 
 
484
int mr_schema_info( Entry *e )
 
485
{
 
486
        AttributeDescription *ad_matchingRules = slap_schema.si_ad_matchingRules;
 
487
        MatchingRule *mr;
 
488
        struct berval nval;
 
489
 
 
490
        LDAP_SLIST_FOREACH(mr, &mr_list, smr_next ) {
 
491
                if ( mr->smr_usage & SLAP_MR_HIDE ) {
 
492
                        /* skip hidden rules */
 
493
                        continue;
 
494
                }
 
495
 
 
496
                if ( ! mr->smr_match ) {
 
497
                        /* skip rules without matching functions */
 
498
                        continue;
 
499
                }
 
500
 
 
501
                if ( mr->smr_str.bv_val == NULL ) {
 
502
                        if ( ldap_matchingrule2bv( &mr->smr_mrule, &mr->smr_str ) == NULL ) {
 
503
                                return -1;
 
504
                        }
 
505
                }
 
506
#if 0
 
507
                Debug( LDAP_DEBUG_TRACE, "Merging mr [%lu] %s\n",
 
508
                        mr->smr_str.bv_len, mr->smr_str.bv_val, 0 );
 
509
#endif
 
510
 
 
511
                nval.bv_val = mr->smr_oid;
 
512
                nval.bv_len = strlen(mr->smr_oid);
 
513
                if( attr_merge_one( e, ad_matchingRules, &mr->smr_str, &nval ) ) {
 
514
                        return -1;
 
515
                }
 
516
        }
 
517
        return 0;
 
518
}
 
519
 
 
520
int mru_schema_info( Entry *e )
 
521
{
 
522
        AttributeDescription *ad_matchingRuleUse 
 
523
                = slap_schema.si_ad_matchingRuleUse;
 
524
        MatchingRuleUse *mru;
 
525
        struct berval nval;
 
526
 
 
527
        LDAP_SLIST_FOREACH( mru, &mru_list, smru_next ) {
 
528
                assert( !( mru->smru_usage & SLAP_MR_HIDE ) );
 
529
 
 
530
                if ( mru->smru_str.bv_val == NULL ) {
 
531
                        if ( ldap_matchingruleuse2bv( &mru->smru_mruleuse, &mru->smru_str )
 
532
                                        == NULL ) {
 
533
                                return -1;
 
534
                        }
 
535
                }
 
536
 
 
537
#if 0
 
538
                Debug( LDAP_DEBUG_TRACE, "Merging mru [%lu] %s\n",
 
539
                        mru->smru_str.bv_len, mru->smru_str.bv_val, 0 );
 
540
#endif
 
541
 
 
542
                nval.bv_val = mru->smru_oid;
 
543
                nval.bv_len = strlen(mru->smru_oid);
 
544
                if( attr_merge_one( e, ad_matchingRuleUse, &mru->smru_str, &nval ) ) {
 
545
                        return -1;
 
546
                }
 
547
        }
 
548
        return 0;
 
549
}