~ttx/openldap/lucid-gssapi-495418

« back to all changes in this revision

Viewing changes to contrib/slapd-modules/allowed/allowed.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2009-09-07 13:41:10 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20090907134110-rsnlhy8b0r21p9bg
Tags: 2.4.18-0ubuntu1
* New upstream release: (LP: #419515):
  + pcache overlay supports disconnected mode.
* Fix nss overlay load (LP: #417163).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* allowed.c - add allowed attributes based on ACL */
 
2
/* $OpenLDAP: pkg/ldap/contrib/slapd-modules/allowed/allowed.c,v 1.3.2.2 2009/08/25 19:59:12 quanah Exp $ */
 
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 
4
 *
 
5
 * Copyright 2006-2009 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
/* ACKNOWLEDGEMENTS:
 
17
 * This work was initially developed by Pierangelo Masarati for inclusion in
 
18
 * OpenLDAP Software.
 
19
 */
 
20
 
 
21
/*
 
22
 * Rationale: return in allowedAttributes the attributes required/allowed
 
23
 * by the objectClasses that are currently present in an object; return
 
24
 * in allowedAttributesEffective the subset of the above that can be written
 
25
 * by the identity that performs the search.
 
26
 *
 
27
 * Caveats:
 
28
 * - right now, the overlay assumes that all values of the objectClass
 
29
 *   attribute will be returned in rs->sr_entry; this may not be true
 
30
 *   in general, but it usually is for back-bdb/back-hdb.  To generalize,
 
31
 *   the search request should be analyzed, and if allowedAttributes or
 
32
 *   allowedAttributesEffective are requested, add objectClass to the
 
33
 *   requested attributes
 
34
 * - it assumes that there is no difference between write-add and 
 
35
 *   write-delete
 
36
 * - it assumes that access rules do not depend on the values of the 
 
37
 *   attributes or on the contents of the entry (attr/val, filter, ...)
 
38
 *   allowedAttributes and allowedAttributesEffective cannot be used
 
39
 *   in filters or in compare
 
40
 */
 
41
 
 
42
#include "portable.h"
 
43
 
 
44
/* define SLAPD_OVER_ALLOWED=2 to build as run-time loadable module */
 
45
#ifdef SLAPD_OVER_ALLOWED
 
46
 
 
47
#include "slap.h"
 
48
 
 
49
/*
 
50
 * Schema from
 
51
 *
 
52
 * <http://www.redhat.com/archives/fedora-directory-devel/2006-August/msg00007.html>
 
53
 *
 
54
 * posted by Andrew Bartlett
 
55
 */
 
56
 
 
57
#define AA_SCHEMA_AT "1.2.840.113556.1.4"
 
58
 
 
59
static AttributeDescription
 
60
                *ad_allowedChildClasses,
 
61
                *ad_allowedChildClassesEffective,
 
62
                *ad_allowedAttributes,
 
63
                *ad_allowedAttributesEffective;
 
64
 
 
65
static struct {
 
66
        char *at;
 
67
        AttributeDescription **ad;
 
68
} aa_attrs[] = {
 
69
        { "( " AA_SCHEMA_AT ".911 "
 
70
                "NAME 'allowedChildClasses' "
 
71
                "EQUALITY objectIdentifierMatch "
 
72
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
 
73
                /* added by me :) */
 
74
                "DESC 'Child classes allowed for a given object' "
 
75
                "NO-USER-MODIFICATION "
 
76
                "USAGE directoryOperation )", &ad_allowedChildClasses },
 
77
        { "( " AA_SCHEMA_AT ".912 "
 
78
                "NAME 'allowedChildClassesEffective' "
 
79
                "EQUALITY objectIdentifierMatch "
 
80
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
 
81
                /* added by me :) */
 
82
                "DESC 'Child classes allowed for a given object according to ACLs' "
 
83
                "NO-USER-MODIFICATION "
 
84
                "USAGE directoryOperation )", &ad_allowedChildClassesEffective },
 
85
        { "( " AA_SCHEMA_AT ".913 "
 
86
                "NAME 'allowedAttributes' "
 
87
                "EQUALITY objectIdentifierMatch "
 
88
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
 
89
                /* added by me :) */
 
90
                "DESC 'Attributes allowed for a given object' "
 
91
                "NO-USER-MODIFICATION "
 
92
                "USAGE directoryOperation )", &ad_allowedAttributes },
 
93
        { "( " AA_SCHEMA_AT ".914 "
 
94
                "NAME 'allowedAttributesEffective' "
 
95
                "EQUALITY objectIdentifierMatch "
 
96
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
 
97
                /* added by me :) */
 
98
                "DESC 'Attributes allowed for a given object according to ACLs' "
 
99
                "NO-USER-MODIFICATION "
 
100
                "USAGE directoryOperation )", &ad_allowedAttributesEffective },
 
101
 
 
102
        /* TODO: add objectClass stuff? */
 
103
 
 
104
        { NULL, NULL }
 
105
};
 
106
 
 
107
static int
 
108
aa_add_at( AttributeType *at, AttributeType ***atpp )
 
109
{
 
110
        int             i = 0;
 
111
 
 
112
        if ( *atpp ) {
 
113
                for ( i = 0; (*atpp)[ i ] != NULL; i++ ) {
 
114
                        if ( (*atpp)[ i ] == at ) {
 
115
                                break;
 
116
                        }
 
117
                }
 
118
        
 
119
                if ( (*atpp)[ i ] != NULL ) {
 
120
                        return 0;
 
121
                }
 
122
        }
 
123
 
 
124
        *atpp = ch_realloc( *atpp, sizeof( AttributeType * ) * ( i + 2 ) );
 
125
        (*atpp)[ i ] = at;
 
126
        (*atpp)[ i + 1 ] = NULL;
 
127
 
 
128
        return 0;
 
129
}
 
130
 
 
131
static int
 
132
aa_add_oc( ObjectClass *oc, ObjectClass ***ocpp, AttributeType ***atpp )
 
133
{
 
134
        int             i = 0;
 
135
 
 
136
        if ( *ocpp ) {
 
137
                for ( ; (*ocpp)[ i ] != NULL; i++ ) {
 
138
                        if ( (*ocpp)[ i ] == oc ) {
 
139
                                break;
 
140
                        }
 
141
                }
 
142
 
 
143
                if ( (*ocpp)[ i ] != NULL ) {
 
144
                        return 0;
 
145
                }
 
146
        }
 
147
 
 
148
        *ocpp = ch_realloc( *ocpp, sizeof( ObjectClass * ) * ( i + 2 ) );
 
149
        (*ocpp)[ i ] = oc;
 
150
        (*ocpp)[ i + 1 ] = NULL;
 
151
 
 
152
        if ( oc->soc_required ) {
 
153
                int             i;
 
154
 
 
155
                for ( i = 0; oc->soc_required[ i ] != NULL; i++ ) {
 
156
                        aa_add_at( oc->soc_required[ i ], atpp );
 
157
                }
 
158
        }
 
159
 
 
160
        if ( oc->soc_allowed ) {
 
161
                int             i;
 
162
 
 
163
                for ( i = 0; oc->soc_allowed[ i ] != NULL; i++ ) {
 
164
                        aa_add_at( oc->soc_allowed[ i ], atpp );
 
165
                }
 
166
        }
 
167
 
 
168
        return 0;
 
169
}
 
170
 
 
171
static int
 
172
aa_operational( Operation *op, SlapReply *rs )
 
173
{
 
174
        Attribute               *a, **ap;
 
175
        AccessControlState      acl_state = ACL_STATE_INIT;
 
176
        struct berval           *v;
 
177
        AttributeType           **atp = NULL;
 
178
        ObjectClass             **ocp = NULL;
 
179
        BerVarray               bv_allowed = NULL,
 
180
                                bv_effective = NULL;
 
181
        int                     i, ja = 0, je = 0;
 
182
 
 
183
#define GOT_NONE        (0x0U)
 
184
#define GOT_C           (0x1U)
 
185
#define GOT_CE          (0x2U)
 
186
#define GOT_A           (0x4U)
 
187
#define GOT_AE          (0x8U)
 
188
#define GOT_ALL         (GOT_C|GOT_CE|GOT_A|GOT_AE)
 
189
        int             got = GOT_NONE;
 
190
 
 
191
        /* only add if requested */
 
192
        if ( SLAP_OPATTRS( rs->sr_attr_flags ) ) {
 
193
                got = GOT_ALL;
 
194
 
 
195
        } else {
 
196
                if ( ad_inlist( ad_allowedChildClasses, rs->sr_attrs ) ) {
 
197
                        got |= GOT_C;
 
198
                }
 
199
 
 
200
                if ( ad_inlist( ad_allowedChildClassesEffective, rs->sr_attrs ) ) {
 
201
                        got |= GOT_CE;
 
202
                }
 
203
 
 
204
                if ( ad_inlist( ad_allowedAttributes, rs->sr_attrs ) ) {
 
205
                        got |= GOT_A;
 
206
                }
 
207
 
 
208
                if ( ad_inlist( ad_allowedAttributesEffective, rs->sr_attrs ) ) {
 
209
                        got |= GOT_AE;
 
210
                }
 
211
        }
 
212
 
 
213
        if ( got == GOT_NONE ) {
 
214
                return SLAP_CB_CONTINUE;
 
215
        }
 
216
 
 
217
        /* shouldn't be called without an entry; please check */
 
218
        assert( rs->sr_entry != NULL );
 
219
 
 
220
        /* see caveats; this is not guaranteed for all backends */
 
221
        a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_objectClass );
 
222
        if ( a == NULL ) {
 
223
                return SLAP_CB_CONTINUE;
 
224
        }
 
225
 
 
226
        /* if client has no access to objectClass attribute; don't compute */
 
227
        if ( !access_allowed( op, rs->sr_entry, slap_schema.si_ad_objectClass,
 
228
                                NULL, ACL_READ, &acl_state ) )
 
229
        {
 
230
                return SLAP_CB_CONTINUE;
 
231
        }
 
232
 
 
233
        for ( v = a->a_nvals; !BER_BVISNULL( v ); v++ ) {
 
234
                ObjectClass     *oc = oc_bvfind( v );
 
235
 
 
236
                assert( oc != NULL );
 
237
 
 
238
                /* if client has no access to specific value, don't compute */
 
239
                if ( !access_allowed( op, rs->sr_entry,
 
240
                        slap_schema.si_ad_objectClass,
 
241
                        &oc->soc_cname, ACL_READ, &acl_state ) )
 
242
                {
 
243
                        continue;
 
244
                }
 
245
 
 
246
                aa_add_oc( oc, &ocp, &atp );
 
247
 
 
248
                if ( oc->soc_sups ) {
 
249
                        for ( i = 0; oc->soc_sups[ i ] != NULL; i++ ) {
 
250
                                aa_add_oc( oc->soc_sups[ i ], &ocp, &atp );
 
251
                        }
 
252
                }
 
253
        }
 
254
 
 
255
        if ( atp != NULL ) {
 
256
                for ( i = 0; atp[ i ] != NULL; i++ )
 
257
                        /* just count */ ;
 
258
        
 
259
                if ( got & GOT_A ) {
 
260
                        bv_allowed = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
 
261
                }
 
262
                if ( got & GOT_AE ) {
 
263
                        bv_effective = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
 
264
                }
 
265
 
 
266
                for ( i = 0, ja = 0, je = 0; atp[ i ] != NULL; i++ ) {
 
267
                        if ( got & GOT_A ) {
 
268
                                ber_dupbv( &bv_allowed[ ja ], &atp[ i ]->sat_cname );
 
269
                                ja++;
 
270
                        }
 
271
 
 
272
                        if ( got & GOT_AE ) {
 
273
                                AttributeDescription    *ad = NULL;
 
274
                                const char              *text = NULL;
 
275
        
 
276
                                if ( slap_bv2ad( &atp[ i ]->sat_cname, &ad, &text ) ) {
 
277
                                        /* log? */
 
278
                                        continue;
 
279
                                }
 
280
 
 
281
                                if ( access_allowed( op, rs->sr_entry,
 
282
                                        ad, NULL, ACL_WRITE, NULL ) )
 
283
                                {
 
284
                                        ber_dupbv( &bv_effective[ je ], &atp[ i ]->sat_cname );
 
285
                                        je++;
 
286
                                }
 
287
                        }
 
288
                }
 
289
 
 
290
                for ( ap = &rs->sr_operational_attrs; *ap != NULL; ap = &(*ap)->a_next )
 
291
                        /* go to last */ ;
 
292
 
 
293
                if ( ( got & GOT_A ) && ja > 0 ) {
 
294
                        BER_BVZERO( &bv_allowed[ ja ] );
 
295
                        *ap = attr_alloc( ad_allowedAttributes );
 
296
                        (*ap)->a_vals = bv_allowed;
 
297
                        (*ap)->a_nvals = bv_allowed;
 
298
                        (*ap)->a_numvals = ja;
 
299
                        ap = &(*ap)->a_next;
 
300
                }
 
301
        
 
302
                if ( ( got & GOT_AE ) && je > 0 ) {
 
303
                        BER_BVZERO( &bv_effective[ je ] );
 
304
                        *ap = attr_alloc( ad_allowedAttributesEffective );
 
305
                        (*ap)->a_vals = bv_effective;
 
306
                        (*ap)->a_nvals = bv_effective;
 
307
                        (*ap)->a_numvals = je;
 
308
                        ap = &(*ap)->a_next;
 
309
                }
 
310
        
 
311
                *ap = NULL;
 
312
        }
 
313
 
 
314
        ch_free( atp );
 
315
        ch_free( ocp );
 
316
 
 
317
        return SLAP_CB_CONTINUE;
 
318
}
 
319
 
 
320
static slap_overinst aa;
 
321
 
 
322
#if LDAP_VENDOR_VERSION_MINOR != X && LDAP_VENDOR_VERSION_MINOR <= 3
 
323
/* backport register_at() from HEAD, to allow building with OL <= 2.3 */
 
324
static int
 
325
register_at( char *def, AttributeDescription **rad, int dupok )
 
326
{
 
327
        LDAPAttributeType *at;
 
328
        int code, freeit = 0;
 
329
        const char *err;
 
330
        AttributeDescription *ad = NULL;
 
331
 
 
332
        at = ldap_str2attributetype( def, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
 
333
        if ( !at ) {
 
334
                Debug( LDAP_DEBUG_ANY,
 
335
                        "register_at: AttributeType \"%s\": %s, %s\n",
 
336
                                def, ldap_scherr2str(code), err );
 
337
                return code;
 
338
        }
 
339
 
 
340
        code = at_add( at, 0, NULL, &err );
 
341
        if ( code ) {
 
342
                if ( code == SLAP_SCHERR_ATTR_DUP && dupok ) {
 
343
                        freeit = 1;
 
344
 
 
345
                } else {
 
346
                        ldap_attributetype_free( at );
 
347
                        Debug( LDAP_DEBUG_ANY,
 
348
                                "register_at: AttributeType \"%s\": %s, %s\n",
 
349
                                def, scherr2str(code), err );
 
350
                        return code;
 
351
                }
 
352
        }
 
353
        code = slap_str2ad( at->at_names[0], &ad, &err );
 
354
        if ( freeit || code ) {
 
355
                ldap_attributetype_free( at );
 
356
        } else {
 
357
                ldap_memfree( at );
 
358
        }
 
359
        if ( code ) {
 
360
                Debug( LDAP_DEBUG_ANY, "register_at: AttributeType \"%s\": %s\n",
 
361
                        def, err, 0 );
 
362
        }
 
363
        if ( rad ) *rad = ad;
 
364
        return code;
 
365
}
 
366
#endif
 
367
 
 
368
#if SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC
 
369
static
 
370
#endif /* SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC */
 
371
int
 
372
aa_initialize( void )
 
373
{
 
374
        int i;
 
375
 
 
376
        aa.on_bi.bi_type = "allowed";
 
377
 
 
378
        aa.on_bi.bi_operational = aa_operational;
 
379
 
 
380
        /* aa schema integration */
 
381
        for ( i = 0; aa_attrs[i].at; i++ ) {
 
382
                int code;
 
383
 
 
384
                code = register_at( aa_attrs[i].at, aa_attrs[i].ad, 0 );
 
385
                if ( code ) {
 
386
                        Debug( LDAP_DEBUG_ANY,
 
387
                                "aa_initialize: register_at failed\n", 0, 0, 0 );
 
388
                        return -1;
 
389
                }
 
390
        }
 
391
 
 
392
        return overlay_register( &aa );
 
393
}
 
394
 
 
395
#if SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC
 
396
int
 
397
init_module( int argc, char *argv[] )
 
398
{
 
399
        return aa_initialize();
 
400
}
 
401
#endif /* SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC */
 
402
 
 
403
#endif /* SLAPD_OVER_ALLOWED */