~ubuntu-branches/ubuntu/saucy/389-ds-base/saucy

« back to all changes in this revision

Viewing changes to .pc/fix-cve-2012-4450.diff/ldap/servers/plugins/acl/acl.c

  • Committer: Package Import Robot
  • Author(s): Timo Aaltonen
  • Date: 2013-02-06 18:06:31 UTC
  • mfrom: (11.1.1 raring-proposed)
  • Revision ID: package-import@ubuntu.com-20130206180631-h6ldv3k506hmm46e
Tags: 1.3.0.2-0ubuntu2
debian/*: Fix time stamps due to clock skew (FTBFS).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/** BEGIN COPYRIGHT BLOCK
2
 
 * This Program is free software; you can redistribute it and/or modify it under
3
 
 * the terms of the GNU General Public License as published by the Free Software
4
 
 * Foundation; version 2 of the License.
5
 
 * 
6
 
 * This Program is distributed in the hope that it will be useful, but WITHOUT
7
 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8
 
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9
 
 * 
10
 
 * You should have received a copy of the GNU General Public License along with
11
 
 * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
12
 
 * Place, Suite 330, Boston, MA 02111-1307 USA.
13
 
 * 
14
 
 * In addition, as a special exception, Red Hat, Inc. gives You the additional
15
 
 * right to link the code of this Program with code not covered under the GNU
16
 
 * General Public License ("Non-GPL Code") and to distribute linked combinations
17
 
 * including the two, subject to the limitations in this paragraph. Non-GPL Code
18
 
 * permitted under this exception must only link to the code of this Program
19
 
 * through those well defined interfaces identified in the file named EXCEPTION
20
 
 * found in the source code files (the "Approved Interfaces"). The files of
21
 
 * Non-GPL Code may instantiate templates or use macros or inline functions from
22
 
 * the Approved Interfaces without causing the resulting work to be covered by
23
 
 * the GNU General Public License. Only Red Hat, Inc. may make changes or
24
 
 * additions to the list of Approved Interfaces. You must obey the GNU General
25
 
 * Public License in all respects for all of the Program code and other code used
26
 
 * in conjunction with the Program except the Non-GPL Code covered by this
27
 
 * exception. If you modify this file, you may extend this exception to your
28
 
 * version of the file, but you are not obligated to do so. If you do not wish to
29
 
 * provide this exception without modification, you must delete this exception
30
 
 * statement from your version and license this file solely under the GPL without
31
 
 * exception. 
32
 
 * 
33
 
 * 
34
 
 * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
35
 
 * Copyright (C) 2005 Red Hat, Inc.
36
 
 * All rights reserved.
37
 
 * END COPYRIGHT BLOCK **/
38
 
 
39
 
#ifdef HAVE_CONFIG_H
40
 
#  include <config.h>
41
 
#endif
42
 
 
43
 
#include        "acl.h"
44
 
 
45
 
/****************************************************************************
46
 
*
47
 
* acl.c
48
 
*
49
 
*
50
 
*       This file contains the functions related to Access Control List (ACL)
51
 
*       checking. The ACL checking is based on the ONE ACL design implemented
52
 
*       in the Web server 2.0. For more information on the ACL design look
53
 
*       into the barracuda home page.
54
 
*
55
 
*
56
 
******************************************************************************/
57
 
 
58
 
 
59
 
/****************************************************************************/
60
 
/*      Globals. Must be protected by Mutex.                                */
61
 
/****************************************************************************/
62
 
/* Signatures to see if things have changed */
63
 
static  short   acl_signature = 0;
64
 
 
65
 
/****************************************************************************/
66
 
/* Defines, Constants, ande Declarations                                    */
67
 
/****************************************************************************/
68
 
static char *ds_map_generic[2] = { NULL, NULL };
69
 
 
70
 
/****************************************************************************/
71
 
/* prototypes                                                               */
72
 
/****************************************************************************/
73
 
static  int     acl__resource_match_aci(struct acl_pblock *aclpb, aci_t *aci ,
74
 
                                                                int skip_attrEval, int *a_matched);
75
 
static  int acl__TestRights(Acl_PBlock *aclpb,int access, char **right,
76
 
                                                char ** map_generic, aclResultReason_t *result_reason);
77
 
static int      acl__scan_for_acis(struct acl_pblock *aclpb, int *err);
78
 
static void     acl__reset_cached_result (struct acl_pblock *aclpb );
79
 
static int      acl__scan_match_handles ( struct acl_pblock *aclpb, int type);
80
 
static int      acl__attr_cached_result (struct acl_pblock *aclpb, char *attr, int access );
81
 
static int      acl__match_handlesFromCache (struct acl_pblock *aclpb, char *attr, int access);
82
 
static int      acl__get_attrEval ( struct acl_pblock *aclpb, char *attr );
83
 
static int      acl__recompute_acl (Acl_PBlock *aclpb, AclAttrEval *a_eval,
84
 
                                                                        int     access, int     aciIndex);
85
 
static void     __acl_set_aclIndex_inResult ( Acl_PBlock *aclpb,
86
 
                                                                                                int access, int index );
87
 
static int      acl__make_filter_test_entry ( Slapi_Entry **entry,
88
 
                                                                        char *attr_type, struct berval *attr_val);
89
 
static int      acl__test_filter ( Slapi_Entry *entry, struct slapi_filter *f,
90
 
                                                         int filter_sense);
91
 
static void print_access_control_summary( char * source,
92
 
                                                                        int ret_val, char *clientDn,
93
 
                                                                        struct  acl_pblock      *aclpb,
94
 
                                                                        char *right,
95
 
                                                                        char *attr,
96
 
                                                                        const char *edn,
97
 
                                                                        aclResultReason_t *acl_reason);
98
 
static int check_rdn_access( Slapi_PBlock *pb, Slapi_Entry *e, 
99
 
                             const char * newrdn, int access);
100
 
 
101
 
 
102
 
/*
103
 
 * Check the rdn permissions for this entry:
104
 
 *      require: write access to the entry, write (add) access to the new
105
 
 * naming attribute, write (del) access to the old naming attribute if
106
 
 * deleteoldrdn set.
107
 
 *
108
 
 * Valid only for the modrdn operation.
109
 
*/
110
 
int
111
 
acl_access_allowed_modrdn(
112
 
        Slapi_PBlock        *pb,
113
 
        Slapi_Entry         *e,                 /* The Slapi_Entry */
114
 
        char                            *attr,          /* Attribute of the entry */
115
 
        struct berval       *val,               /* value of attr. NOT USED */
116
 
        int                 access              /* requested access rights */
117
 
        )
118
 
{
119
 
        int retCode ;
120
 
        char *newrdn;
121
 
        char *ci_newrdn;
122
 
        const char *oldrdn;
123
 
        Slapi_DN *target_sdn = NULL;
124
 
        int deleteoldrdn = 0;
125
 
 
126
 
        /*
127
 
         * First check write permission on the entry--this is actually
128
 
         * specially for modrdn.
129
 
         */
130
 
        retCode = acl_access_allowed ( pb, e, NULL /* attr */, NULL /* val */,
131
 
                                                                        SLAPI_ACL_WRITE);
132
 
 
133
 
        if ( retCode != LDAP_SUCCESS ) {
134
 
                slapi_log_error( SLAPI_LOG_ACL, plugin_name,
135
 
                                                        "modrdn:write permission to entry not allowed\n");
136
 
                return(retCode);
137
 
        }
138
 
 
139
 
        /* Now get the new rdn attribute name and value */
140
 
        slapi_pblock_get( pb, SLAPI_MODRDN_TARGET_SDN, &target_sdn );
141
 
        slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &newrdn );
142
 
 
143
 
        ci_newrdn = slapi_ch_strdup(newrdn);
144
 
        slapi_dn_ignore_case(ci_newrdn);
145
 
        /* Check can add the new naming attribute */
146
 
        retCode = check_rdn_access( pb, e, ci_newrdn, ACLPB_SLAPI_ACL_WRITE_ADD) ;
147
 
        slapi_ch_free_string(&ci_newrdn);
148
 
        if ( retCode != LDAP_SUCCESS ) {
149
 
                slapi_log_error( SLAPI_LOG_ACL, plugin_name,
150
 
                        "modrdn:write permission to add new naming attribute not allowed\n");
151
 
                return(retCode);
152
 
        }
153
 
 
154
 
        /* Check can delete the new naming attribute--if required */
155
 
        slapi_pblock_get( pb, SLAPI_MODRDN_DELOLDRDN, &deleteoldrdn );
156
 
        if ( deleteoldrdn ) {
157
 
                oldrdn = slapi_sdn_get_ndn(target_sdn);
158
 
                retCode = check_rdn_access( pb, e, oldrdn, ACLPB_SLAPI_ACL_WRITE_DEL) ;
159
 
                if ( retCode != LDAP_SUCCESS ) {
160
 
                        slapi_log_error( SLAPI_LOG_ACL, plugin_name,
161
 
                                "modrdn:write permission to delete old naming attribute not allowed\n");
162
 
                        return(retCode);
163
 
                }
164
 
        }
165
 
 
166
 
        return(retCode);
167
 
 
168
 
}
169
 
/*
170
 
 * Test if have access to make the first rdn of dn in entry e.
171
 
*/
172
 
 
173
 
static int check_rdn_access( Slapi_PBlock *pb, Slapi_Entry *e, const char *dn,
174
 
                                                int access) {
175
 
        
176
 
        char **dns;
177
 
        char **rdns;
178
 
        int retCode = LDAP_INSUFFICIENT_ACCESS;
179
 
        int i;
180
 
 
181
 
        if ( (dns = slapi_ldap_explode_dn( dn, 0 )) != NULL ) {
182
 
 
183
 
                if ( (rdns = slapi_ldap_explode_rdn( dns[0], 0 )) != NULL ) {
184
 
        
185
 
                        for ( i = 0; rdns[i] != NULL; i++ ) {
186
 
                                char *type;                     
187
 
                                struct berval bv;
188
 
                        
189
 
                                if ( slapi_rdn2typeval( rdns[i], &type, &bv ) != 0 ) {
190
 
                                slapi_log_error( SLAPI_LOG_ACL, plugin_name,
191
 
                                                        "modrdn: rdn2typeval (%s) failed\n", rdns[i]);
192
 
                                        retCode = LDAP_INSUFFICIENT_ACCESS;
193
 
                                        break;                  
194
 
                                } else {
195
 
                                        if ( (retCode = acl_access_allowed ( pb, e, type /* attr */,
196
 
                                                                                                        &bv /* val */,
197
 
                                                                                                        access)) != LDAP_SUCCESS) {
198
 
                                                break;
199
 
                                        }
200
 
                                }                       
201
 
                        }
202
 
                        slapi_ldap_value_free( rdns );
203
 
                }
204
 
                slapi_ldap_value_free( dns );
205
 
        }
206
 
 
207
 
        return(retCode);
208
 
}
209
 
 
210
 
/***************************************************************************
211
 
*
212
 
* acl_access_allowed
213
 
*       Determines if access to the resource is allowed or not.
214
 
*
215
 
* Input:
216
 
*                                       
217
 
*
218
 
* Returns:
219
 
*
220
 
*       Returns success/Denied/error condition
221
 
*
222
 
*       LDAP_SUCCESS                    -- access allowed
223
 
*       LDAP_INSUFFICIENT_ACCESS        -- access denied
224
 
*
225
 
*       Errors returned:
226
 
*
227
 
*       Some of the definition of the return values used copied from
228
 
*       "ldap.h" for convienience.
229
 
*               LDAP_OPERATIONS_ERROR
230
 
*               LDAP_PROTOCOL_ERROR
231
 
*               LDAP_UNWILLING_TO_PERFORM
232
 
*
233
 
*
234
 
* Error Handling:
235
 
*               Returned error code.
236
 
**************************************************************************/
237
 
int
238
 
acl_access_allowed(
239
 
        Slapi_PBlock        *pb,
240
 
        Slapi_Entry         *e,                 /* The Slapi_Entry */
241
 
        char                            *attr,          /* Attribute of the entry */
242
 
        struct berval       *val,               /* value of attr */
243
 
        int                 access              /* requested access rights */
244
 
        )
245
 
{
246
 
        char                            *n_edn;         /*  Normalized DN of the entry */
247
 
        int                                     rv;
248
 
        int                                     err;
249
 
        int                                     ret_val;
250
 
        char                            *right;
251
 
        struct  acl_pblock      *aclpb = NULL;
252
 
        AclAttrEval                     *c_attrEval = NULL;
253
 
        int                                     got_reader_locked = 0;
254
 
        int                                     deallocate_attrEval = 0;
255
 
        char                            *clientDn;
256
 
        Slapi_DN                        *e_sdn;
257
 
        Slapi_Operation         *op = NULL;
258
 
        aclResultReason_t       decision_reason;
259
 
        int                                     loglevel;
260
 
 
261
 
        loglevel = slapi_is_loglevel_set(SLAPI_LOG_ACL) ? SLAPI_LOG_ACL : SLAPI_LOG_ACLSUMMARY;
262
 
        slapi_pblock_get(pb, SLAPI_OPERATION, &op); /* for logging */
263
 
 
264
 
        TNF_PROBE_1_DEBUG(acl_access_allowed_start,"ACL","",
265
 
                                                tnf_int,access,access);
266
 
 
267
 
        decision_reason.deciding_aci = NULL;
268
 
        decision_reason.reason = ACL_REASON_NONE;
269
 
 
270
 
        /**
271
 
         * First, if the acl private write/delete on attribute right
272
 
         * is requested, turn this into SLAPI_ACL_WRITE
273
 
         * and record the original value.
274
 
     * Need to make sure that these rights do not clash with the SLAPI
275
 
     * public rights.  This should be easy as the requested rights
276
 
     * in the aclpb are stored in the bottom byte of aclpb_res_type,
277
 
     * so if we keep the ACL private bits here too we make sure
278
 
     * not to clash.
279
 
     *
280
 
        */
281
 
 
282
 
        if ( access & (ACLPB_SLAPI_ACL_WRITE_ADD | ACLPB_SLAPI_ACL_WRITE_DEL) ) {
283
 
                access |= SLAPI_ACL_WRITE;
284
 
        }
285
 
 
286
 
        n_edn = slapi_entry_get_ndn ( e );
287
 
        e_sdn = slapi_entry_get_sdn ( e );
288
 
 
289
 
        /* Check if this is a write operation and the database is readonly */
290
 
        /* No one, even the rootdn should be allowed to write to the database */
291
 
        /* jcm: ReadOnly only applies to the public backends, the private ones */
292
 
        /* (the DSEs) should still be writable for configuration. */
293
 
        if ( access & ( SLAPI_ACL_WRITE | SLAPI_ACL_ADD  | SLAPI_ACL_DELETE )) {
294
 
                int                     be_readonly, privateBackend;
295
 
                Slapi_Backend           *be;
296
 
 
297
 
                slapi_pblock_get ( pb, SLAPI_BE_READONLY, &be_readonly );
298
 
                slapi_pblock_get ( pb, SLAPI_BACKEND, &be );
299
 
                privateBackend = slapi_be_private ( be );
300
 
 
301
 
                 if (  !privateBackend && (be_readonly ||  slapi_config_get_readonly () )){
302
 
                        slapi_log_error (loglevel, plugin_name,
303
 
                                "conn=%" NSPRIu64 " op=%d (main): Deny %s on entry(%s)"
304
 
                                ": readonly backend\n",
305
 
                                 op->o_connid, op->o_opid,
306
 
                                acl_access2str(access),
307
 
                                n_edn);
308
 
                        return LDAP_UNWILLING_TO_PERFORM;
309
 
                }
310
 
        }
311
 
        
312
 
        /* Check for things we need to skip */
313
 
        TNF_PROBE_0_DEBUG(acl_skipaccess_start,"ACL","");
314
 
        if (  acl_skip_access_check ( pb, e )) {
315
 
                slapi_log_error (loglevel,      plugin_name,
316
 
                                "conn=%" NSPRIu64 " op=%d (main): Allow %s on entry(%s)"
317
 
                                ": root user\n",
318
 
                                op->o_connid, op->o_opid,
319
 
                                acl_access2str(access),
320
 
                                n_edn);
321
 
                return(LDAP_SUCCESS);
322
 
        }
323
 
        TNF_PROBE_0_DEBUG(acl_skipaccess_end,"ACL","");
324
 
 
325
 
 
326
 
        /* Get the bindDN (normalized & case-ignored) */
327
 
        slapi_pblock_get ( pb, SLAPI_REQUESTOR_DN, &clientDn );
328
 
 
329
 
        /* Initialize aclpb */
330
 
        aclplugin_preop_common( pb );
331
 
 
332
 
        /* get the right acl pblock  to work with */
333
 
        if ( access & SLAPI_ACL_PROXY )
334
 
                aclpb = acl_get_aclpb ( pb, ACLPB_PROXYDN_PBLOCK );
335
 
        else
336
 
                aclpb = acl_get_aclpb ( pb, ACLPB_BINDDN_PBLOCK );
337
 
 
338
 
        if ( !aclpb ) {
339
 
                slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,  "Missing aclpb 1 \n" );
340
 
                ret_val = LDAP_OPERATIONS_ERROR;
341
 
                goto cleanup_and_ret;
342
 
        }
343
 
 
344
 
        if ( !aclpb->aclpb_curr_entry_sdn ) {
345
 
                slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,  "NULL aclpb_curr_entry_sdn \n" );
346
 
                ret_val = LDAP_OPERATIONS_ERROR;
347
 
                goto cleanup_and_ret;
348
 
        }
349
 
 
350
 
        /* check if aclpb is initialized or not */
351
 
        TNF_PROBE_0_DEBUG(acl_aclpbinit_start,"ACL","");
352
 
        acl_init_aclpb ( pb, aclpb, clientDn, 0 );
353
 
        TNF_PROBE_0_DEBUG(acl_aclpbinit_end,"ACL","");
354
 
 
355
 
        /* Here we mean if "I am trying to add/delete "myself" to a group, etc." We
356
 
         * basically just want to see if the value matches the DN of the user that
357
 
         * we're checking access for */
358
 
        if (val &&  (access & SLAPI_ACL_WRITE) && (val->bv_len > 0)) {
359
 
                Slapi_Attr *sa = slapi_attr_new();
360
 
                char *oid = NULL;
361
 
 
362
 
                slapi_attr_init(sa, attr);
363
 
                slapi_attr_get_syntax_oid_copy(sa, &oid);
364
 
  
365
 
                /* We only want to perform this check if the attribute is
366
 
                 * defined using the DN or Name And Optional UID syntaxes. */
367
 
                if (oid && ((strcasecmp(oid, DN_SYNTAX_OID) == 0) ||
368
 
                            (strcasecmp(oid, NAMEANDOPTIONALUID_SYNTAX_OID) == 0))) { 
369
 
                        /* should use slapi_sdn_compare() but that'a an extra malloc/free */
370
 
                        char *dn_val_to_write = slapi_create_dn_string("%s", val->bv_val);
371
 
                        if ( dn_val_to_write && aclpb->aclpb_authorization_sdn && 
372
 
                                        slapi_utf8casecmp((ACLUCHP)dn_val_to_write, (ACLUCHP)
373
 
                                        slapi_sdn_get_ndn(aclpb->aclpb_authorization_sdn)) == 0) { 
374
 
                                access |= SLAPI_ACL_SELF;
375
 
                        } 
376
 
        
377
 
                        slapi_ch_free_string(&dn_val_to_write);
378
 
                }
379
 
 
380
 
                slapi_ch_free_string(&oid);
381
 
                slapi_attr_free(&sa);
382
 
        }
383
 
 
384
 
        /* Convert access to string of rights eg SLAPI_ACL_ADD->"add". */
385
 
        if ((right= acl_access2str(access)) == NULL) {
386
 
                /* ERROR: unknown rights */
387
 
                slapi_log_error(SLAPI_LOG_ACL, plugin_name,
388
 
                                "acl_access_allowed unknown rights:%d\n", access);
389
 
 
390
 
                ret_val = LDAP_OPERATIONS_ERROR;
391
 
                goto cleanup_and_ret;
392
 
        }
393
 
 
394
 
        
395
 
        /*
396
 
         * Am I a anonymous dude ? then we can use our anonymous profile
397
 
         * We don't require the aclpb to have been initialized for anom stuff
398
 
         *
399
 
        */
400
 
        TNF_PROBE_0_DEBUG(acl_anon_test_start,"ACL","");
401
 
        if ( (access & (SLAPI_ACL_SEARCH | SLAPI_ACL_READ )) &&
402
 
                                                                                (clientDn && *clientDn == '\0')) {
403
 
                aclanom_get_suffix_info(e, aclpb);
404
 
                ret_val = aclanom_match_profile ( pb, aclpb, e, attr, access );
405
 
                if (ret_val != -1 ) {
406
 
                        if (ret_val == LDAP_SUCCESS ) {
407
 
                                decision_reason.reason = ACL_REASON_ANON_ALLOWED;
408
 
                        } else if (ret_val == LDAP_INSUFFICIENT_ACCESS) {
409
 
                                decision_reason.reason = ACL_REASON_ANON_DENIED;
410
 
                        }
411
 
                        goto cleanup_and_ret;
412
 
                }
413
 
        }
414
 
        TNF_PROBE_0_DEBUG(acl_anon_test_end,"ACL","");
415
 
        
416
 
    /* copy the value into the aclpb for later checking by the value acl code */
417
 
 
418
 
    aclpb->aclpb_curr_attrVal = val;
419
 
 
420
 
        if (!(aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_LIST) &&
421
 
                (access & SLAPI_ACL_SEARCH)) {
422
 
                /* We are evaluating SEARCH right for the entry. After that
423
 
                ** we will eval the READ right. We need to refresh  the
424
 
                ** list of acls selected for evaluation for the entry.
425
 
                ** Initialize the array so that we indicate nothing has been
426
 
                ** selected.
427
 
                */
428
 
                aclpb->aclpb_handles_index[0] = -1;
429
 
                /* access is not allowed on entry for search -- it's for 
430
 
                ** read only.
431
 
                */
432
 
                aclpb->aclpb_state &= ~ACLPB_ACCESS_ALLOWED_ON_ENTRY;
433
 
        }
434
 
 
435
 
        /* set that this is a new entry */
436
 
        aclpb->aclpb_res_type |= ACLPB_NEW_ENTRY;
437
 
        aclpb->aclpb_access = 0;
438
 
        aclpb->aclpb_access |= access; 
439
 
 
440
 
        /*
441
 
         * stub the Slapi_Entry info  first time and only it has changed
442
 
         * or if the pblock is a psearch pblock--in this case the lifetime
443
 
         * of entries associated with psearches is such that we cannot cache
444
 
         * pointers to them--we must always start afresh (see psearch.c).
445
 
        */ 
446
 
        slapi_pblock_get( pb, SLAPI_OPERATION, &op);
447
 
        if ( operation_is_flag_set(op, OP_FLAG_PS) ||
448
 
                 (aclpb->aclpb_curr_entry_sdn == NULL) ||
449
 
                 (slapi_sdn_compare ( aclpb->aclpb_curr_entry_sdn, e_sdn) != 0) ||
450
 
                 (aclpb->aclpb_curr_entry != e) /* cannot trust the cached entry */ ) {
451
 
                TNF_PROBE_0_DEBUG(acl_entry_first_touch_start,"ACL","");
452
 
 
453
 
                slapi_log_error(loglevel, plugin_name,
454
 
                        "#### conn=%" NSPRIu64 " op=%d binddn=\"%s\"\n",
455
 
                        op->o_connid, op->o_opid, clientDn);
456
 
                aclpb->aclpb_stat_total_entries++;
457
 
 
458
 
                if (!(access & SLAPI_ACL_PROXY) &&
459
 
                                                        !( aclpb->aclpb_state & ACLPB_DONOT_EVALUATE_PROXY )) {
460
 
                                Acl_PBlock *proxy_pb;
461
 
 
462
 
                        proxy_pb = acl_get_aclpb( pb, ACLPB_PROXYDN_PBLOCK );
463
 
                        if (proxy_pb) {
464
 
                                TNF_PROBE_0_DEBUG(acl_access_allowed_proxy_start,"ACL","");
465
 
                                ret_val = acl_access_allowed( pb, e, attr, val, SLAPI_ACL_PROXY );
466
 
                                TNF_PROBE_0_DEBUG(acl_access_allowed_proxy_end,"ACL","");
467
 
 
468
 
                                if (ret_val != LDAP_SUCCESS) goto cleanup_and_ret;
469
 
                        }
470
 
                }
471
 
                if ( access & SLAPI_ACL_SEARCH)  {
472
 
                        aclpb->aclpb_num_entries++;
473
 
 
474
 
                        if ( aclpb->aclpb_num_entries == 1) {
475
 
                                aclpb->aclpb_state |= ACLPB_COPY_EVALCONTEXT;
476
 
                        } else if ( aclpb->aclpb_state & ACLPB_COPY_EVALCONTEXT ) {     
477
 
                                /* We need to copy the evalContext */
478
 
                                acl_copyEval_context ( aclpb, &aclpb->aclpb_curr_entryEval_context,
479
 
                                                        &aclpb->aclpb_prev_entryEval_context, 0 );
480
 
                                aclpb->aclpb_state &= ~ACLPB_COPY_EVALCONTEXT;
481
 
                        }
482
 
                        acl_clean_aclEval_context ( &aclpb->aclpb_curr_entryEval_context, 1 /*scrub */);
483
 
                }
484
 
 
485
 
                /* reset the cached result based on the scope */
486
 
                acl__reset_cached_result (aclpb );
487
 
 
488
 
                /* Find all the candidate aci's that apply by scanning up the DIT tree from edn. */
489
 
                
490
 
                TNF_PROBE_0_DEBUG(acl_aciscan_start,"ACL","");
491
 
                slapi_sdn_done ( aclpb->aclpb_curr_entry_sdn );
492
 
                slapi_sdn_set_ndn_byval ( aclpb->aclpb_curr_entry_sdn, n_edn );
493
 
                acllist_aciscan_update_scan ( aclpb, n_edn ); 
494
 
                TNF_PROBE_0_DEBUG(acl_aciscan_end,"ACL","");
495
 
 
496
 
                /* Keep the ptr to the current entry */
497
 
                aclpb->aclpb_curr_entry =  (Slapi_Entry *) e;
498
 
 
499
 
                /* Get the attr info */
500
 
                deallocate_attrEval = acl__get_attrEval ( aclpb, attr );
501
 
 
502
 
                aclutil_print_resource ( aclpb, right,  attr, clientDn );    
503
 
        
504
 
        /*
505
 
         * Used to be PListInitProp(aclpb->aclpb_proplist, 0,
506
 
         *                                                      DS_ATTR_ENTRY, e, 0);
507
 
                 *
508
 
         * The difference is that PListInitProp() allocates a new property
509
 
         * every time it's called, overwriting the old name in the PList hash
510
 
         * table, but not freeing the original property.
511
 
         * Now, we just create the property at aclpb_malloc() time and
512
 
         * Assign a new value each time.
513
 
        */       
514
 
        
515
 
                rv = PListAssignValue(aclpb->aclpb_proplist, 
516
 
                                   DS_ATTR_ENTRY, e, 0);
517
 
                                                 
518
 
                if (rv < 0) {
519
 
                        slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
520
 
                                "Unable to set the Slapi_Entry in the Plist\n");
521
 
                        ret_val = LDAP_OPERATIONS_ERROR;
522
 
                        goto cleanup_and_ret;
523
 
                }
524
 
                
525
 
                TNF_PROBE_0_DEBUG(acl_entry_first_touch_end,"ACL","");
526
 
 
527
 
        } else {
528
 
                /* we are processing the same entry but for a different
529
 
                ** attribute. If access is already allowed on that, entry, then 
530
 
                ** it's not a new entry anymore. It's the same old one.
531
 
                */
532
 
        
533
 
                TNF_PROBE_0_DEBUG(acl_entry_subs_touch_start,"ACL","");
534
 
        
535
 
                aclpb->aclpb_res_type &= ~ACLPB_NEW_ENTRY;
536
 
 
537
 
                /* Get the attr info */
538
 
                deallocate_attrEval = acl__get_attrEval ( aclpb, attr );
539
 
 
540
 
                TNF_PROBE_0_DEBUG(acl_entry_subs_touch_end,"ACL","");
541
 
 
542
 
        }
543
 
 
544
 
        /* get a lock for the reader */
545
 
        acllist_acicache_READ_LOCK();
546
 
        got_reader_locked = 1;
547
 
 
548
 
        /*
549
 
        ** Check if we can use any cached information to determine 
550
 
        ** access to this resource
551
 
        */
552
 
        if (  (access & SLAPI_ACL_SEARCH) &&
553
 
         (ret_val =  acl__match_handlesFromCache ( aclpb , attr, access))  != -1) {
554
 
                /* means got a result: allowed or not*/
555
 
 
556
 
                if (ret_val == LDAP_SUCCESS ) {
557
 
                                decision_reason.reason = ACL_REASON_EVALCONTEXT_CACHED_ALLOW;
558
 
                } else if (ret_val == LDAP_INSUFFICIENT_ACCESS) {
559
 
                                decision_reason.reason =
560
 
                                        ACL_REASON_EVALCONTEXT_CACHED_NOT_ALLOWED;
561
 
                }
562
 
                goto cleanup_and_ret;
563
 
        }
564
 
        
565
 
        /*
566
 
        ** Now we have all the information about the resource. Now we need to 
567
 
        ** figure out if there are any ACLs which can be applied.
568
 
        ** If no ACLs are there, then it's a DENY as default.
569
 
        */
570
 
        if (!(acl__scan_for_acis(aclpb, &err))) {
571
 
 
572
 
                /* We might have accessed the ACL first time which could
573
 
                ** have caused syntax error.
574
 
                */
575
 
                if ( err == ACL_ONEACL_TEXT_ERR) 
576
 
                        ret_val = LDAP_INVALID_SYNTAX;
577
 
                else {
578
 
                        ret_val = LDAP_INSUFFICIENT_ACCESS;
579
 
                        decision_reason.reason = ACL_REASON_NO_MATCHED_RESOURCE_ALLOWS;                 
580
 
                }
581
 
                goto cleanup_and_ret;
582
 
        }
583
 
 
584
 
        slapi_log_error( SLAPI_LOG_ACL, plugin_name,
585
 
                   "Processed attr:%s for entry:%s\n", attr ? attr : "NULL",
586
 
                    n_edn);
587
 
 
588
 
        /*
589
 
        ** Now evaluate the rights. 
590
 
        ** This is what we have been waiting for.
591
 
        ** The return value should be ACL_RES_DENY or ACL_RES_ALLOW.
592
 
        */
593
 
        rv = acl__TestRights(aclpb, access, &right, ds_map_generic,
594
 
                                                                                                &decision_reason);
595
 
        if ( rv != ACL_RES_ALLOW && (0 == strcasecmp ( right, "selfwrite") ) ) {
596
 
                /* If I am adding myself to a group, we don't need selfwrite always,
597
 
                ** write priv is good enough. Since libaccess doesn't provide me a nice
598
 
                ** way to evaluate OR rights, I have to try again with wite priv.
599
 
                ** bug: 339051
600
 
                */
601
 
                right = access_str_write;
602
 
                rv = acl__TestRights(aclpb, access, &right, ds_map_generic,
603
 
                                                                                                        &decision_reason);
604
 
    }
605
 
 
606
 
        if (rv == ACL_RES_ALLOW) {
607
 
                ret_val = LDAP_SUCCESS;
608
 
        } else {
609
 
                ret_val = LDAP_INSUFFICIENT_ACCESS;
610
 
        } 
611
 
 
612
 
cleanup_and_ret:
613
 
 
614
 
        TNF_PROBE_0_DEBUG(acl_cleanup_start,"ACL","");
615
 
 
616
 
        /* I am ready to get out. */
617
 
        if ( got_reader_locked ) acllist_acicache_READ_UNLOCK();
618
 
 
619
 
        /* Store the status of the evaluation for this attr */
620
 
        if (  aclpb && (c_attrEval = aclpb->aclpb_curr_attrEval )) {
621
 
                if ( deallocate_attrEval ) {
622
 
                        /* In this case we are not caching the result as 
623
 
                        ** we have too many attrs. we have malloced space. 
624
 
                        ** Get rid of it.
625
 
                        */
626
 
                        slapi_ch_free ( (void **) &c_attrEval->attrEval_name );
627
 
                        slapi_ch_free ( (void **) &c_attrEval );
628
 
                } else if (ret_val == LDAP_SUCCESS ) {
629
 
                        if ( access & SLAPI_ACL_SEARCH )
630
 
                                c_attrEval->attrEval_s_status |= ACL_ATTREVAL_SUCCESS;
631
 
                        else if ( access & SLAPI_ACL_READ )
632
 
                                c_attrEval->attrEval_r_status |= ACL_ATTREVAL_SUCCESS;
633
 
                        else
634
 
                                c_attrEval->attrEval_r_status |= ACL_ATTREVAL_INVALID;
635
 
                } else {
636
 
                        if ( access & SLAPI_ACL_SEARCH )
637
 
                                c_attrEval->attrEval_s_status |= ACL_ATTREVAL_FAIL;
638
 
                        else if ( access & SLAPI_ACL_READ )
639
 
                                c_attrEval->attrEval_r_status |= ACL_ATTREVAL_FAIL;
640
 
                        else
641
 
                                c_attrEval->attrEval_r_status |= ACL_ATTREVAL_INVALID;
642
 
                }
643
 
        }
644
 
 
645
 
        if ( aclpb ) aclpb->aclpb_curr_attrEval = NULL;
646
 
 
647
 
        print_access_control_summary( "main", ret_val, clientDn, aclpb, right,
648
 
                                      (attr ? attr : "NULL"), n_edn,
649
 
                                      &decision_reason );
650
 
        TNF_PROBE_0_DEBUG(acl_cleanup_end,"ACL","");
651
 
        
652
 
        TNF_PROBE_0_DEBUG(acl_access_allowed_end,"ACL","");
653
 
 
654
 
        return(ret_val);
655
 
        
656
 
}
657
 
 
658
 
static void print_access_control_summary( char *source, int ret_val, char *clientDn,
659
 
                                                                        struct  acl_pblock      *aclpb,
660
 
                                                                        char *right,
661
 
                                                                        char *attr,
662
 
                                                                        const char *edn,
663
 
                                                                        aclResultReason_t *acl_reason)
664
 
{
665
 
        struct codebook {
666
 
                int   code;
667
 
                char *text;
668
 
        };
669
 
 
670
 
        static struct codebook reasonbook[] = {
671
 
                {ACL_REASON_NO_ALLOWS,                                  "no allow acis"},
672
 
                {ACL_REASON_RESULT_CACHED_DENY,                 "cached deny"},
673
 
                {ACL_REASON_RESULT_CACHED_ALLOW,                "cached allow"},
674
 
                {ACL_REASON_EVALUATED_ALLOW,                    "allowed"},
675
 
                {ACL_REASON_EVALUATED_DENY,                             "denied"},
676
 
                {ACL_REASON_NO_MATCHED_RESOURCE_ALLOWS, "no aci matched the resource"},
677
 
                {ACL_REASON_NO_MATCHED_SUBJECT_ALLOWS,  "no aci matched the subject"},
678
 
                {ACL_REASON_ANON_ALLOWED,                               "allow anyone aci matched anon user"},
679
 
                {ACL_REASON_ANON_DENIED,                                "no matching anyone aci for anon user"},
680
 
                {ACL_REASON_EVALCONTEXT_CACHED_ALLOW,   "cached context/parent allow"},
681
 
                {ACL_REASON_EVALCONTEXT_CACHED_NOT_ALLOWED,     "cached context/parent deny"},
682
 
                {ACL_REASON_EVALCONTEXT_CACHED_ATTR_STAR_ALLOW, "cached context/parent allow any attr"},
683
 
                {ACL_REASON_NONE,                                               "error occurred"},
684
 
        };
685
 
 
686
 
        char *anon = "anonymous";
687
 
        char *null_user = "NULL";       /* bizare case */ 
688
 
        char *real_user = NULL;
689
 
        char *proxy_user = NULL;        
690
 
        char *access_allowed_string = "Allow";
691
 
        char *access_not_allowed_string = "Deny";
692
 
        char *access_error_string = "access_error";
693
 
        char *access_status = NULL;
694
 
        char *access_reason_none = "no reason available";
695
 
        char *access_reason = access_reason_none;       
696
 
        char acl_info[ BUFSIZ ];
697
 
        Slapi_Operation *op = NULL;
698
 
        int loglevel; 
699
 
        int     i;
700
 
 
701
 
        loglevel = slapi_is_loglevel_set(SLAPI_LOG_ACL) ? SLAPI_LOG_ACL : SLAPI_LOG_ACLSUMMARY;
702
 
 
703
 
        if ( !slapi_is_loglevel_set(loglevel) ) {
704
 
                return;
705
 
        }
706
 
 
707
 
        if ( !aclpb ) {
708
 
                slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,  "Missing aclpb \n" );
709
 
                return;
710
 
        }
711
 
 
712
 
        slapi_pblock_get(aclpb->aclpb_pblock, SLAPI_OPERATION, &op); /* for logging */
713
 
 
714
 
        if (ret_val == LDAP_INSUFFICIENT_ACCESS) {
715
 
                access_status = access_not_allowed_string;
716
 
        } else if ( ret_val == LDAP_SUCCESS) {
717
 
                access_status = access_allowed_string;
718
 
        } else { /* some kind of error */
719
 
                access_status = access_error_string;
720
 
        }
721
 
 
722
 
        /* decode the reason */
723
 
        for (i = 0; i < sizeof(reasonbook) / sizeof(struct codebook); i++) {
724
 
                if ( acl_reason->reason == reasonbook[i].code ) {
725
 
                        access_reason = reasonbook[i].text;
726
 
                        break;
727
 
                }
728
 
        }
729
 
 
730
 
        /* get the acl */
731
 
        acl_info[0] = '\0';
732
 
        if (acl_reason->deciding_aci) {
733
 
                if (acl_reason->reason == ACL_REASON_RESULT_CACHED_DENY ||
734
 
                        acl_reason->reason == ACL_REASON_RESULT_CACHED_ALLOW) {
735
 
                        /* acl is in cache. Its detail must have been printed before.
736
 
                         * So no need to print out acl detail this time.
737
 
                         */
738
 
                        PR_snprintf( &acl_info[0], BUFSIZ, "%s by aci(%d)",
739
 
                                access_reason,
740
 
                                acl_reason->deciding_aci->aci_index);
741
 
                } 
742
 
                else {
743
 
                        PR_snprintf( &acl_info[0], BUFSIZ, "%s by aci(%d): aciname=%s, acidn=\"%s\"",
744
 
                                access_reason,
745
 
                                acl_reason->deciding_aci->aci_index,
746
 
                                acl_reason->deciding_aci->aclName,
747
 
                                slapi_sdn_get_ndn (acl_reason->deciding_aci->aci_sdn) );
748
 
                }
749
 
        } 
750
 
 
751
 
        /* Say who was denied access */
752
 
 
753
 
        if (clientDn) {
754
 
                if (clientDn[0] == '\0') {
755
 
                        /* anon */
756
 
                        real_user = anon;
757
 
                } else {
758
 
                        real_user = clientDn;
759
 
                }
760
 
        } else {
761
 
                real_user = null_user;
762
 
        }
763
 
                        
764
 
        /* Is there a proxy */
765
 
 
766
 
        if ( aclpb->aclpb_proxy != NULL) {
767
 
 
768
 
                if ( aclpb->aclpb_authorization_sdn != NULL ) {
769
 
 
770
 
                                proxy_user = 
771
 
                                        (char *)(slapi_sdn_get_ndn(aclpb->aclpb_authorization_sdn)?
772
 
                                        slapi_sdn_get_ndn(aclpb->aclpb_authorization_sdn):
773
 
                                        null_user);
774
 
 
775
 
                                slapi_log_error(loglevel, plugin_name, 
776
 
                "conn=%" NSPRIu64 " op=%d (%s): %s %s on entry(%s).attr(%s) to proxy (%s)"
777
 
                ": %s\n",
778
 
                                op->o_connid, op->o_opid,
779
 
                                source,
780
 
                                access_status,
781
 
                                right, 
782
 
                                edn,
783
 
                                attr ? attr: "NULL",
784
 
                                proxy_user,
785
 
                                acl_info[0] ? acl_info : access_reason);                                                                        
786
 
                } else {
787
 
                                        proxy_user = null_user;
788
 
                                        slapi_log_error(loglevel, plugin_name, 
789
 
                "conn=%" NSPRIu64 " op=%d (%s): %s %s on entry(%s).attr(%s) to proxy (%s)"
790
 
                ": %s\n",
791
 
                                op->o_connid, op->o_opid,
792
 
                                source,
793
 
                                access_status,
794
 
                                right, 
795
 
                                edn,
796
 
                                attr ? attr: "NULL",
797
 
                                proxy_user,
798
 
                                acl_info[0] ? acl_info : access_reason);                                                                
799
 
                }
800
 
        } else{
801
 
                slapi_log_error(loglevel, plugin_name, 
802
 
                        "conn=%" NSPRIu64 " op=%d (%s): %s %s on entry(%s).attr(%s) to %s"
803
 
                        ": %s\n",
804
 
                                op->o_connid, op->o_opid,
805
 
                                source,
806
 
                                access_status,
807
 
                                right, 
808
 
                                edn,
809
 
                                attr ? attr: "NULL",
810
 
                                real_user,
811
 
                                acl_info[0] ? acl_info : access_reason);                                                                        
812
 
        }
813
 
        
814
 
 
815
 
}
816
 
/***************************************************************************
817
 
*
818
 
* acl_read_access_allowed_on_entry 
819
 
*       check read access control on the given entry.
820
 
*
821
 
*  Only used during seearch to test for read access on the entry.
822
 
*  (Could be generalized).
823
 
824
 
*       attrs is the list of requested attributes passed with the search.
825
 
*       If the entry has no attributes (weird case) then the routine survives.
826
 
*
827
 
* Input:
828
 
*
829
 
*
830
 
* Returns:
831
 
*       LDAP_SUCCESS                    - access allowed
832
 
*       LDAP_INSUFFICIENT_ACCESS        - access denied
833
 
*
834
 
* Error Handling:
835
 
*       None.
836
 
*
837
 
**************************************************************************/
838
 
int
839
 
acl_read_access_allowed_on_entry (
840
 
        Slapi_PBlock       *pb,
841
 
        Slapi_Entry        *e,                  /* The Slapi_Entry */   
842
 
        char               **attrs,
843
 
        int                access               /* access rights */
844
 
        )
845
 
{
846
 
 
847
 
        struct  acl_pblock      *aclpb; 
848
 
        Slapi_Attr                      *currAttr;
849
 
        Slapi_Attr                      *nextAttr;
850
 
        int                                     len;
851
 
#ifdef DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES
852
 
        int                                     attr_index = -1;
853
 
#endif
854
 
        char                            *attr_type = NULL;
855
 
        int                                     rv, isRoot;
856
 
        char                            *clientDn;
857
 
        unsigned long           flags;
858
 
        aclResultReason_t       decision_reason;
859
 
        int loglevel;
860
 
 
861
 
        loglevel = slapi_is_loglevel_set(SLAPI_LOG_ACL) ? SLAPI_LOG_ACL : SLAPI_LOG_ACLSUMMARY;
862
 
 
863
 
        TNF_PROBE_0_DEBUG(acl_read_access_allowed_on_entry_start ,"ACL","");
864
 
 
865
 
        decision_reason.deciding_aci = NULL;
866
 
        decision_reason.reason = ACL_REASON_NONE;
867
 
 
868
 
        slapi_pblock_get ( pb, SLAPI_REQUESTOR_ISROOT, &isRoot );
869
 
 
870
 
        /* 
871
 
        ** If it's the root, or acl is off or the entry is a rootdse, 
872
 
        ** Then you have the privilege to read it.
873
 
        */
874
 
        if ( acl_skip_access_check ( pb, e ) ) {
875
 
                char   *n_edn =  slapi_entry_get_ndn ( e );
876
 
                slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
877
 
                          "Root access (%s) allowed on entry(%s)\n",
878
 
                           acl_access2str(access), 
879
 
                           n_edn);
880
 
                TNF_PROBE_1_DEBUG(acl_read_access_allowed_on_entry_end ,"ACL","",
881
 
                                                        tnf_string,skip_access,"");
882
 
                return LDAP_SUCCESS;
883
 
        }               
884
 
 
885
 
        aclpb = acl_get_aclpb ( pb, ACLPB_BINDDN_PBLOCK );
886
 
        if ( !aclpb ) {
887
 
                slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,  "Missing aclpb 2 \n" );
888
 
                TNF_PROBE_1_DEBUG(acl_read_access_allowed_on_entry_end ,"ACL","",
889
 
                                                        tnf_string,end,"aclpb error");
890
 
                return LDAP_OPERATIONS_ERROR;
891
 
        }
892
 
 
893
 
        /*
894
 
         * Am I a anonymous dude ? then we can use our anonympous profile
895
 
         * We don't require the aclpb to have been initialized for anom stuff
896
 
         *
897
 
        */
898
 
        slapi_pblock_get ( pb, SLAPI_REQUESTOR_DN, &clientDn );
899
 
        if ( clientDn  && *clientDn == '\0' ) {
900
 
                int ret_val;
901
 
                ret_val =  aclanom_match_profile ( pb, aclpb, e, NULL, SLAPI_ACL_READ );
902
 
                TNF_PROBE_1_DEBUG(acl_read_access_allowed_on_entry_end ,"ACL","",
903
 
                                        tnf_string,end,"anon");
904
 
 
905
 
                if (ret_val != -1 ) return ret_val;
906
 
        }
907
 
 
908
 
        aclpb->aclpb_state &= ~ACLPB_RESET_MASK;
909
 
        if (aclpb->aclpb_state & ACLPB_MATCHES_ALL_ACLS ) {
910
 
                int     ret_val;
911
 
                ret_val = acl__attr_cached_result (aclpb, NULL, SLAPI_ACL_READ);
912
 
                if (ret_val != -1 ) {
913
 
                        /* print summary if loglevel set */                     
914
 
                        if ( slapi_is_loglevel_set(loglevel) ) {
915
 
                                char *n_edn;
916
 
                                n_edn =  slapi_entry_get_ndn ( e );
917
 
                                if ( ret_val == LDAP_SUCCESS) {
918
 
                                        decision_reason.reason =
919
 
                                                        ACL_REASON_EVALCONTEXT_CACHED_ALLOW;
920
 
                                } else {
921
 
                                        decision_reason.reason =
922
 
                                                                        ACL_REASON_EVALCONTEXT_CACHED_NOT_ALLOWED;
923
 
                                }
924
 
                                /*
925
 
                                 * pass NULL as the attr as this routine is concerned with
926
 
                                 * access at the entry level.
927
 
                                */
928
 
                                print_access_control_summary( "on entry",
929
 
                                                                                        ret_val, clientDn, aclpb,
930
 
                                                                                        acl_access2str(SLAPI_ACL_READ),
931
 
                                                                                        NULL, n_edn,
932
 
                                                                                        &decision_reason);
933
 
                        }
934
 
                        TNF_PROBE_1_DEBUG(acl_read_access_allowed_on_entry_end ,"ACL","",
935
 
                                                        tnf_string,eval_context_cached,"");
936
 
 
937
 
                        return ret_val;
938
 
                }
939
 
        }
940
 
 
941
 
        /*
942
 
         * Currently do not use this code--it results in confusing
943
 
         * behaviour..see 529905
944
 
        */      
945
 
#ifdef DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES
946
 
 
947
 
        /* Do we have access to the entry by virtue of 
948
 
        ** having access to an attr. Before that, let's find out which attrs
949
 
        ** the user want. If the user has specified certain attributes, then
950
 
        ** we check aginst that set of attributes.
951
 
        */
952
 
        if (!((aclpb->aclpb_state & ACLPB_USER_WANTS_ALL_ATTRS) || 
953
 
                (aclpb->aclpb_state & ACLPB_USER_SPECIFIED_ATTARS))) {
954
 
                int i;
955
 
                if (attrs == NULL) {
956
 
                        aclpb->aclpb_state |= ACLPB_USER_WANTS_ALL_ATTRS;
957
 
                } else {
958
 
                        for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) {
959
 
                                if ( strcmp( LDAP_ALL_USER_ATTRS, attrs[i] ) == 0 ) {
960
 
                                        aclpb->aclpb_state |= ACLPB_USER_WANTS_ALL_ATTRS;
961
 
                                        break;
962
 
                                }
963
 
                        }
964
 
                }
965
 
 
966
 
                if (!(aclpb->aclpb_state & ACLPB_USER_WANTS_ALL_ATTRS)) {
967
 
                        for (i = 0; attrs != NULL && attrs[i] != NULL; i++ ) {
968
 
                                if ( !slapi_entry_attr_find ( e,  attrs[i], &currAttr ) ) {
969
 
                                        aclpb->aclpb_state |= ACLPB_USER_SPECIFIED_ATTARS;
970
 
                                        break;
971
 
                                }
972
 
                        }
973
 
                }
974
 
        } /* end of all user test*/
975
 
 
976
 
 
977
 
        /* 
978
 
        ** If user has specified a list of attrs, might as well use it
979
 
        ** to determine access control.
980
 
        */
981
 
        currAttr = NULL;
982
 
        attr_index = -1;
983
 
        if ( aclpb->aclpb_state & ACLPB_USER_SPECIFIED_ATTARS) {
984
 
                attr_index = 0;
985
 
                attr_type = attrs[attr_index++];
986
 
        } else { 
987
 
                /* Skip the operational attributes  -- if there are any in the front */
988
 
                slapi_entry_first_attr ( e, &currAttr );
989
 
                if (currAttr != NULL) {
990
 
                        slapi_attr_get_flags ( currAttr,  &flags );
991
 
                        while  ( flags & SLAPI_ATTR_FLAG_OPATTR ) {
992
 
                                flags = 0;
993
 
                                rv = slapi_entry_next_attr ( e, currAttr, &nextAttr );
994
 
                                if  (  !rv )  slapi_attr_get_flags ( nextAttr,  &flags );
995
 
                                currAttr = nextAttr;
996
 
                        }               
997
 
 
998
 
                        /* Get the attr type */
999
 
                        if ( currAttr ) slapi_attr_get_type ( currAttr , &attr_type );
1000
 
                }
1001
 
        }
1002
 
 
1003
 
#endif /*DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES*/
1004
 
 
1005
 
#ifndef DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES
1006
 
 
1007
 
        /*
1008
 
         * Here look at each attribute in the entry and see if
1009
 
         * we have read access to it--if we do
1010
 
         * and we are not denied access to the entry then this
1011
 
         * is taken as implying access to the entry.
1012
 
        */
1013
 
        slapi_entry_first_attr ( e, &currAttr );
1014
 
        if (currAttr != NULL) {
1015
 
                slapi_attr_get_type ( currAttr , &attr_type );
1016
 
        }
1017
 
#endif
1018
 
        aclpb->aclpb_state |= ACLPB_EVALUATING_FIRST_ATTR;
1019
 
 
1020
 
        while (attr_type) {
1021
 
                if (acl_access_allowed (pb, e,attr_type, NULL, 
1022
 
                                    SLAPI_ACL_READ) == LDAP_SUCCESS) {
1023
 
                        /*
1024
 
                        ** We found a rule which requires us to test access
1025
 
                        ** to the entry.
1026
 
                        */
1027
 
                        if ( aclpb->aclpb_state & ACLPB_FOUND_A_ENTRY_TEST_RULE){
1028
 
                                /* Do I have access on the entry  itself */
1029
 
                                if (acl_access_allowed (pb, e, NULL, 
1030
 
                                                NULL, access) != LDAP_SUCCESS) {
1031
 
                                        /* How was I denied ? 
1032
 
                                        ** I could be denied on a DENY rule or because 
1033
 
                                        ** there is no allow rule. If it's a DENY from
1034
 
                                        ** a DENY rule, then we don't have access to 
1035
 
                                        ** the entry ( nice trick to get in )
1036
 
                                        */
1037
 
                                        if ( aclpb->aclpb_state & 
1038
 
                                                        ACLPB_EXECUTING_DENY_HANDLES)
1039
 
                                                return LDAP_INSUFFICIENT_ACCESS;
1040
 
                                        
1041
 
                                        /* The other case is I don't have an
1042
 
                                        ** explicit allow rule -- which is fine.
1043
 
                                        ** Since, I am already here, it means that I have
1044
 
                                        ** an implicit allow to the entry.      
1045
 
                                        */
1046
 
                                }
1047
 
                        }
1048
 
                        aclpb->aclpb_state &= ~ACLPB_EVALUATING_FIRST_ATTR;
1049
 
 
1050
 
                        /*
1051
 
                        ** If we are not sending all the attrs, then we must
1052
 
                        ** make sure that we have right on a attr that we are 
1053
 
                        ** sending
1054
 
                        */
1055
 
                        len = strlen(attr_type);
1056
 
                        if ( (len + 1) > ACLPB_MAX_ATTR_LEN) {
1057
 
                                slapi_ch_free ( (void **) &aclpb->aclpb_Evalattr);
1058
 
                                aclpb->aclpb_Evalattr = slapi_ch_malloc(len+1);
1059
 
                        }
1060
 
                        PL_strncpyz (aclpb->aclpb_Evalattr, attr_type, len);
1061
 
#ifdef DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES
1062
 
                        if ( attr_index >= 0 ) {
1063
 
                                /*
1064
 
                                 * access was granted to one of the user specified attributes
1065
 
                                 * which was found in the entry and that attribute is
1066
 
                                 * now in aclpb_Evalattr
1067
 
                                */
1068
 
                                aclpb->aclpb_state |= ACLPB_ACCESS_ALLOWED_USERATTR;
1069
 
                        } else {
1070
 
#endif /* DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES */
1071
 
                                /*
1072
 
                                 * Access was granted to _an_ attribute in the entry and that
1073
 
                                 * attribute is now in aclpb_Evalattr
1074
 
                                */
1075
 
                                aclpb->aclpb_state |= ACLPB_ACCESS_ALLOWED_ON_A_ATTR;
1076
 
#ifdef DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES
1077
 
                        }
1078
 
#endif /* DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES */
1079
 
                        TNF_PROBE_1_DEBUG(acl_read_access_allowed_on_entry_end , "ACL","",
1080
 
                                                tnf_string,called_access_allowed,"");
1081
 
 
1082
 
                        return LDAP_SUCCESS;
1083
 
                } else {
1084
 
                        /* try the next one */
1085
 
                        attr_type = NULL;
1086
 
#ifdef DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES 
1087
 
                        if (attr_index >= 0) {
1088
 
                                attr_type = attrs[attr_index++];
1089
 
                        } else {
1090
 
#endif /* DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES */
1091
 
                                rv = slapi_entry_next_attr ( e, currAttr, &nextAttr );
1092
 
                                if ( rv != 0 ) break;
1093
 
                                currAttr = nextAttr;
1094
 
                                slapi_attr_get_flags ( currAttr,  &flags );
1095
 
                                while  ( flags & SLAPI_ATTR_FLAG_OPATTR ) {
1096
 
                                        flags = 0;
1097
 
                                        rv = slapi_entry_next_attr ( e, currAttr, &nextAttr );
1098
 
                                        if  (  !rv )  slapi_attr_get_flags ( nextAttr,  &flags );
1099
 
                                        currAttr = nextAttr;
1100
 
                                }
1101
 
                                /* Get the attr type */
1102
 
                                if ( currAttr ) slapi_attr_get_type ( currAttr , &attr_type );
1103
 
#ifdef DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES
1104
 
                        }
1105
 
#endif /* DETERMINE_ACCESS_BASED_ON_REQUESTED_ATTRIBUTES */
1106
 
                }
1107
 
        }
1108
 
 
1109
 
        /* 
1110
 
        ** That means. we have searched thru all the attrs and found
1111
 
        ** access is denied on all attrs.
1112
 
        **
1113
 
        ** If there were no attributes in the entry at all (can have
1114
 
        ** such entries thrown up by the b/e, then we do
1115
 
        ** not have such an implied access.
1116
 
        */
1117
 
        aclpb->aclpb_state |= ACLPB_ACCESS_DENIED_ON_ALL_ATTRS;
1118
 
        aclpb->aclpb_state &= ~ACLPB_EVALUATING_FIRST_ATTR;
1119
 
        TNF_PROBE_0_DEBUG(acl_read_access_allowed_on_entry_end ,"ACL","");
1120
 
 
1121
 
        return LDAP_INSUFFICIENT_ACCESS;
1122
 
}
1123
 
 
1124
 
/***************************************************************************
1125
 
*
1126
 
* acl_read_access_allowed_on_attr 
1127
 
*       check access control on the given attr.
1128
 
*
1129
 
* Only used during search to test for read access to an attr.
1130
 
* (Could be generalized)
1131
 
*
1132
 
* Input:
1133
 
*
1134
 
*
1135
 
* Returns:
1136
 
*       LDAP_SUCCESS                    - access allowed
1137
 
*       LDAP_INSUFFICIENT_ACCESS        - access denied
1138
 
*
1139
 
* Error Handling:
1140
 
*       None.
1141
 
*
1142
 
**************************************************************************/
1143
 
int
1144
 
acl_read_access_allowed_on_attr (
1145
 
        Slapi_PBlock            *pb,
1146
 
        Slapi_Entry                     *e,             /* The Slapi_Entry */
1147
 
        char                            *attr,          /* Attribute of the entry */
1148
 
        struct berval           *val,           /* value of attr. NOT USED */
1149
 
        int                                     access          /* access rights */
1150
 
        )
1151
 
{
1152
 
 
1153
 
        struct  acl_pblock      *aclpb =  NULL;
1154
 
        char                            *clientDn = NULL;
1155
 
        char                            *n_edn;
1156
 
        aclResultReason_t       decision_reason;
1157
 
        int                             ret_val = -1;
1158
 
        int                                     loglevel;
1159
 
 
1160
 
        loglevel = slapi_is_loglevel_set(SLAPI_LOG_ACL) ? SLAPI_LOG_ACL : SLAPI_LOG_ACLSUMMARY;
1161
 
 
1162
 
        TNF_PROBE_0_DEBUG(acl_read_access_allowed_on_attr_start ,"ACL","");
1163
 
 
1164
 
        decision_reason.deciding_aci = NULL;
1165
 
        decision_reason.reason = ACL_REASON_NONE;
1166
 
 
1167
 
        /* I am here, because I have access to the entry */
1168
 
 
1169
 
        n_edn =  slapi_entry_get_ndn ( e );
1170
 
 
1171
 
        /* If it's the root or acl is off or rootdse, he has all the priv */
1172
 
        if ( acl_skip_access_check ( pb, e ) ) {
1173
 
                slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
1174
 
                          "Root access (%s) allowed on entry(%s)\n",
1175
 
                           acl_access2str(access), 
1176
 
                           n_edn);
1177
 
                TNF_PROBE_1_DEBUG(acl_read_access_allowed_on_attr_end ,"ACL","",
1178
 
                                                        tnf_string,skip_aclcheck,"");
1179
 
 
1180
 
                return LDAP_SUCCESS;
1181
 
        }       
1182
 
 
1183
 
        aclpb = acl_get_aclpb ( pb, ACLPB_BINDDN_PBLOCK );
1184
 
        if ( !aclpb ) {
1185
 
                slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,  "Missing aclpb 3 \n" );
1186
 
                TNF_PROBE_1_DEBUG(acl_read_access_allowed_on_attr_end ,"ACL","",
1187
 
                                                        tnf_string,aclpb_error,"");
1188
 
 
1189
 
                return LDAP_OPERATIONS_ERROR;
1190
 
        }
1191
 
        
1192
 
        /*
1193
 
         * Am I a anonymous dude ? then we can use our anonympous profile
1194
 
         * We don't require the aclpb to have been initialized for anom stuff
1195
 
         *
1196
 
        */
1197
 
        slapi_pblock_get (pb, SLAPI_REQUESTOR_DN ,&clientDn );
1198
 
        if ( clientDn && *clientDn == '\0' ) {          
1199
 
                ret_val =  aclanom_match_profile ( pb, aclpb, e, attr, 
1200
 
                                                SLAPI_ACL_READ );
1201
 
                TNF_PROBE_1_DEBUG(acl_read_access_allowed_on_attr_end ,"ACL","",
1202
 
                                                        tnf_string,anon_decision,"");
1203
 
                if (ret_val != -1 ) return ret_val;
1204
 
        }
1205
 
 
1206
 
        /* Then I must have a access to the entry. */
1207
 
        aclpb->aclpb_state |= ACLPB_ACCESS_ALLOWED_ON_ENTRY;
1208
 
 
1209
 
        if ( aclpb->aclpb_state & ACLPB_MATCHES_ALL_ACLS ) {            
1210
 
 
1211
 
                ret_val = acl__attr_cached_result (aclpb, attr, SLAPI_ACL_READ);
1212
 
                if (ret_val != -1 ) {
1213
 
                        slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
1214
 
                                 "MATCHED HANDLE:dn:%s attr: %s val:%d\n", 
1215
 
                                n_edn, attr, ret_val );
1216
 
                        if ( ret_val == LDAP_SUCCESS) {
1217
 
                                decision_reason.reason =
1218
 
                                                ACL_REASON_EVALCONTEXT_CACHED_ALLOW;
1219
 
                        } else {
1220
 
                                decision_reason.reason =
1221
 
                                                        ACL_REASON_EVALCONTEXT_CACHED_NOT_ALLOWED;
1222
 
                        }               
1223
 
                        goto acl_access_allowed_on_attr_Exit;
1224
 
                 } else  {
1225
 
                        aclpb->aclpb_state |= ACLPB_COPY_EVALCONTEXT;
1226
 
                }
1227
 
        }
1228
 
 
1229
 
        if (aclpb->aclpb_state & ACLPB_ACCESS_DENIED_ON_ALL_ATTRS) {
1230
 
                /* access is denied on all the attributes */
1231
 
                TNF_PROBE_1_DEBUG(acl_read_access_allowed_on_attr_end ,"ACL","",
1232
 
                                                        tnf_string,deny_all_attrs,"");
1233
 
 
1234
 
                return LDAP_INSUFFICIENT_ACCESS;
1235
 
        } 
1236
 
 
1237
 
        /* do I have access to all the entries by virtue of having aci 
1238
 
        ** rules with targetattr ="*". If yes, then allow access to
1239
 
        ** rest of the attributes.
1240
 
        */
1241
 
        if (aclpb->aclpb_state & ACLPB_ATTR_STAR_MATCHED) {
1242
 
                slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
1243
 
                          "STAR Access allowed on attr:%s; entry:%s \n",
1244
 
                           attr, n_edn);
1245
 
                decision_reason.reason = ACL_REASON_EVALCONTEXT_CACHED_ATTR_STAR_ALLOW;
1246
 
                ret_val = LDAP_SUCCESS;
1247
 
                goto acl_access_allowed_on_attr_Exit;
1248
 
 
1249
 
        }
1250
 
 
1251
 
        if (aclpb->aclpb_state & ACLPB_ACCESS_ALLOWED_ON_A_ATTR) {
1252
 
 
1253
 
                /* access is allowed on that attr.
1254
 
                ** for example:  Slapi_Entry: cn, sn. phone, uid, passwd, address
1255
 
                ** We found that access is allowed on phone. That means the
1256
 
                **  -- access is denied on cn, sn
1257
 
                **  -- access  is allowed on phone
1258
 
                **  -- Don't know about the rest. Need to evaluate.
1259
 
                */
1260
 
 
1261
 
                if ( slapi_attr_type_cmp (attr, aclpb->aclpb_Evalattr, 1) == 0) {
1262
 
                        /* from now on we need to evaluate access on
1263
 
                        ** rest of the attrs.
1264
 
                        */
1265
 
                        aclpb->aclpb_state &= ~ACLPB_ACCESS_ALLOWED_ON_A_ATTR;
1266
 
                        TNF_PROBE_1_DEBUG(acl_read_access_allowed_on_attr_end ,"ACL","",
1267
 
                                                                tnf_string,aclp_Evalattr1,"");
1268
 
 
1269
 
                        return LDAP_SUCCESS;
1270
 
                } else {
1271
 
                        /*
1272
 
                         * Here, the attr that implied access to the entry (aclpb_Evalattr),
1273
 
                         *  is not
1274
 
                         * the one we currently want evaluated--so
1275
 
                         * we need to evaluate access to attr--so fall through.
1276
 
                        */                                              
1277
 
                }
1278
 
 
1279
 
        }  else if (aclpb->aclpb_state & ACLPB_ACCESS_ALLOWED_USERATTR) {
1280
 
                /* Only skip evaluation on the user attr on which we have
1281
 
                ** evaluated before.
1282
 
                */
1283
 
                if ( slapi_attr_type_cmp (attr, aclpb->aclpb_Evalattr, 1) == 0) {
1284
 
                        aclpb->aclpb_state &= ~ACLPB_ACCESS_ALLOWED_USERATTR;
1285
 
                        TNF_PROBE_1_DEBUG(acl_read_access_allowed_on_attr_end ,"ACL","",
1286
 
                                                                tnf_string,aclp_Evalattr2,"");
1287
 
                        return LDAP_SUCCESS;
1288
 
                }
1289
 
        }
1290
 
 
1291
 
        /* we need to evaluate the access on this attr */
1292
 
        return ( acl_access_allowed(pb, e, attr, val, access) );
1293
 
 
1294
 
        /* This exit point prints a summary and returns ret_val */
1295
 
acl_access_allowed_on_attr_Exit:
1296
 
 
1297
 
        /* print summary if loglevel set */                     
1298
 
        if ( slapi_is_loglevel_set(loglevel) ) {
1299
 
                
1300
 
                print_access_control_summary( "on attr",
1301
 
                                                                                ret_val, clientDn, aclpb,
1302
 
                                                                                acl_access2str(SLAPI_ACL_READ),
1303
 
                                                                                attr, n_edn,                                                                                    &decision_reason);
1304
 
        }
1305
 
        TNF_PROBE_0_DEBUG(acl_read_access_allowed_on_attr_end ,"ACL","");
1306
 
 
1307
 
        return(ret_val);
1308
 
}
1309
 
/***************************************************************************
1310
 
*
1311
 
* acl_check_mods 
1312
 
*        check access control on the given entry to see if
1313
 
*       it allows the given modifications by the user associated with op.
1314
 
*
1315
 
*
1316
 
* Input:
1317
 
*
1318
 
*
1319
 
* Returns:
1320
 
*       LDAP_SUCCESS                    - mods allowed ok
1321
 
*       <err>                           - same return value as acl_access_allowed()
1322
 
*
1323
 
* Error Handling:
1324
 
*       None.
1325
 
*
1326
 
**************************************************************************/
1327
 
int
1328
 
acl_check_mods(
1329
 
    Slapi_PBlock        *pb,
1330
 
    Slapi_Entry *e,
1331
 
    LDAPMod     **mods,
1332
 
    char        **errbuf
1333
 
)
1334
 
{
1335
 
        int                     i;
1336
 
        int                             rv, accessCheckDisabled;
1337
 
        int                             lastmod = 0;
1338
 
        Slapi_Attr              *attr = NULL;
1339
 
        char                    *n_edn;
1340
 
        Slapi_Backend   *be = NULL;
1341
 
        Slapi_DN                *e_sdn;
1342
 
        Acl_PBlock              *aclpb = acl_get_aclpb ( pb, ACLPB_PROXYDN_PBLOCK );
1343
 
        LDAPMod                 *mod;
1344
 
        Slapi_Mods              smods;
1345
 
 
1346
 
        rv = slapi_pblock_get ( pb, SLAPI_PLUGIN_DB_NO_ACL, &accessCheckDisabled );
1347
 
    if ( rv != -1 && accessCheckDisabled ) return LDAP_SUCCESS;
1348
 
 
1349
 
         if ( NULL == aclpb )
1350
 
                aclpb = acl_get_aclpb ( pb, ACLPB_BINDDN_PBLOCK );
1351
 
 
1352
 
        n_edn = slapi_entry_get_ndn ( e );
1353
 
        e_sdn = slapi_entry_get_sdn ( e );
1354
 
 
1355
 
        slapi_mods_init_byref(&smods,mods);
1356
 
        
1357
 
        for (mod = slapi_mods_get_first_mod(&smods);
1358
 
                 mod != NULL;
1359
 
                 mod = slapi_mods_get_next_mod(&smods)) {
1360
 
                switch (mod->mod_op & ~LDAP_MOD_BVALUES ) {
1361
 
 
1362
 
                   case LDAP_MOD_DELETE:
1363
 
                        if (mod->mod_bvalues != NULL ) {
1364
 
                                break;
1365
 
                        }
1366
 
                        
1367
 
                        /*
1368
 
                         * Here, check that we have the right to delete all 
1369
 
                         * the values of the attribute in the entry.
1370
 
                        */
1371
 
 
1372
 
                   case LDAP_MOD_REPLACE:
1373
 
                        if ( !lastmod ) {
1374
 
                            if (be == NULL) { 
1375
 
                                if (slapi_pblock_get( pb, SLAPI_BACKEND, &be )) {
1376
 
                                    be = NULL;
1377
 
                                }
1378
 
                            }
1379
 
                            if (be != NULL)
1380
 
                                slapi_pblock_get ( pb, SLAPI_BE_LASTMOD, &lastmod );
1381
 
                        }
1382
 
                        if (lastmod &&
1383
 
                            (strcmp (mod->mod_type, "modifiersname")== 0 ||
1384
 
                             strcmp (mod->mod_type, "modifytimestamp")== 0 ||
1385
 
                             strcmp (mod->mod_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD)== 0)
1386
 
                                ) {
1387
 
                                continue; 
1388
 
                        }
1389
 
 
1390
 
                        slapi_entry_attr_find (e, mod->mod_type, &attr);
1391
 
                        if ( attr != NULL) {
1392
 
                                Slapi_Value *sval=NULL;
1393
 
                                const struct berval *attrVal=NULL;
1394
 
                                int k= slapi_attr_first_value(attr,&sval);
1395
 
                                while(k != -1) {
1396
 
                                        attrVal = slapi_value_get_berval(sval);
1397
 
                                        rv = slapi_access_allowed (pb, e,
1398
 
                                                             mod->mod_type, 
1399
 
                                                             (struct berval *)attrVal, /* XXXggood had to cast away const - BAD */
1400
 
                                                                        ACLPB_SLAPI_ACL_WRITE_DEL); /* was SLAPI_ACL_WRITE */
1401
 
                                        if ( rv != LDAP_SUCCESS) {
1402
 
                                                acl_gen_err_msg (
1403
 
                                                        SLAPI_ACL_WRITE,
1404
 
                                                        n_edn, 
1405
 
                                                        mod->mod_type,
1406
 
                                                        errbuf);
1407
 
                                                /* Cleanup */
1408
 
                                                slapi_mods_done(&smods);
1409
 
                                                return(rv);
1410
 
                                        }
1411
 
                                        k= slapi_attr_next_value(attr, k, &sval);
1412
 
                                }
1413
 
                        }
1414
 
                        else {
1415
 
                                        rv = slapi_access_allowed (pb, e,
1416
 
                                                             mod->mod_type, 
1417
 
                                                             NULL,
1418
 
                                                                        ACLPB_SLAPI_ACL_WRITE_DEL); /* was SLAPI_ACL_WRITE */
1419
 
                                        if ( rv != LDAP_SUCCESS) {
1420
 
                                                acl_gen_err_msg (
1421
 
                                                        SLAPI_ACL_WRITE,
1422
 
                                                        n_edn, 
1423
 
                                                        mod->mod_type,
1424
 
                                                        errbuf);
1425
 
                                                /* Cleanup */
1426
 
                                                slapi_mods_done(&smods);
1427
 
                                                return(rv);
1428
 
                                        }
1429
 
                        }
1430
 
                        break;
1431
 
 
1432
 
                   default:
1433
 
                        break;
1434
 
                } /* switch */
1435
 
 
1436
 
                /* 
1437
 
         * Check that we have add/delete writes on the specific values
1438
 
                 * we are trying to add.
1439
 
        */
1440
 
        
1441
 
                if ( aclpb && aclpb->aclpb_curr_entry_sdn )
1442
 
                        slapi_sdn_done ( aclpb->aclpb_curr_entry_sdn );
1443
 
 
1444
 
                if ( mod->mod_bvalues != NULL ) {
1445
 
 
1446
 
                        /*
1447
 
                         * Here, there are specific values specified.
1448
 
                         * For add and replace--we need add rights for these values.
1449
 
                         * For delete we need delete rights for these values.
1450
 
                        */
1451
 
 
1452
 
                        for ( i = 0; mod->mod_bvalues[i] != NULL; i++ ) {
1453
 
 
1454
 
                                if (SLAPI_IS_MOD_ADD(mod->mod_op) ||
1455
 
                                         SLAPI_IS_MOD_REPLACE(mod->mod_op)) {
1456
 
 
1457
 
                                                rv = acl_access_allowed (pb,e,
1458
 
                                                     mod->mod_type, 
1459
 
                                                     mod->mod_bvalues[i],
1460
 
                                ACLPB_SLAPI_ACL_WRITE_ADD); /*was SLAPI_ACL_WRITE*/
1461
 
                                } else if (SLAPI_IS_MOD_DELETE(mod->mod_op)) {
1462
 
                                                rv = acl_access_allowed (pb,e,
1463
 
                                                     mod->mod_type, 
1464
 
                                                     mod->mod_bvalues[i],
1465
 
                                ACLPB_SLAPI_ACL_WRITE_DEL); /*was SLAPI_ACL_WRITE*/
1466
 
                                } else {
1467
 
                                                rv = LDAP_INSUFFICIENT_ACCESS;
1468
 
                                }               
1469
 
                                     
1470
 
                                if ( rv != LDAP_SUCCESS ) {
1471
 
                                        acl_gen_err_msg (
1472
 
                                                SLAPI_ACL_WRITE,
1473
 
                                                n_edn, 
1474
 
                                                mod->mod_type,
1475
 
                                                errbuf);
1476
 
                                        /* Cleanup */
1477
 
                                        slapi_mods_done(&smods);
1478
 
                                        return rv;
1479
 
                                }
1480
 
                                /* Need to check for all the values because
1481
 
                                ** we may be modifying a "self<right>" value.
1482
 
                                */
1483
 
 
1484
 
                                /* Are we adding/replacing a aci attribute
1485
 
                                ** value. In that case, we need to make
1486
 
                                ** sure that the new value has thr right 
1487
 
                                ** syntax
1488
 
                                */
1489
 
                                if (strcmp(mod->mod_type, 
1490
 
                                           aci_attr_type) == 0) {
1491
 
                                        if ( 0 != (rv = acl_verify_syntax( e_sdn,
1492
 
                                                                        mod->mod_bvalues[i], errbuf))) {
1493
 
                                                aclutil_print_err(rv, e_sdn, 
1494
 
                                                        mod->mod_bvalues[i],
1495
 
                                                        errbuf);
1496
 
                                                /* Cleanup */
1497
 
                                                slapi_mods_done(&smods);
1498
 
                                                return LDAP_INVALID_SYNTAX;
1499
 
                                        }
1500
 
                                }
1501
 
                        } /* for */
1502
 
                }
1503
 
        } /* end of big for */
1504
 
        /* Cleanup */
1505
 
        slapi_mods_done(&smods);
1506
 
        return( LDAP_SUCCESS );
1507
 
}
1508
 
/***************************************************************************
1509
 
*
1510
 
* acl_modified
1511
 
*       Modifies ( removed, add, changes) the ACI LIST. 
1512
 
*
1513
 
* Input:
1514
 
*       int     *optype         - op code
1515
 
*       char    *dn             - DN of the entry
1516
 
*       void    *change         - The change struct which contais the 
1517
 
*                               - change value
1518
 
*
1519
 
* Returns:
1520
 
*       None.
1521
 
*
1522
 
* Error Handling:
1523
 
*       None.
1524
 
*
1525
 
**************************************************************************/
1526
 
extern void
1527
 
acl_modified (Slapi_PBlock *pb, int optype, char *n_dn, void *change)
1528
 
{
1529
 
        struct  berval  **bvalue;
1530
 
        char                    **value;
1531
 
        int                             rv=0;           /* returned value */
1532
 
        char*           new_RDN;
1533
 
        char*           parent_DN;
1534
 
        char*           new_DN;
1535
 
        LDAPMod                 **mods;
1536
 
        struct  berval  b;
1537
 
        int                             j;
1538
 
        Slapi_Attr              *attr = NULL;
1539
 
        Slapi_Entry             *e = NULL;
1540
 
        Slapi_DN                *e_sdn;
1541
 
        aclUserGroup    *ugroup = NULL;
1542
 
        
1543
 
        e_sdn = slapi_sdn_new_normdn_byval ( n_dn );
1544
 
        /* Before we proceed, Let's first check if we are changing any groups.
1545
 
        ** If we are, then we need to change the signature
1546
 
        */
1547
 
        switch ( optype ) {
1548
 
        case SLAPI_OPERATION_MODIFY:
1549
 
        case SLAPI_OPERATION_DELETE:
1550
 
                slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, (void*)&e);
1551
 
                break;
1552
 
        case SLAPI_OPERATION_ADD:
1553
 
                e = (Slapi_Entry *)change;
1554
 
                break;
1555
 
        }
1556
 
 
1557
 
        /* e can be null for RDN */
1558
 
        if ( e ) slapi_entry_attr_find( e, "objectclass", &attr);
1559
 
 
1560
 
        if ( attr ) {
1561
 
                int     group_change = 0;
1562
 
                Slapi_Value *sval=NULL;
1563
 
                const struct berval *attrVal;
1564
 
                int i;
1565
 
 
1566
 
                i= slapi_attr_first_value ( attr,&sval );
1567
 
                while(i != -1) {
1568
 
                        attrVal = slapi_value_get_berval ( sval );
1569
 
                        if ( (strcasecmp (attrVal->bv_val, "groupOfNames") == 0 )  ||
1570
 
                                (strcasecmp (attrVal->bv_val, "groupOfUniqueNames") == 0 )  ||
1571
 
                                (strcasecmp (attrVal->bv_val, "groupOfCertificates") == 0 )  ||
1572
 
                                (strcasecmp (attrVal->bv_val, "groupOfURLs") == 0 ) ) {
1573
 
                                group_change= 1;
1574
 
                                if ( optype == SLAPI_OPERATION_MODIFY ) {
1575
 
                                        Slapi_Attr      *a = NULL;
1576
 
                                        int                     rv;
1577
 
                                        rv = slapi_entry_attr_find ( e, "uniqueMember", &a);
1578
 
                                        if ( rv != 0 ) break;
1579
 
                                        rv = slapi_entry_attr_find ( e, "Member", &a );
1580
 
                                        if ( rv != 0 ) break;
1581
 
                                        rv = slapi_entry_attr_find ( e, "MemberURL", &a );
1582
 
                                        if ( rv != 0 ) break;
1583
 
                                        /* That means we are not changing the member
1584
 
                                        ** list, so it's okay to let go this 
1585
 
                                        ** change
1586
 
                                        */
1587
 
                                        group_change = 0;
1588
 
                                } 
1589
 
                                break;
1590
 
                        }
1591
 
                        i= slapi_attr_next_value ( attr, i, &sval );
1592
 
                }
1593
 
 
1594
 
                /*
1595
 
                ** We can do better here XXX, i.e invalidate the cache for users who
1596
 
                ** use this group. for now just do the whole thing.
1597
 
                */
1598
 
                if ( group_change )  {
1599
 
                        slapi_log_error(SLAPI_LOG_ACL, plugin_name,
1600
 
                        "Group Change: Invalidating entire UserGroup Cache %s\n",
1601
 
                        n_dn);
1602
 
                        aclg_regen_group_signature();
1603
 
                        if (  (optype == SLAPI_OPERATION_MODIFY) || (optype == SLAPI_OPERATION_DELETE ) ) {
1604
 
                                /* Then we need to invalidate the acl signature also */
1605
 
                                acl_signature = aclutil_gen_signature ( acl_signature );
1606
 
                        }
1607
 
                }
1608
 
        }
1609
 
 
1610
 
        /*
1611
 
         * Here if the target entry is in the group cache
1612
 
         * as a user then, as it's being changed it may move out of any dynamic
1613
 
         * groups it belongs to.
1614
 
         * Just remove it for now--can do better XXX by checking to see if
1615
 
         * it really needs to be removed by testing to see if he's
1616
 
         * still in th group after the change--but this requires keeping
1617
 
         * the memberURL of the group  which we don't currently do.
1618
 
         * Also, if we keep
1619
 
         * the attributes that are being used in dynamic
1620
 
         * groups then we could only remove the user if a sensitive
1621
 
         * attribute was being modified (rather than scanning the whole user cache
1622
 
         * all the time).  Also could do a hash lookup.
1623
 
         *
1624
 
         * aclg_find_userGroup() incs a refcnt so we can still refer to ugroup.
1625
 
         * aclg_markUgroupForRemoval() decs it and marks it for removal
1626
 
         * , so after that you cannot refer to ugroup.
1627
 
         *
1628
 
        */
1629
 
 
1630
 
        if ( (ugroup = aclg_find_userGroup(n_dn)) != NULL) {    
1631
 
                /*
1632
 
                 * Mark this for deletion next time round--try to impact
1633
 
                 * this mainline code as little as possible.
1634
 
                */
1635
 
                slapi_log_error(SLAPI_LOG_ACL, plugin_name,
1636
 
                        "Marking entry %s for removal from ACL user Group Cache\n",
1637
 
                        n_dn);
1638
 
                aclg_markUgroupForRemoval (ugroup);
1639
 
        }
1640
 
 
1641
 
        /*
1642
 
         * Take the write lock around all the mods--so that
1643
 
         * other operations will see the acicache either before the whole mod
1644
 
         * or after but not, as it was before, during the mod.
1645
 
         * This is in line with the LDAP concept of the operation
1646
 
         * on the whole entry being the atomic unit.
1647
 
         * 
1648
 
        */
1649
 
        
1650
 
        switch(optype) {
1651
 
           case SLAPI_OPERATION_DELETE:
1652
 
                /* In this case we have already checked if the user has 
1653
 
                ** right to delete the entry. Part of delete of entry is 
1654
 
                ** remove all the ACLs also.
1655
 
                */
1656
 
                
1657
 
                acllist_acicache_WRITE_LOCK();
1658
 
                rv = acllist_remove_aci_needsLock(e_sdn, NULL);
1659
 
                acllist_acicache_WRITE_UNLOCK();
1660
 
 
1661
 
                break;
1662
 
           case SLAPI_OPERATION_ADD:
1663
 
                slapi_entry_attr_find ( (Slapi_Entry *) change, aci_attr_type, &attr );
1664
 
 
1665
 
                if ( attr ) {
1666
 
                        Slapi_Value     *sval=NULL;
1667
 
                        const struct berval     *attrVal;
1668
 
                        int i;
1669
 
 
1670
 
                        acllist_acicache_WRITE_LOCK();
1671
 
                        i= slapi_attr_first_value ( attr,&sval );
1672
 
                        while ( i != -1 ) {
1673
 
                                attrVal = slapi_value_get_berval(sval);
1674
 
                                rv= acllist_insert_aci_needsLock(e_sdn, attrVal );
1675
 
                                if (rv <= ACL_ERR) 
1676
 
                                        aclutil_print_err(rv, e_sdn, attrVal, NULL);
1677
 
                                /* Print the aci list */
1678
 
                                i= slapi_attr_next_value ( attr, i, &sval );
1679
 
                        }
1680
 
                        acllist_acicache_WRITE_UNLOCK();                
1681
 
                }
1682
 
                break;
1683
 
 
1684
 
           case SLAPI_OPERATION_MODIFY:
1685
 
           {
1686
 
                int got_write_lock = 0;
1687
 
 
1688
 
                mods = (LDAPMod **) change;
1689
 
                
1690
 
                for (j=0;  mods[j] != NULL; j++) {
1691
 
                        if (strcasecmp(mods[j]->mod_type, aci_attr_type) == 0) {
1692
 
 
1693
 
                                /* Got an aci to mod in this list of mods, so
1694
 
                                 * take the acicache lock for the whole list of mods,
1695
 
                                 * remembering to free it below.
1696
 
                                */
1697
 
                                if ( !got_write_lock) {
1698
 
                                        acllist_acicache_WRITE_LOCK();
1699
 
                                        got_write_lock = 1;
1700
 
                                }
1701
 
 
1702
 
                           switch (mods[j]->mod_op & ~LDAP_MOD_BVALUES) {
1703
 
                           case LDAP_MOD_REPLACE:
1704
 
                                /* First remove the item */
1705
 
                                rv = acllist_remove_aci_needsLock(e_sdn, NULL);
1706
 
                                
1707
 
                                /* now fall thru to add the new one */
1708
 
                           case LDAP_MOD_ADD:
1709
 
                                /* Add the new aci */
1710
 
                                if (mods[j]->mod_op & LDAP_MOD_BVALUES) {
1711
 
                                        bvalue = mods[j]->mod_bvalues;  
1712
 
                                        if (bvalue == NULL)
1713
 
                                                break;
1714
 
                                        for (; *bvalue != NULL; ++bvalue) {
1715
 
                                                rv=acllist_insert_aci_needsLock( e_sdn, *bvalue);
1716
 
                                                if (rv <= ACL_ERR) { 
1717
 
                                                    aclutil_print_err(rv, e_sdn,
1718
 
                                                                   *bvalue, NULL);
1719
 
                                                }
1720
 
                                        }
1721
 
                                } else {
1722
 
                                        value = mods[j]->mod_values;
1723
 
                                        if (value == NULL)
1724
 
                                                break;
1725
 
                                        for (; *value != NULL; ++value) {
1726
 
                                                b.bv_len = strlen (*value);
1727
 
                                                b.bv_val = *value;
1728
 
                                                rv=acllist_insert_aci_needsLock( e_sdn, &b);
1729
 
                                                if (rv <= ACL_ERR) {
1730
 
                                                    aclutil_print_err(rv, e_sdn,
1731
 
                                                                   &b, NULL);
1732
 
                                                }
1733
 
                                        }
1734
 
                                }
1735
 
                                break;
1736
 
                           case LDAP_MOD_DELETE:
1737
 
                                if (mods[j]->mod_op & LDAP_MOD_BVALUES) {
1738
 
                                        bvalue = mods[j]->mod_bvalues;
1739
 
                                        if (bvalue == NULL || *bvalue == NULL) {
1740
 
                                                 rv = acllist_remove_aci_needsLock( e_sdn, NULL);
1741
 
                                        } else {
1742
 
                                                for (; *bvalue != NULL; ++bvalue)
1743
 
                                                   acllist_remove_aci_needsLock( e_sdn, *bvalue);
1744
 
                                        }
1745
 
                                } else {
1746
 
                                        value = mods[j]->mod_values;
1747
 
                                        if (value == NULL || *value == NULL)  {
1748
 
                                           acllist_remove_aci_needsLock( e_sdn,NULL);
1749
 
                                        } else {
1750
 
                                                for (; *value != NULL; ++value) {
1751
 
                                                        b.bv_len = strlen (*value);
1752
 
                                                        b.bv_val = *value;
1753
 
                                                        acllist_remove_aci_needsLock( e_sdn, &b);
1754
 
                                                }
1755
 
                                        }
1756
 
 
1757
 
                                }
1758
 
                                break;
1759
 
                                
1760
 
                           default:
1761
 
                                break;
1762
 
                        }/* modtype switch */
1763
 
                   }/* attrtype is aci */
1764
 
                } /* end of for */
1765
 
                if ( got_write_lock ) {
1766
 
                        acllist_acicache_WRITE_UNLOCK();                
1767
 
                        got_write_lock = 0;
1768
 
                }
1769
 
 
1770
 
                break;
1771
 
           }/* case op is modify*/
1772
 
 
1773
 
           case SLAPI_OPERATION_MODRDN:
1774
 
 
1775
 
                new_RDN = (char*) change;
1776
 
                slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
1777
 
                           "acl_modified (MODRDN %s => \"%s\"\n", 
1778
 
                           n_dn, new_RDN);
1779
 
 
1780
 
                /* compute new_DN: */
1781
 
                parent_DN = slapi_dn_parent (n_dn);
1782
 
                if (parent_DN == NULL) {
1783
 
                        new_DN = new_RDN;
1784
 
                } else {
1785
 
                        new_DN = slapi_create_dn_string("%s,%s", new_RDN, parent_DN);
1786
 
                }
1787
 
 
1788
 
                /* Change the acls */
1789
 
                acllist_acicache_WRITE_LOCK();          
1790
 
                /* acllist_moddn_aci_needsLock expects normalized new_DN, 
1791
 
                 * which is no need to be case-ignored */
1792
 
                acllist_moddn_aci_needsLock ( e_sdn, new_DN );
1793
 
                acllist_acicache_WRITE_UNLOCK();
1794
 
 
1795
 
                /* deallocat the parent_DN */
1796
 
                if (parent_DN != NULL)  {
1797
 
                        slapi_ch_free ( (void **) &new_DN );
1798
 
                        slapi_ch_free ( (void **) &parent_DN );
1799
 
                }
1800
 
                break;
1801
 
 
1802
 
           default:
1803
 
                /* print ERROR */
1804
 
                break;
1805
 
        } /*optype switch */
1806
 
                
1807
 
        slapi_sdn_free ( &e_sdn );      
1808
 
 
1809
 
}
1810
 
/***************************************************************************
1811
 
*
1812
 
* acl__scan_for_acis
1813
 
*       Scan the list and picup the correct acls for evaluation.
1814
 
*
1815
 
* Input:
1816
 
*       Acl_PBlock      *aclpb          - Main ACL pblock
1817
 
*       int                     *err;           - Any error status
1818
 
* Returns:
1819
 
*       num_handles                     - Number of handles matched to the
1820
 
*                                       - resource + 1.
1821
 
* Error Handling:
1822
 
*       None.
1823
 
*
1824
 
**************************************************************************/
1825
 
static int  
1826
 
acl__scan_for_acis(Acl_PBlock *aclpb, int *err)
1827
 
{
1828
 
        aci_t                   *aci;
1829
 
        NSErr_t                 errp;
1830
 
        int                             attr_matched;
1831
 
        int                             deny_handle;
1832
 
        int                             allow_handle;
1833
 
        int                             gen_allow_handle = ACI_MAX_ELEVEL+1;
1834
 
        int                             gen_deny_handle = ACI_MAX_ELEVEL+1;
1835
 
        PRUint32                cookie;
1836
 
        
1837
 
        TNF_PROBE_0_DEBUG(acl__scan_for_acis_start,"ACL","");
1838
 
 
1839
 
        /* 
1840
 
        ** Determine if we are traversing via the list Vs. we have our own 
1841
 
        ** generated list
1842
 
        */
1843
 
        if ( aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_LIST ||
1844
 
                        aclpb->aclpb_handles_index[0] != -1 ) {
1845
 
                        int kk = 0;
1846
 
                        while ( kk < aclpb_max_selected_acls && aclpb->aclpb_handles_index[kk] != -1 ) {
1847
 
                                slapi_log_error(SLAPI_LOG_ACL, plugin_name, "Using ACL Container:%d for evaluation\n", kk);
1848
 
                                kk++;
1849
 
                        }
1850
 
        }
1851
 
 
1852
 
        memset (&errp, 0, sizeof(NSErr_t));
1853
 
        *err = ACL_FALSE;
1854
 
        aclpb->aclpb_num_deny_handles = -1;
1855
 
        aclpb->aclpb_num_allow_handles = -1;
1856
 
        memset(aclpb->aclpb_deny_handles, 0, sizeof(aci_t *)*(ACI_MAX_ELEVEL+1));
1857
 
        memset(aclpb->aclpb_allow_handles, 0, sizeof(aci_t *)*(ACI_MAX_ELEVEL+1));
1858
 
 
1859
 
        /* Check the signature. If it has changed, start fresh */
1860
 
        if ( aclpb->aclpb_signature != acl_signature ) {
1861
 
                slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
1862
 
                                "Restart the scan -- due to acl changes\n");
1863
 
                acllist_init_scan ( aclpb->aclpb_pblock, LDAP_SCOPE_BASE, NULL );
1864
 
        }
1865
 
 
1866
 
        attr_matched = ACL_FALSE;
1867
 
        deny_handle = 0;
1868
 
        allow_handle = 0;
1869
 
 
1870
 
        aclpb->aclpb_stat_acllist_scanned++;
1871
 
        aci = acllist_get_first_aci ( aclpb, &cookie );
1872
 
 
1873
 
        while( aci ) {
1874
 
                if (acl__resource_match_aci(aclpb, aci, 0, &attr_matched)) {
1875
 
                        /* Generate the ACL list handle  */
1876
 
                        if (aci->aci_handle == NULL) {
1877
 
                                aci = acllist_get_next_aci ( aclpb, aci, &cookie );
1878
 
                                continue;
1879
 
                        }
1880
 
                        aclutil_print_aci (aci, acl_access2str (aclpb->aclpb_access));
1881
 
 
1882
 
                        if (aci->aci_type & ACI_HAS_DENY_RULE) {
1883
 
                                if (aclpb->aclpb_deny_handles[aci->aci_elevel] == NULL ) {
1884
 
                                        aclpb->aclpb_deny_handles[aci->aci_elevel] = aci;
1885
 
                                } else {
1886
 
                                   if ((gen_deny_handle + ACI_DEFAULT_ELEVEL + 1) == 
1887
 
                                        aclpb->aclpb_deny_handles_size ) {
1888
 
                                        int num = ACLPB_INCR_LIST_HANDLES +
1889
 
                                                aclpb->aclpb_deny_handles_size;
1890
 
                                        /* allocate more space */
1891
 
                                        aclpb->aclpb_deny_handles =  
1892
 
                                                (aci_t **) 
1893
 
                                                  slapi_ch_realloc (
1894
 
                                                       (void *) aclpb->aclpb_deny_handles,
1895
 
                                                       num * sizeof (aci_t *));
1896
 
                                        aclpb->aclpb_deny_handles_size = num;
1897
 
                                   }    
1898
 
                                   aclpb->aclpb_deny_handles [gen_deny_handle] = aci;
1899
 
                                   gen_deny_handle++;
1900
 
                                }
1901
 
                                deny_handle++;
1902
 
                        }
1903
 
                        /* 
1904
 
                        ** It's possible that a single acl is in both the camps i.e
1905
 
                        ** It has a allow and a deny rule 
1906
 
                        ** In that case we keep the same acl in both the camps.
1907
 
                        */ 
1908
 
                        if (aci->aci_type & ACI_HAS_ALLOW_RULE) {
1909
 
                                if (aclpb->aclpb_allow_handles[aci->aci_elevel] == NULL ) {
1910
 
                                        aclpb->aclpb_allow_handles[aci->aci_elevel] = aci;
1911
 
                                } else {
1912
 
                                   if ((gen_allow_handle + ACI_DEFAULT_ELEVEL + 1) == 
1913
 
                                        aclpb->aclpb_allow_handles_size) {
1914
 
                                        /* allocate more space */
1915
 
                                        int num = ACLPB_INCR_LIST_HANDLES +
1916
 
                                                aclpb->aclpb_allow_handles_size;
1917
 
 
1918
 
                                        aclpb->aclpb_allow_handles =  
1919
 
                                                (aci_t **) 
1920
 
                                                  slapi_ch_realloc (
1921
 
                                                       (void *) aclpb->aclpb_allow_handles,
1922
 
                                                       num * sizeof (aci_t *));
1923
 
                                        aclpb->aclpb_allow_handles_size = num;
1924
 
                                   }    
1925
 
                                   aclpb->aclpb_allow_handles [gen_allow_handle] = aci;
1926
 
                                   gen_allow_handle++;
1927
 
                                }
1928
 
                                allow_handle++;
1929
 
                        }
1930
 
                }
1931
 
                aci = acllist_get_next_aci ( aclpb, aci, &cookie );
1932
 
        } /* end of while */
1933
 
 
1934
 
        /* make the last one a null */
1935
 
        aclpb->aclpb_deny_handles [gen_deny_handle] = NULL;
1936
 
        aclpb->aclpb_allow_handles [gen_allow_handle] = NULL;
1937
 
 
1938
 
        /* specify how many we found */
1939
 
        aclpb->aclpb_num_deny_handles = deny_handle;
1940
 
        aclpb->aclpb_num_allow_handles = allow_handle;
1941
 
 
1942
 
        slapi_log_error(SLAPI_LOG_ACL, plugin_name, "Num of ALLOW Handles:%d, DENY handles:%d\n", 
1943
 
                  aclpb->aclpb_num_allow_handles, aclpb->aclpb_num_deny_handles);
1944
 
 
1945
 
        TNF_PROBE_0_DEBUG(acl__scan_for_acis_end,"ACL","");
1946
 
 
1947
 
        return(allow_handle + deny_handle);
1948
 
}
1949
 
 
1950
 
/***************************************************************************
1951
 
*
1952
 
* acl__resource_match_aci
1953
 
*
1954
 
*       This compares the ACI for the given resource and determines if
1955
 
*       the ACL applies to the resource or not.
1956
 
*
1957
 
*       For read/search operation, we collect all the possible acls which
1958
 
*       will apply, We will be using this list  for future acl evaluation
1959
 
*       for that entry.
1960
 
*
1961
 
* Input:
1962
 
*       struct acl_pblock       *aclpb - Main acl private block
1963
 
*       aci_t           *aci            - The ACI item
1964
 
*       int             skip_attrEval   - DOn't check for attrs
1965
 
*       int             *a_matched      - Attribute matched 
1966
 
*
1967
 
* Returns:
1968
 
*
1969
 
*       ACL_TRUE                        - Yep, This  ACL is applicable to the
1970
 
*                                       - the resource.
1971
 
*       ACL_FALSE                       - No it is not.
1972
 
*
1973
 
* Error Handling:
1974
 
*       None.
1975
 
*
1976
 
**************************************************************************/
1977
 
#define ACL_RIGHTS_TARGETATTR_NOT_NEEDED  ( SLAPI_ACL_ADD | SLAPI_ACL_DELETE | SLAPI_ACL_PROXY)
1978
 
static int
1979
 
acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a_matched)
1980
 
{
1981
 
 
1982
 
        struct slapi_filter     *f;                     /* filter */
1983
 
        int                                             rv;                     /* return value */
1984
 
        /* Assume that resource matches */
1985
 
        int                                             matches = ACL_TRUE;
1986
 
        int                                             attr_matched = ACL_TRUE;
1987
 
        int                                             attr_matched_in_targetattrfilters = 0;
1988
 
        int                                             dn_matched;
1989
 
        char                                    *res_attr;
1990
 
        int                                             aci_right = 0;
1991
 
        int                                             res_right = 0;
1992
 
        int                                             star_matched = ACL_FALSE;
1993
 
        int                                             num_attrs = 0;
1994
 
        AclAttrEval                             *c_attrEval = NULL;
1995
 
        const   char                    *res_ndn = NULL;
1996
 
        const   char                    *aci_ndn = NULL;
1997
 
        char                                    *matched_val = NULL;    
1998
 
        int                                             add_matched_val_to_ht = 0;
1999
 
        char                                    res_right_str[128];
2000
 
 
2001
 
        TNF_PROBE_0_DEBUG(acl__resource_match_aci_start,"ACL","");
2002
 
 
2003
 
        if (NULL == aclpb) {
2004
 
                matches = ACL_FALSE;
2005
 
                goto acl__resource_match_aci_EXIT;                      
2006
 
        }
2007
 
 
2008
 
        /* Figure out if the acl has the correct rights or not */
2009
 
        aci_right = aci->aci_access;
2010
 
        res_right = aclpb->aclpb_access;
2011
 
        if (!(aci_right & res_right)) {
2012
 
                /* If we are looking for read/search and the acl has read/search
2013
 
                ** then go further because if targets match we may keep that
2014
 
                ** acl in  the entry cache list.
2015
 
                */
2016
 
                if (!((res_right & (SLAPI_ACL_SEARCH | SLAPI_ACL_READ)) &&
2017
 
                        (aci_right & (SLAPI_ACL_SEARCH | SLAPI_ACL_READ))))
2018
 
                        matches = ACL_FALSE;
2019
 
                        goto acl__resource_match_aci_EXIT;                      
2020
 
        }
2021
 
 
2022
 
        
2023
 
        /* first Let's see if the entry is under the subtree where the
2024
 
        ** ACL resides. We can't let somebody affect a target beyond the 
2025
 
        ** scope of where the ACL resides
2026
 
        ** Example: ACL is located in "ou=engineering, o=ace industry, c=us
2027
 
        ** but if the target is "o=ace industry, c=us", then we are in trouble.
2028
 
        **
2029
 
        ** If the aci is in the rootdse and the entry is not, then we do not
2030
 
        ** match--ie. acis in the rootdse do NOT apply below...for the moment.
2031
 
        ** 
2032
 
        */
2033
 
        res_ndn = slapi_sdn_get_ndn ( aclpb->aclpb_curr_entry_sdn );
2034
 
        aci_ndn = slapi_sdn_get_ndn ( aci->aci_sdn );
2035
 
        if (!slapi_sdn_issuffix(aclpb->aclpb_curr_entry_sdn, aci->aci_sdn)
2036
 
                || (!slapi_is_rootdse(res_ndn) && slapi_is_rootdse(aci_ndn)) ) {
2037
 
 
2038
 
                /* cant' poke around */
2039
 
                matches = ACL_FALSE;
2040
 
                goto acl__resource_match_aci_EXIT;                      
2041
 
        }
2042
 
        
2043
 
        /*
2044
 
        ** We have a single ACI which we need to find if it applies to
2045
 
        ** the resource or not.
2046
 
        */
2047
 
        if ((aci->aci_type & ACI_TARGET_DN) && (aclpb->aclpb_curr_entry_sdn)) {
2048
 
                char            *avaType;
2049
 
                struct berval   *avaValue;              
2050
 
 
2051
 
                f = aci->target; 
2052
 
                dn_matched = ACL_TRUE;
2053
 
                slapi_filter_get_ava ( f, &avaType, &avaValue );
2054
 
                
2055
 
                if (!slapi_dn_issuffix( res_ndn, avaValue->bv_val)) {
2056
 
                        dn_matched = ACL_FALSE;
2057
 
                }
2058
 
                if (aci->aci_type & ACI_TARGET_NOT) {
2059
 
                        matches = (dn_matched ? ACL_FALSE : ACL_TRUE);
2060
 
                } else {
2061
 
                        matches = (dn_matched ? ACL_TRUE: ACL_FALSE);
2062
 
                }
2063
 
        }
2064
 
        
2065
 
        /* No need to look further */
2066
 
        if (matches == ACL_FALSE) {
2067
 
                goto acl__resource_match_aci_EXIT;      
2068
 
        }
2069
 
 
2070
 
        if (aci->aci_type & ACI_TARGET_PATTERN) {
2071
 
                
2072
 
                f = aci->target; 
2073
 
                dn_matched = ACL_TRUE;
2074
 
        
2075
 
                if ((rv = acl_match_substring(f, (char *)res_ndn, 0 /* match suffux */)) != ACL_TRUE) {
2076
 
                        dn_matched = ACL_FALSE;
2077
 
                        if(rv == ACL_ERR) {
2078
 
                                slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
2079
 
                                        "acl__resource_match_aci:pattern err\n");
2080
 
                                matches = ACL_FALSE;
2081
 
                                goto acl__resource_match_aci_EXIT;      
2082
 
                        }
2083
 
                }
2084
 
                if (aci->aci_type & ACI_TARGET_NOT) {
2085
 
                        matches = (dn_matched ? ACL_FALSE : ACL_TRUE);
2086
 
                } else {
2087
 
                        matches = (dn_matched ? ACL_TRUE: ACL_FALSE);
2088
 
                }
2089
 
        }
2090
 
 
2091
 
        /* No need to look further */
2092
 
        if (matches == ACL_FALSE) {
2093
 
                goto acl__resource_match_aci_EXIT;      
2094
 
        }
2095
 
 
2096
 
        /*
2097
 
         * Is it a (target="ldap://cn=*,($dn),o=sun.com") kind of thing.
2098
 
        */
2099
 
        if (aci->aci_type & ACI_TARGET_MACRO_DN) {
2100
 
                /*
2101
 
                 * See if the ($dn) component matches the string and
2102
 
                 * retrieve the matched substring for later use
2103
 
                 * in the userdn.
2104
 
                 * The macro string is a function of the dn only, so if the
2105
 
                 * entry is the same one don't recalculate it--
2106
 
                 * this flag only works for search right now, could
2107
 
                 * also optimise for mods by making it work for mods.
2108
 
                */
2109
 
                        
2110
 
                if ( (aclpb->aclpb_res_type & ACLPB_NEW_ENTRY) == 0 ) {
2111
 
                        /*
2112
 
                         * Here same entry so just look up the matched value,
2113
 
                         * calculated from the targetdn and stored judiciously there
2114
 
                         */
2115
 
                        matched_val = (char *)acl_ht_lookup( aclpb->aclpb_macro_ht,
2116
 
                                                                                (PLHashNumber)aci->aci_index);
2117
 
                }
2118
 
                if ( matched_val == NULL &&
2119
 
                        (aclpb->aclpb_res_type & (ACLPB_NEW_ENTRY | ACLPB_EFFECTIVE_RIGHTS))) {
2120
 
 
2121
 
                        slapi_log_error (SLAPI_LOG_ACL, plugin_name,
2122
 
                                "Evaluating macro aci(%d)%s for resource %s\n",
2123
 
                                aci->aci_index, aci->aclName,
2124
 
                                aclutil__access_str(res_right, res_right_str));
2125
 
                        matched_val = acl_match_macro_in_target( res_ndn,
2126
 
                                                                                                aci->aci_macro->match_this,
2127
 
                                                                                                aci->aci_macro->macro_ptr);
2128
 
                        add_matched_val_to_ht = 1; /* may need to add matched value to ht */
2129
 
                }
2130
 
                if (matched_val == NULL) {
2131
 
                        dn_matched = ACL_FALSE;
2132
 
                } else {
2133
 
                        dn_matched = ACL_TRUE;
2134
 
                }
2135
 
                                                                                                                
2136
 
                if (aci->aci_type & ACI_TARGET_NOT) {
2137
 
                        matches = (dn_matched ? ACL_FALSE : ACL_TRUE);
2138
 
                } else {
2139
 
                        matches = (dn_matched ? ACL_TRUE: ACL_FALSE);
2140
 
                }
2141
 
                
2142
 
                if ( add_matched_val_to_ht ) {
2143
 
                        if ( matches == ACL_TRUE && matched_val ) {
2144
 
                                /*
2145
 
                                 * matched_val may be needed later for matching on
2146
 
                                 * other targets or on the subject--so optimistically
2147
 
                                 * put it in the hash table.
2148
 
                                 * If, at the end of this routine, we
2149
 
                                 * find that after all the resource did not match then
2150
 
                                 * that's ok--the value is freed at aclpb cleanup time.
2151
 
                                 * If there is already an entry for this aci in this
2152
 
                                 * aclpb then remove it--it's an old value for a
2153
 
                                 * different entry.
2154
 
                                */
2155
 
 
2156
 
                                acl_ht_add_and_freeOld(aclpb->aclpb_macro_ht,
2157
 
                                                                        (PLHashNumber)aci->aci_index,
2158
 
                                                                        matched_val);
2159
 
                                slapi_log_error (SLAPI_LOG_ACL, plugin_name,
2160
 
                                        "-- Added aci(%d) and matched value (%s) to macro ht\n",
2161
 
                                        aci->aci_index, matched_val);
2162
 
                                acl_ht_display_ht(aclpb->aclpb_macro_ht);
2163
 
                        } else {
2164
 
                                slapi_ch_free((void **)&matched_val);
2165
 
                                if (matches == ACL_FALSE) {
2166
 
                                        slapi_log_error (SLAPI_LOG_ACL, plugin_name,
2167
 
                                                "Evaluated ACL_FALSE\n");
2168
 
                                }
2169
 
                        }
2170
 
                }
2171
 
        } /* MACRO_DN */
2172
 
 
2173
 
        /* No need to look further */
2174
 
        if (matches == ACL_FALSE) {
2175
 
                goto acl__resource_match_aci_EXIT;      
2176
 
        }
2177
 
 
2178
 
        /* 
2179
 
        ** Here, if there's a targetfilter field, see if it matches.
2180
 
        **
2181
 
        ** The commented out code below was an erroneous attempt to skip
2182
 
        ** this test.  It is wrong because: 1. you need to store
2183
 
        ** whether the last test matched or not (you cannot just assume it did)
2184
 
        ** and 2. It may not be the same aci, so the previous matched
2185
 
        ** value is a function of the aci.
2186
 
        ** May be interesting to build such a cache...but no evidence for
2187
 
        ** for that right now. See Bug 383424.
2188
 
        **
2189
 
        ** 
2190
 
        **   && ((aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_LIST) ||
2191
 
        **      (aclpb->aclpb_res_type & ACLPB_NEW_ENTRY))
2192
 
        */
2193
 
        if (aci->aci_type & ACI_TARGET_FILTER ) {
2194
 
                int     filter_matched = ACL_TRUE;
2195
 
 
2196
 
                /*
2197
 
                 * Check for macros.
2198
 
                 * For targetfilter we need to fake the lasinfo structure--it's
2199
 
                 * created "naturally" for subjects but not targets.
2200
 
                */
2201
 
                
2202
 
 
2203
 
                if ( aci->aci_type &  ACI_TARGET_FILTER_MACRO_DN) {                     
2204
 
                                
2205
 
                        lasInfo *lasinfo = NULL;
2206
 
                        
2207
 
                        lasinfo = (lasInfo*) slapi_ch_malloc( sizeof(lasInfo) );
2208
 
 
2209
 
                        lasinfo->aclpb = aclpb;
2210
 
                        lasinfo->resourceEntry = aclpb->aclpb_curr_entry;
2211
 
                        aclpb->aclpb_curr_aci = aci;
2212
 
                        filter_matched = aclutil_evaluate_macro( aci->targetFilterStr,
2213
 
                                                                                                        lasinfo,
2214
 
                                                                                                        ACL_EVAL_TARGET_FILTER);
2215
 
                        slapi_ch_free((void**)&lasinfo);
2216
 
                } else {
2217
 
 
2218
 
 
2219
 
                        if (slapi_vattr_filter_test(NULL, aclpb->aclpb_curr_entry, 
2220
 
                                aci->targetFilter,
2221
 
                                0 /*don't do acess chk*/)!= 0) {
2222
 
                                filter_matched = ACL_FALSE;
2223
 
                        }
2224
 
 
2225
 
                }
2226
 
 
2227
 
                /* If it's a logical value we can do logic on it...otherwise we do not match */
2228
 
                if ( filter_matched == ACL_TRUE || filter_matched == ACL_FALSE) {
2229
 
                        if (aci->aci_type & ACI_TARGET_FILTER_NOT) {
2230
 
                                matches = (filter_matched == ACL_TRUE ? ACL_FALSE : ACL_TRUE);
2231
 
                        } else {
2232
 
                                matches = (filter_matched == ACL_TRUE ? ACL_TRUE: ACL_FALSE);
2233
 
                        }
2234
 
                } else {
2235
 
                        matches = ACL_FALSE;
2236
 
                        slapi_log_error( SLAPI_LOG_ACL, plugin_name,
2237
 
                                "Returning UNDEFINED for targetfilter evaluation.\n");
2238
 
                }
2239
 
 
2240
 
                if (matches == ACL_FALSE) {
2241
 
                        goto acl__resource_match_aci_EXIT;      
2242
 
                }
2243
 
        }
2244
 
 
2245
 
        /*
2246
 
         * Check to see if we need to evaluate any targetattrfilters.
2247
 
         * They look as follows:
2248
 
         * (targetattrfilters="add=sn:(sn=rob) && gn:(gn!=byrne),
2249
 
         *                                         del=sn:(sn=rob) && gn:(gn=byrne)")
2250
 
         *
2251
 
         * For ADD/DELETE:
2252
 
         * If theres's a targetattrfilter then each add/del filter
2253
 
         * that applies to an attribute in the entry, must be satisfied
2254
 
         * by each value of the attribute in the entry.
2255
 
         *
2256
 
         * For MODIFY:
2257
 
         *      If there's a targetattrfilter then the add/del filter
2258
 
         * must be satisfied by the attribute to be added/deleted.
2259
 
         * (MODIFY acl is evaluated one value at a time).
2260
 
         * 
2261
 
         *
2262
 
        */
2263
 
 
2264
 
        if (((aclpb->aclpb_access & SLAPI_ACL_ADD) &&
2265
 
                 (aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS) )||
2266
 
                ((aclpb->aclpb_access & SLAPI_ACL_DELETE) && 
2267
 
                 (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS) ) ) {
2268
 
                
2269
 
                        Targetattrfilter **attrFilterArray;
2270
 
 
2271
 
                        Targetattrfilter        *attrFilter = NULL;
2272
 
 
2273
 
                        Slapi_Attr      *attr_ptr = NULL;
2274
 
                        Slapi_Value *sval;
2275
 
                        const struct berval *attrVal;
2276
 
                        int k;
2277
 
                        int done;
2278
 
 
2279
 
 
2280
 
                        if (aclpb->aclpb_access & SLAPI_ACL_ADD &&
2281
 
                                aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS) {
2282
 
 
2283
 
                                attrFilterArray = aci->targetAttrAddFilters;
2284
 
 
2285
 
                        } else if (aclpb->aclpb_access & SLAPI_ACL_DELETE && 
2286
 
                                                aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS) {
2287
 
                                
2288
 
                                attrFilterArray = aci->targetAttrDelFilters;
2289
 
 
2290
 
                        }
2291
 
 
2292
 
                        attr_matched = ACL_TRUE;
2293
 
                        num_attrs = 0;
2294
 
 
2295
 
                        while (attrFilterArray[num_attrs] && attr_matched) {
2296
 
                                attrFilter = attrFilterArray[num_attrs];
2297
 
 
2298
 
                                /* 
2299
 
                                 * If this filter applies to an attribute in the entry,
2300
 
                                 * apply it to the entry.
2301
 
                                 * Otherwise just ignore it.
2302
 
                                 * 
2303
 
                                */
2304
 
 
2305
 
                                if (slapi_entry_attr_find ( aclpb->aclpb_curr_entry,
2306
 
                                                                                   attrFilter->attr_str,
2307
 
                                                                                   &attr_ptr) == 0)  {
2308
 
 
2309
 
                                        /*
2310
 
                                         * This is an applicable filter.
2311
 
                                         *  The filter is to be appplied to the entry being added
2312
 
                                         * or deleted.
2313
 
                                         * The filter needs to be satisfied by _each_ occurence
2314
 
                                         * of the attribute in the entry--otherwise you
2315
 
                                         * could satisfy the filter and then put loads of other
2316
 
                                         * values in on the back of it.
2317
 
                                        */
2318
 
 
2319
 
                                        sval=NULL;
2320
 
                                        attrVal=NULL;
2321
 
                                        k= slapi_attr_first_value(attr_ptr,&sval);
2322
 
                                        done = 0;
2323
 
                                        while(k != -1 && !done) {
2324
 
                                                attrVal = slapi_value_get_berval(sval);
2325
 
 
2326
 
                                                if ( acl__make_filter_test_entry(
2327
 
                                &aclpb->aclpb_filter_test_entry,
2328
 
                                                                attrFilter->attr_str,
2329
 
                                                                (struct berval *)attrVal) == LDAP_SUCCESS ) {                      
2330
 
                                
2331
 
                                                        attr_matched= acl__test_filter( 
2332
 
                                        aclpb->aclpb_filter_test_entry,
2333
 
                                                                                attrFilter->filter,
2334
 
                                                                                1 /* Do filter sense evaluation below */
2335
 
                                                                                );
2336
 
                                                        done = !attr_matched;
2337
 
                                                        slapi_entry_free( aclpb->aclpb_filter_test_entry );                     
2338
 
                                                }                                           
2339
 
                                                
2340
 
                                                k= slapi_attr_next_value(attr_ptr, k, &sval);
2341
 
                                        }/* while */
2342
 
 
2343
 
                                        /*
2344
 
                                         * Here, we applied an applicable filter to the entry.
2345
 
                                         * So if attr_matched is ACL_TRUE then every value
2346
 
                                         * of the attribute in the entry satisfied the filter.
2347
 
                                         * Otherwise, attr_matched is ACL_FALSE and not every 
2348
 
                                         * value satisfied the filter, so we will teminate the
2349
 
                                         * scan of the filter list.                                     
2350
 
                                        */
2351
 
 
2352
 
                                }
2353
 
 
2354
 
                                num_attrs++;
2355
 
                        } /* while */
2356
 
 
2357
 
                /*
2358
 
                 * Here, we've applied all the applicable filters to the entry.
2359
 
                 * Each one must have been satisfied by all the values of the attribute.
2360
 
                 * The result of this is stored in attr_matched.
2361
 
                */              
2362
 
 
2363
 
#if 0           
2364
 
                /*
2365
 
                 * Don't support a notion of "add != " or "del != "
2366
 
                 * at the moment.
2367
 
                 * To do this, need to test whether it's an add test or del test
2368
 
                 * then if it's add and ACI_TARGET_ATTR_ADD_FILTERS_NOT then
2369
 
                 * flip the bit.  Same for del.
2370
 
                */
2371
 
 
2372
 
                if (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS_NOT) {
2373
 
                        matches = (matches ? ACL_FALSE : ACL_TRUE);
2374
 
                } else {
2375
 
                        matches = (matches ? ACL_TRUE: ACL_FALSE);
2376
 
                }
2377
 
#endif
2378
 
 
2379
 
                /* No need to look further */
2380
 
                if (attr_matched == ACL_FALSE) {
2381
 
                        matches = ACL_FALSE;
2382
 
                        goto acl__resource_match_aci_EXIT;      
2383
 
                }
2384
 
 
2385
 
        } else  if ( ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD) &&
2386
 
                  (aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) ||
2387
 
                 ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL) &&
2388
 
                  (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)) ) {
2389
 
 
2390
 
            
2391
 
                /*     
2392
 
                 * Here, it's a modify add/del and we have attr filters.  
2393
 
                 * So, we need to scan the add/del filter list to find the filter
2394
 
                 * that applies to the current attribute.
2395
 
                 * Then the (attribute,value) pair being added/deleted better
2396
 
                 * match that filter.
2397
 
                 *
2398
 
                 *
2399
 
                 */
2400
 
 
2401
 
                Targetattrfilter **attrFilterArray = NULL;
2402
 
                Targetattrfilter        *attrFilter;
2403
 
                int found = 0;
2404
 
 
2405
 
                if ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD) &&
2406
 
                        (aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) {
2407
 
 
2408
 
                        attrFilterArray = aci->targetAttrAddFilters;
2409
 
 
2410
 
                } else if ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL) && 
2411
 
                                   (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)) {
2412
 
                                
2413
 
                        attrFilterArray = aci->targetAttrDelFilters;
2414
 
 
2415
 
                }
2416
 
                
2417
 
 
2418
 
                /*
2419
 
                 * Scan this filter list for an applicable filter.
2420
 
                 */
2421
 
 
2422
 
                found = 0;
2423
 
                num_attrs = 0;
2424
 
 
2425
 
                while (attrFilterArray[num_attrs] && !found) {
2426
 
                                attrFilter = attrFilterArray[num_attrs];
2427
 
 
2428
 
                        /* If this filter applies to the attribute, stop. */
2429
 
                        if ((aclpb->aclpb_curr_attrEval) &&
2430
 
                                slapi_attr_type_cmp ( aclpb->aclpb_curr_attrEval->attrEval_name,
2431
 
                                                                          attrFilter->attr_str, 1) == 0) {
2432
 
                                found = 1;
2433
 
                        }
2434
 
                        num_attrs++;
2435
 
                }
2436
 
 
2437
 
                /*
2438
 
                 * Here, if found an applicable filter, then apply the filter to the 
2439
 
                 * (attr,val) pair.
2440
 
                 * Otherwise, ignore the targetattrfilters.
2441
 
                */
2442
 
 
2443
 
                if (found) {
2444
 
 
2445
 
                        if ( acl__make_filter_test_entry(
2446
 
                                &aclpb->aclpb_filter_test_entry,
2447
 
                                                                aclpb->aclpb_curr_attrEval->attrEval_name,
2448
 
                                                                aclpb->aclpb_curr_attrVal) == LDAP_SUCCESS ) {                      
2449
 
                                
2450
 
                                attr_matched= acl__test_filter(aclpb->aclpb_filter_test_entry,
2451
 
                                                                                attrFilter->filter,
2452
 
                                                                                1 /* Do filter sense evaluation below */
2453
 
                                                                                );                            
2454
 
                                slapi_entry_free( aclpb->aclpb_filter_test_entry );                     
2455
 
                        }           
2456
 
 
2457
 
                        /* No need to look further */
2458
 
                        if (attr_matched == ACL_FALSE) {
2459
 
                                matches = attr_matched;
2460
 
                                goto acl__resource_match_aci_EXIT;
2461
 
                        }
2462
 
 
2463
 
                        /*
2464
 
                         * Here this attribute appeared and was matched in a
2465
 
                         * targetattrfilters list, so record this fact so we do
2466
 
                         * not have to scan the targetattr list for the attribute.
2467
 
                        */
2468
 
                
2469
 
                        attr_matched_in_targetattrfilters = 1;
2470
 
                }                                
2471
 
        } /* targetvaluefilters */ 
2472
 
        
2473
 
 
2474
 
        /* There are 3 cases  by which acis are selected.
2475
 
        ** 1) By scanning the whole list and picking based on the resource.
2476
 
        ** 2) By picking a subset of the list which will be used for the whole
2477
 
        **    acl evaluation. 
2478
 
        ** 3) A finer granularity, i.e, a selected list of acls which will be
2479
 
        ** used for only that entry's evaluation.
2480
 
        */
2481
 
        if ( !(skip_attrEval) && (aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_ENTRY_LIST) &&
2482
 
                (res_right & SLAPI_ACL_SEARCH) && 
2483
 
                ((aci->aci_access & SLAPI_ACL_READ) || (aci->aci_access & SLAPI_ACL_SEARCH))) {
2484
 
                int     kk=0;
2485
 
 
2486
 
                while ( kk < aclpb_max_selected_acls && aclpb->aclpb_handles_index[kk] >=0 ) kk++;
2487
 
                if (kk >= aclpb_max_selected_acls)  {
2488
 
                        aclpb->aclpb_state &= ~ACLPB_SEARCH_BASED_ON_ENTRY_LIST;
2489
 
                } else {
2490
 
                        aclpb->aclpb_handles_index[kk++] = aci->aci_index;
2491
 
                        aclpb->aclpb_handles_index[kk] = -1;
2492
 
                }
2493
 
        }
2494
 
 
2495
 
 
2496
 
        /* If we are suppose to skip attr eval, then let's skip it */
2497
 
        if ( (aclpb->aclpb_access & SLAPI_ACL_SEARCH ) && ( ! skip_attrEval ) &&
2498
 
                ( aclpb->aclpb_res_type &  ACLPB_NEW_ENTRY )) {
2499
 
                aclEvalContext          *c_evalContext = &aclpb->aclpb_curr_entryEval_context;
2500
 
                int                     nhandle = c_evalContext->acle_numof_tmatched_handles;
2501
 
 
2502
 
                if ( nhandle < aclpb_max_selected_acls) {
2503
 
                   c_evalContext->acle_handles_matched_target[nhandle] = aci->aci_index;
2504
 
                   c_evalContext->acle_numof_tmatched_handles++;
2505
 
                }
2506
 
        }
2507
 
 
2508
 
        if ( skip_attrEval ) {
2509
 
                goto acl__resource_match_aci_EXIT;
2510
 
        }
2511
 
 
2512
 
        /* We need to check again because we don't want to select this handle 
2513
 
        ** if the right doesn't match for now.
2514
 
        */
2515
 
        if (!(aci_right & res_right)) {
2516
 
                matches = ACL_FALSE;
2517
 
                goto acl__resource_match_aci_EXIT;
2518
 
        }
2519
 
 
2520
 
    /*
2521
 
     * Here if the request is one that requires matching 
2522
 
     * on a targetattr then do it here.
2523
 
     * If we have already matched an attribute in the targetattrfitlers list
2524
 
     * then we do not require a match in the targetattr so we can skip it.
2525
 
     * The operations that require targetattr are SLAPI_ACL_COMPARE,
2526
 
     * SLAPI_ACL_SEARCH, SLAPI_ACL_READ and SLAPI_ACL_WRITE, as long as
2527
 
     * c_attrEval is non-null (otherwise it's a modrdn op which
2528
 
     * does not require the targetattr list).     
2529
 
     *
2530
 
         * rbyrneXXX if we had a proper permission for modrdn eg SLAPI_ACL_MODRDN
2531
 
         * then we would not need this crappy way of telling it was a MODRDN
2532
 
         * request ie. SLAPI_ACL_WRITE && !(c_attrEval).
2533
 
    */
2534
 
    
2535
 
        c_attrEval = aclpb->aclpb_curr_attrEval;
2536
 
    
2537
 
    /*
2538
 
     * If we've already matched on targattrfilter then do not
2539
 
     * bother to look at the attrlist.
2540
 
    */
2541
 
    
2542
 
    if (!attr_matched_in_targetattrfilters) {                
2543
 
            
2544
 
        /* match target attr */
2545
 
        if ((c_attrEval) && 
2546
 
                (aci->aci_type & ACI_TARGET_ATTR))      {
2547
 
                        /* there is a target ATTR */
2548
 
                        Targetattr      **attrArray = aci->targetAttr;
2549
 
                        Targetattr      *attr = NULL;
2550
 
 
2551
 
                        res_attr = c_attrEval->attrEval_name;
2552
 
                        attr_matched = ACL_FALSE;
2553
 
                        star_matched = ACL_FALSE;
2554
 
                        num_attrs = 0;
2555
 
 
2556
 
                        while (attrArray[num_attrs] && !attr_matched) {
2557
 
                                attr = attrArray[num_attrs];           
2558
 
                    if (attr->attr_type & ACL_ATTR_STRING) { 
2559
 
                                        if (slapi_attr_type_cmp ( res_attr, 
2560
 
                                                        attr->u.attr_str, 1) == 0) {
2561
 
                                                attr_matched = ACL_TRUE;
2562
 
                                                *a_matched = ACL_TRUE;
2563
 
                                        } 
2564
 
                                } else if (attr->attr_type & ACL_ATTR_FILTER) {
2565
 
                                        if (ACL_TRUE == acl_match_substring (
2566
 
                                                                attr->u.attr_filter, 
2567
 
                                                                res_attr, 1)) {
2568
 
                                                attr_matched = ACL_TRUE;
2569
 
                                                *a_matched = ACL_TRUE;
2570
 
                                        }
2571
 
                                } else if (attr->attr_type & ACL_ATTR_STAR) {
2572
 
                                        attr_matched = ACL_TRUE;
2573
 
                                        *a_matched = ACL_TRUE;
2574
 
                                        star_matched = ACL_TRUE;
2575
 
                                } 
2576
 
                                num_attrs++;
2577
 
                        }
2578
 
 
2579
 
                        if (aci->aci_type & ACI_TARGET_ATTR_NOT) {
2580
 
                                matches = (attr_matched ? ACL_FALSE : ACL_TRUE);
2581
 
                        } else {
2582
 
                                matches = (attr_matched ? ACL_TRUE: ACL_FALSE);
2583
 
                        }
2584
 
 
2585
 
 
2586
 
                        aclpb->aclpb_state &= ~ACLPB_ATTR_STAR_MATCHED;
2587
 
                        /* figure out how it matched, i.e star matched */
2588
 
                        if (matches && star_matched && num_attrs == 1 &&
2589
 
                                !(aclpb->aclpb_state & ACLPB_FOUND_ATTR_RULE))
2590
 
                                aclpb->aclpb_state |= ACLPB_ATTR_STAR_MATCHED;
2591
 
                        else {
2592
 
                                /* we are here means that there is a specific 
2593
 
                                ** attr in the rule for this resource.
2594
 
                                ** We need to avoid this case
2595
 
                                ** Rule 1: (targetattr = "uid")
2596
 
                                ** Rule 2: (targetattr = "*")
2597
 
                                ** we cannot use STAR optimization
2598
 
                                */
2599
 
                                aclpb->aclpb_state |=  ACLPB_FOUND_ATTR_RULE;
2600
 
                                aclpb->aclpb_state &=  ~ACLPB_ATTR_STAR_MATCHED;
2601
 
                        }
2602
 
        } else if ( (c_attrEval) ||
2603
 
                    (aci->aci_type & ACI_TARGET_ATTR)) {
2604
 
                if ((aci_right & ACL_RIGHTS_TARGETATTR_NOT_NEEDED) &&
2605
 
                    (aclpb->aclpb_access & ACL_RIGHTS_TARGETATTR_NOT_NEEDED)) {
2606
 
                        /* 
2607
 
                        ** Targetattr rule doesn't  make any sense
2608
 
                        ** in this case. So select this rule
2609
 
                        ** default: matches = ACL_TRUE;
2610
 
                        */
2611
 
                        ;
2612
 
                } else if (aci_right & SLAPI_ACL_WRITE && 
2613
 
                          (aci->aci_type & ACI_TARGET_ATTR) &&
2614
 
                          !(c_attrEval)) {
2615
 
                        /* We need to handle modrdn operation.  Modrdn doesn't 
2616
 
                        ** change any attrs but changes the RDN and so (attr=NULL).
2617
 
                        ** Here we found an acl which has a targetattr but
2618
 
                        ** the resource doesn't need one. In that case, we should
2619
 
                        ** consider this acl.
2620
 
                        ** default: matches = ACL_TRUE;
2621
 
                        */
2622
 
                        ;
2623
 
                } else {
2624
 
                        matches = ACL_FALSE;
2625
 
                }
2626
 
        }
2627
 
        }/* !attr_matched_in_targetattrfilters */
2628
 
   
2629
 
        /* 
2630
 
        ** Here we are testing if we find a entry test rule (which should
2631
 
        ** be rare). In that case, just remember it. An entry test rule
2632
 
        ** doesn't have "(targetattr)".
2633
 
        */
2634
 
        if ((aclpb->aclpb_state & ACLPB_EVALUATING_FIRST_ATTR) &&
2635
 
                (!(aci->aci_type & ACI_TARGET_ATTR))) {
2636
 
                aclpb->aclpb_state |= ACLPB_FOUND_A_ENTRY_TEST_RULE;
2637
 
        }
2638
 
 
2639
 
        /*
2640
 
         * Generic exit point for this routine:
2641
 
         * matches is ACL_TRUE if the aci matches the target of the resource,
2642
 
         * ACL_FALSE othrewise.
2643
 
         * Apologies for the goto--this is a retro-fitted exit point.
2644
 
        */
2645
 
acl__resource_match_aci_EXIT:
2646
 
 
2647
 
        /*
2648
 
         * For macro acis, there may be a partial macro string
2649
 
         * placed in the aclpb_macro_ht
2650
 
         * even if the aci did not finally match.
2651
 
         * All the partial strings will be freed at aclpb
2652
 
         * cleanup time.
2653
 
         */
2654
 
        if (ACL_TRUE == matches) {
2655
 
                aclpb->aclpb_stat_aclres_matched++;
2656
 
        }
2657
 
 
2658
 
        TNF_PROBE_0_DEBUG(acl__resource_match_aci_end,"ACL","");
2659
 
 
2660
 
        return (matches);
2661
 
}
2662
 
/* Macro to determine if the cached result is valid or not. */
2663
 
#define ACL_CACHED_RESULT_VALID( result)                                \
2664
 
        (((result & ACLPB_CACHE_READ_RES_ALLOW) &&                      \
2665
 
                (result & ACLPB_CACHE_READ_RES_SKIP)) ||                \
2666
 
            ((result & ACLPB_CACHE_SEARCH_RES_ALLOW) &&                 \
2667
 
                (result & ACLPB_CACHE_SEARCH_RES_SKIP))) ? 0 : 1
2668
 
/***************************************************************************
2669
 
*
2670
 
* acl__TestRights
2671
 
*
2672
 
*       Test the rights and find out if access is allowed or not.
2673
 
*
2674
 
*       Processing Alogorithm:
2675
 
*       
2676
 
*       First, process the DENY rules one by one. If the user is not explicitly
2677
 
*       denied, then check if the user is allowed by processing the ALLOW handles
2678
 
*       one by one.
2679
 
*       The result of the evaluation is cached. Exceptions are
2680
 
*         -- If an acl happens to be in both DENY and ALLOW camp.
2681
 
*         -- Only interested for READ/SEARCH right.
2682
 
*
2683
 
* Input:
2684
 
*       struct acl_pblock       *aclpb - main acl private block
2685
 
*       int                                     access  - The access bits
2686
 
*       char                            **right         - The right we are looking for
2687
 
*       char                            ** generic      - Generic rights
2688
 
*
2689
 
* Returns:
2690
 
*
2691
 
*       ACL_RES_ALLOW                   - Access allowed
2692
 
*       ACL_RES_DENY                    - Access denied
2693
 
*       err                             - error condition
2694
 
*
2695
 
* Error Handling:
2696
 
*       None.
2697
 
*
2698
 
**************************************************************************/
2699
 
static int
2700
 
acl__TestRights(Acl_PBlock *aclpb,int access, char **right, char ** map_generic,
2701
 
                                aclResultReason_t *result_reason)
2702
 
{
2703
 
        ACLEvalHandle_t         *acleval;
2704
 
        int                     rights_rv = ACL_RES_DENY;
2705
 
        int                     rv, i,j, k;
2706
 
        int                             index;
2707
 
        char                    *deny = NULL;
2708
 
        char                    *deny_generic = NULL;
2709
 
        char                    *acl_tag;
2710
 
        int                     expr_num;
2711
 
        char                    *testRights[2];
2712
 
        aci_t                   *aci = NULL;
2713
 
        int                     numHandles = 0;
2714
 
        
2715
 
        TNF_PROBE_0_DEBUG(acl__TestRights_start,"ACL","");
2716
 
 
2717
 
        /* record the aci and reason for access decision */
2718
 
        result_reason->deciding_aci = NULL;
2719
 
        result_reason->reason = ACL_REASON_NONE;
2720
 
 
2721
 
        /* If we don't have any ALLLOW handles, it's DENY by default */
2722
 
        if (aclpb->aclpb_num_allow_handles <= 0) {
2723
 
                result_reason->deciding_aci = NULL;
2724
 
                result_reason->reason = ACL_REASON_NO_MATCHED_RESOURCE_ALLOWS;
2725
 
 
2726
 
                TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
2727
 
                                                        tnf_string,no_allows,"");       
2728
 
 
2729
 
                return ACL_RES_DENY;
2730
 
        }
2731
 
 
2732
 
        /* Get the ACL evaluation Context */
2733
 
        acleval =  aclpb->aclpb_acleval;
2734
 
 
2735
 
        testRights[0] = *right;
2736
 
        testRights[1] = '\0';
2737
 
        
2738
 
        /* 
2739
 
        ** START PROCESSING DENY HANDLES
2740
 
        ** Process each handle at a time. Do not concatenate the handles or else
2741
 
        ** all the context information will be build again and we will pay a
2742
 
        ** lot of penalty. The context is built the first time the handle is
2743
 
        ** processed.
2744
 
        **
2745
 
        ** First we set the default to INVALID so that if rules are not matched, then
2746
 
        ** we get INVALID and if a rule matched, the we get DENY.
2747
 
        */
2748
 
        aclpb->aclpb_state &= ~ACLPB_EXECUTING_ALLOW_HANDLES;
2749
 
        aclpb->aclpb_state |= ACLPB_EXECUTING_DENY_HANDLES;
2750
 
        ACL_SetDefaultResult (NULL, acleval, ACL_RES_INVALID);
2751
 
 
2752
 
        numHandles = ACI_MAX_ELEVEL + aclpb->aclpb_num_deny_handles;
2753
 
        for (i=0, k=0; i < numHandles && k < aclpb->aclpb_num_deny_handles ; ++i) {
2754
 
                int skip_eval = 0;
2755
 
 
2756
 
                /* 
2757
 
                ** If the handle has been evaluated before, we can
2758
 
                ** cache the result.
2759
 
                */
2760
 
                if ((aci = aclpb->aclpb_deny_handles[i]) == NULL) {
2761
 
                        if (i <= ACI_MAX_ELEVEL) {
2762
 
                                continue;
2763
 
                        } else {
2764
 
                                break;
2765
 
                        }
2766
 
                }
2767
 
                k++;
2768
 
                index = aci->aci_index;
2769
 
                slapi_log_error(SLAPI_LOG_ACL, plugin_name,
2770
 
                        "Evaluating DENY aci(%d) \"%s\"\n", index, aci->aclName);
2771
 
 
2772
 
                if (access  & ( SLAPI_ACL_SEARCH | SLAPI_ACL_READ)) {
2773
 
 
2774
 
                        /*
2775
 
                         * aclpb->aclpb_cache_result[0..aclpb->aclpb_last_cache_result] is
2776
 
                         * a cache of info about whether applicable acis
2777
 
                         * allowed, did_not_allow or denied access
2778
 
                        */                      
2779
 
                        for (j =0; j < aclpb->aclpb_last_cache_result; j++) {
2780
 
                                if (index == aclpb->aclpb_cache_result[j].aci_index) {
2781
 
                                        short  result;
2782
 
 
2783
 
                                        result = aclpb->aclpb_cache_result[j].result;
2784
 
                                        if ( result <= 0) break;
2785
 
                                        if (!ACL_CACHED_RESULT_VALID(result)) {
2786
 
                                                /* something is wrong. Need to evaluate */
2787
 
                                                aclpb->aclpb_cache_result[j].result = -1;
2788
 
                                                break;
2789
 
                                        }
2790
 
                                        /*
2791
 
                                        ** We have a valid cached result. Let's see if we 
2792
 
                                        ** have what we need.
2793
 
                                        */
2794
 
                                        if (access & SLAPI_ACL_SEARCH) {
2795
 
                                                if ( result & ACLPB_CACHE_SEARCH_RES_DENY){
2796
 
                                                        slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
2797
 
                                                           "DENY:Found SEARCH DENY in cache\n");
2798
 
                                                        __acl_set_aclIndex_inResult ( aclpb, access, index );
2799
 
                                                        result_reason->deciding_aci = aci;
2800
 
                                                        result_reason->reason = ACL_REASON_RESULT_CACHED_DENY;
2801
 
                                                        TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
2802
 
                                                                tnf_string,cached_deny,"");
2803
 
                                                        return ACL_RES_DENY;
2804
 
                                                } else if ((result & ACLPB_CACHE_SEARCH_RES_SKIP) ||
2805
 
                                                           (result & ACLPB_CACHE_SEARCH_RES_ALLOW)) { 
2806
 
                                                    slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
2807
 
                                                             "DENY:Found SEARCH SKIP in cache\n");
2808
 
                                                        skip_eval = 1;
2809
 
                                                        break;
2810
 
                                                } else {
2811
 
                                                        break;
2812
 
                                                }
2813
 
                                        } else {        /* must be READ */
2814
 
                                                if (result & ACLPB_CACHE_READ_RES_DENY) {
2815
 
                                                        slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
2816
 
                                                                  "DENY:Found READ DENY in cache\n");
2817
 
                                                        __acl_set_aclIndex_inResult ( aclpb, access, index );
2818
 
                                                        result_reason->deciding_aci = aci;
2819
 
                                                        result_reason->reason = ACL_REASON_RESULT_CACHED_DENY;
2820
 
                                                        TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
2821
 
                                                                tnf_string,cached_deny,"");
2822
 
                                                        return ACL_RES_DENY;
2823
 
                                                } else if ( result & ACLPB_CACHE_READ_RES_SKIP) {
2824
 
                                                        slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
2825
 
                                                                  "DENY:Found READ SKIP in cache\n");
2826
 
                                                        skip_eval = 1;
2827
 
                                                        break;
2828
 
                                                } else {
2829
 
                                                        break;
2830
 
                                                }
2831
 
                                        }
2832
 
                                }
2833
 
                        }
2834
 
                }
2835
 
                if (skip_eval) {
2836
 
                        skip_eval = 0;
2837
 
                        continue;
2838
 
                }
2839
 
 
2840
 
                rv = ACL_EvalSetACL(NULL, acleval, aci->aci_handle);
2841
 
                if ( rv < 0) {
2842
 
                        slapi_log_error(SLAPI_LOG_ACL, plugin_name,
2843
 
                                "acl__TestRights:Unable to set the DENY acllist\n");
2844
 
                        continue;
2845
 
                }
2846
 
                /* 
2847
 
                ** Now we have all the information we need. We need to call
2848
 
                ** the ONE ACL to test the rights.
2849
 
                ** return value: ACL_RES_DENY, ACL_RES_ALLOW,  error codes 
2850
 
                */
2851
 
                aclpb->aclpb_curr_aci = aci;
2852
 
                rights_rv = ACL_EvalTestRights (NULL, acleval, testRights, 
2853
 
                                                map_generic, &deny, 
2854
 
                                                &deny_generic,
2855
 
                                                &acl_tag, &expr_num);
2856
 
 
2857
 
                slapi_log_error( SLAPI_LOG_ACL, plugin_name, "Processed:%d DENY handles Result:%d\n",index, rights_rv);
2858
 
 
2859
 
                if (rights_rv   == ACL_RES_FAIL) {
2860
 
                                result_reason->deciding_aci = aci;
2861
 
                                result_reason->reason = ACL_REASON_NONE;
2862
 
                                TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
2863
 
                                                                tnf_string,evaled_deny,"");
2864
 
                                return ACL_RES_DENY;
2865
 
                }
2866
 
 
2867
 
                /* have we executed an ATTR RULE */
2868
 
                if ( aci->aci_ruleType & ACI_ATTR_RULES )
2869
 
                        aclpb->aclpb_state |= ACLPB_ATTR_RULE_EVALUATED;
2870
 
 
2871
 
                if (access & (SLAPI_ACL_SEARCH | SLAPI_ACL_READ)) {
2872
 
 
2873
 
                        for (j=0; j <aclpb->aclpb_last_cache_result; ++j) {
2874
 
                                if (index == aclpb->aclpb_cache_result[j].aci_index) {
2875
 
                                        break;
2876
 
                                }
2877
 
                        }
2878
 
 
2879
 
                        if ( j < aclpb->aclpb_last_cache_result)  {
2880
 
                                /* already in cache */
2881
 
                        } else if ( j < aclpb_max_cache_results ) {
2882
 
                                /* j == aclpb->aclpb_last_cache_result  &&
2883
 
                                        j < ACLPB_MAX_CACHE_RESULTS */
2884
 
                                aclpb->aclpb_last_cache_result++;
2885
 
                                aclpb->aclpb_cache_result[j].aci_index = index;
2886
 
                                aclpb->aclpb_cache_result[j].aci_ruleType = aci->aci_ruleType; 
2887
 
 
2888
 
                        } else {  /* cache overflow */
2889
 
                                if (  rights_rv == ACL_RES_DENY) {
2890
 
                                        result_reason->deciding_aci = aci;
2891
 
                                        result_reason->reason = ACL_REASON_EVALUATED_DENY;
2892
 
                                        TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
2893
 
                                                                tnf_string,evaled_deny,"");
2894
 
                                        return ACL_RES_DENY;
2895
 
                                } else {
2896
 
                                        continue;
2897
 
                                }
2898
 
                        }
2899
 
                
2900
 
                        __acl_set_aclIndex_inResult ( aclpb, access, index );
2901
 
                        if (rights_rv == ACL_RES_DENY) {
2902
 
                                if (access & SLAPI_ACL_SEARCH)  {
2903
 
                                        aclpb->aclpb_cache_result[j].result |= 
2904
 
                                                        ACLPB_CACHE_SEARCH_RES_DENY;
2905
 
                                } else  {               /* MUST BE READ */
2906
 
                                        aclpb->aclpb_cache_result[j].result |= 
2907
 
                                                        ACLPB_CACHE_READ_RES_DENY;
2908
 
                                }
2909
 
                                /* We are done  -- return */
2910
 
                                result_reason->deciding_aci = aci;
2911
 
                                result_reason->reason = ACL_REASON_EVALUATED_DENY;
2912
 
                                TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
2913
 
                                                                tnf_string,evaled_deny,"");
2914
 
                                return ACL_RES_DENY;
2915
 
                        } else if (rights_rv == ACL_RES_ALLOW) {
2916
 
                                /* This will happen, of we have an acl with both deny and allow 
2917
 
                                ** Since we may not have finished all the deny acl, go thru all
2918
 
                                ** of them. We will use this cached result when we evaluate this
2919
 
                                ** handle in the context of allow handles.
2920
 
                                */
2921
 
                                if (access & SLAPI_ACL_SEARCH)  {
2922
 
                                        aclpb->aclpb_cache_result[j].result |= 
2923
 
                                                        ACLPB_CACHE_SEARCH_RES_ALLOW;
2924
 
                                } else  {
2925
 
                                        aclpb->aclpb_cache_result[j].result |= 
2926
 
                                                        ACLPB_CACHE_READ_RES_ALLOW;
2927
 
                                }
2928
 
 
2929
 
                        } else {
2930
 
                                if (access & SLAPI_ACL_SEARCH)  {
2931
 
                                        aclpb->aclpb_cache_result[j].result |= 
2932
 
                                                        ACLPB_CACHE_SEARCH_RES_SKIP;
2933
 
                                } else  {
2934
 
                                        aclpb->aclpb_cache_result[j].result |= 
2935
 
                                                        ACLPB_CACHE_READ_RES_SKIP;
2936
 
                                }
2937
 
                                continue;
2938
 
                        }
2939
 
                } else {
2940
 
                        if ( rights_rv == ACL_RES_DENY ) {
2941
 
                                result_reason->deciding_aci = aci;
2942
 
                                result_reason->reason = ACL_REASON_EVALUATED_DENY;
2943
 
                                TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
2944
 
                                                                tnf_string,evaled_deny,"");
2945
 
                                return ACL_RES_DENY;
2946
 
                        }
2947
 
                }
2948
 
        }
2949
 
 
2950
 
 
2951
 
        /*
2952
 
        ** START PROCESSING ALLOW HANDLES.
2953
 
        ** Process each handle at a time. Do not concatenate the handles or else
2954
 
        ** all the context information will be build again and we will pay a
2955
 
        ** lot of penalty. The context is built the first time the handle is
2956
 
        ** processed.
2957
 
        **
2958
 
        ** First we set the default to INVALID so that if rules are not matched, then
2959
 
        ** we get INVALID and if a rule matched, the we get ALLOW.
2960
 
        */ 
2961
 
        aclpb->aclpb_state &= ~ACLPB_EXECUTING_DENY_HANDLES;
2962
 
        aclpb->aclpb_state |= ACLPB_EXECUTING_ALLOW_HANDLES;
2963
 
        ACL_SetDefaultResult (NULL, acleval, ACL_RES_INVALID);
2964
 
        numHandles = ACI_MAX_ELEVEL + aclpb->aclpb_num_allow_handles;
2965
 
        for (i=0, k=0; i < numHandles && k < aclpb->aclpb_num_allow_handles ; ++i) {
2966
 
                int     skip_eval = 0;
2967
 
                /* 
2968
 
                ** If the handle has been evaluated before, we can
2969
 
                ** cache the result.
2970
 
                */
2971
 
                if ((aci = aclpb->aclpb_allow_handles[i]) == NULL) {
2972
 
                        if (i <= ACI_MAX_ELEVEL) {
2973
 
                                continue;
2974
 
                        } else {
2975
 
                                break;
2976
 
                        }
2977
 
                }
2978
 
                k++;
2979
 
                index = aci->aci_index;
2980
 
                slapi_log_error(SLAPI_LOG_ACL, plugin_name,
2981
 
                        "%d. Evaluating ALLOW aci(%d) \"%s\"\n", k, index, aci->aclName);
2982
 
 
2983
 
                if (access  & ( SLAPI_ACL_SEARCH | SLAPI_ACL_READ)) {
2984
 
 
2985
 
                        /*
2986
 
                         * aclpb->aclpb_cache_result[0..aclpb->aclpb_last_cache_result] is
2987
 
                         * a cache of info about whether applicable acis
2988
 
                         * allowed, did_not_allow or denied access
2989
 
                        */                      
2990
 
 
2991
 
                        for (j =0; j < aclpb->aclpb_last_cache_result; j++) {
2992
 
                                if (index == aclpb->aclpb_cache_result[j].aci_index) {
2993
 
                                        short  result;
2994
 
                                        result = aclpb->aclpb_cache_result[j].result;
2995
 
                                        if ( result <= 0) break;
2996
 
 
2997
 
                                        if (!ACL_CACHED_RESULT_VALID(result)) {
2998
 
                                                /* something is wrong. Need to evaluate */
2999
 
                                                aclpb->aclpb_cache_result[j].result = -1;
3000
 
                                                break;
3001
 
                                        }
3002
 
 
3003
 
                                        /*
3004
 
                                        ** We have a valid cached result. Let's see if we 
3005
 
                                        ** have what we need.
3006
 
                                        */
3007
 
                                        if (access & SLAPI_ACL_SEARCH) {
3008
 
                                                if (result & ACLPB_CACHE_SEARCH_RES_ALLOW) {
3009
 
                                                        slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
3010
 
                                                           "Found SEARCH ALLOW in cache\n");
3011
 
                                                        __acl_set_aclIndex_inResult ( aclpb, access, index );
3012
 
                                                        result_reason->deciding_aci = aci;
3013
 
                                                        result_reason->reason = ACL_REASON_RESULT_CACHED_ALLOW;
3014
 
                                                        TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
3015
 
                                                                tnf_string,cached_allow,"");
3016
 
                                                        return ACL_RES_ALLOW;
3017
 
                                                } else if ( result & ACLPB_CACHE_SEARCH_RES_SKIP) {
3018
 
                                                        slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
3019
 
                                                           "Found SEARCH SKIP in cache\n");
3020
 
                                                        skip_eval = 1;
3021
 
                                                        break;
3022
 
                                                } else {
3023
 
                                                        /* need to evaluate */
3024
 
                                                        break;
3025
 
                                                }
3026
 
                                        } else {
3027
 
                                                if ( result & ACLPB_CACHE_READ_RES_ALLOW) {
3028
 
                                                        slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
3029
 
                                                           "Found READ ALLOW in cache\n");
3030
 
                                                        __acl_set_aclIndex_inResult ( aclpb, access, index );
3031
 
                                                        result_reason->deciding_aci = aci;
3032
 
                                                        result_reason->reason = ACL_REASON_RESULT_CACHED_ALLOW;
3033
 
                                                        TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
3034
 
                                                                tnf_string,cached_allow,"");
3035
 
                                                        return ACL_RES_ALLOW;
3036
 
                                                } else if ( result & ACLPB_CACHE_READ_RES_SKIP) {
3037
 
                                                        slapi_log_error(SLAPI_LOG_ACL, plugin_name, 
3038
 
                                                           "Found READ SKIP in cache\n");
3039
 
                                                        skip_eval = 1;
3040
 
                                                        break;
3041
 
                                                } else {
3042
 
                                                        break;
3043
 
                                                }
3044
 
                                        }
3045
 
                                }
3046
 
                        }
3047
 
                }
3048
 
                if ( skip_eval) {
3049
 
                        skip_eval = 0;
3050
 
                        continue;
3051
 
                }
3052
 
 
3053
 
                TNF_PROBE_0_DEBUG(acl__libaccess_start,"ACL","");
3054
 
                rv = ACL_EvalSetACL(NULL, acleval, aci->aci_handle);
3055
 
                if ( rv < 0) {
3056
 
                        slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
3057
 
                                "acl__TestRights:Unable to set the acllist\n");
3058
 
                        continue;
3059
 
                }
3060
 
                /* 
3061
 
                ** Now we have all the information we need. We need to call
3062
 
                ** the ONE ACL to test the rights.
3063
 
                ** return value: ACL_RES_DENY, ACL_RES_ALLOW,  error codes 
3064
 
                */
3065
 
                aclpb->aclpb_curr_aci = aci;
3066
 
                rights_rv = ACL_EvalTestRights (NULL, acleval, testRights, 
3067
 
                                                map_generic, &deny, 
3068
 
                                                &deny_generic,
3069
 
                                                &acl_tag, &expr_num);
3070
 
                TNF_PROBE_0_DEBUG(acl__libaccess_end,"ACL","");
3071
 
 
3072
 
                if (aci->aci_ruleType & ACI_ATTR_RULES)
3073
 
                        aclpb->aclpb_state |= ACLPB_ATTR_RULE_EVALUATED;
3074
 
 
3075
 
                if (access & (SLAPI_ACL_SEARCH | SLAPI_ACL_READ))  {
3076
 
 
3077
 
                        for (j=0; j <aclpb->aclpb_last_cache_result; ++j) {
3078
 
                                if (index == aclpb->aclpb_cache_result[j].aci_index) {
3079
 
                                        break;
3080
 
                                }
3081
 
                        }
3082
 
 
3083
 
                        if ( j < aclpb->aclpb_last_cache_result)  {
3084
 
                                /* already in cache */
3085
 
                        } else if ( j < aclpb_max_cache_results ) {
3086
 
                                /* j == aclpb->aclpb_last_cache_result  &&
3087
 
                                        j < ACLPB_MAX_CACHE_RESULTS */
3088
 
                                aclpb->aclpb_last_cache_result++;
3089
 
                                aclpb->aclpb_cache_result[j].aci_index = index;
3090
 
                                aclpb->aclpb_cache_result[j].aci_ruleType = aci->aci_ruleType;
3091
 
                        } else {  /* cache overflow */
3092
 
                                slapi_log_error (SLAPI_LOG_FATAL, "acl__TestRights", "cache overflown\n");
3093
 
                                if (  rights_rv == ACL_RES_ALLOW) {
3094
 
                                        result_reason->deciding_aci = aci;
3095
 
                                        result_reason->reason = ACL_REASON_EVALUATED_ALLOW;
3096
 
                                        TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
3097
 
                                                                tnf_string,evaled_allow,"");
3098
 
                                        return ACL_RES_ALLOW;
3099
 
                                } else {
3100
 
                                        continue;
3101
 
                                }
3102
 
                        }
3103
 
 
3104
 
                        __acl_set_aclIndex_inResult ( aclpb, access, index );
3105
 
                        if (rights_rv == ACL_RES_ALLOW) {
3106
 
                                if (access & SLAPI_ACL_SEARCH)  {
3107
 
                                        aclpb->aclpb_cache_result[j].result |= 
3108
 
                                                        ACLPB_CACHE_SEARCH_RES_ALLOW;
3109
 
                                } else  {               /* must be READ */
3110
 
                                        aclpb->aclpb_cache_result[j].result |= 
3111
 
                                                        ACLPB_CACHE_READ_RES_ALLOW;
3112
 
                                }
3113
 
                                
3114
 
                                /* We are done  -- return */
3115
 
                                result_reason->deciding_aci = aci;
3116
 
                                result_reason->reason = ACL_REASON_EVALUATED_ALLOW;
3117
 
                                TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
3118
 
                                                                tnf_string,evaled_allow,"");
3119
 
                                return ACL_RES_ALLOW;
3120
 
 
3121
 
                        } else {
3122
 
                                if (access & SLAPI_ACL_SEARCH)  {
3123
 
                                        aclpb->aclpb_cache_result[j].result |= 
3124
 
                                                        ACLPB_CACHE_SEARCH_RES_SKIP;
3125
 
                                } else  {
3126
 
                                        aclpb->aclpb_cache_result[j].result |= 
3127
 
                                                        ACLPB_CACHE_READ_RES_SKIP;
3128
 
                                }
3129
 
                                continue;
3130
 
                        }
3131
 
                } else {
3132
 
                        if ( rights_rv == ACL_RES_ALLOW ) {
3133
 
                                result_reason->deciding_aci = aci;
3134
 
                                result_reason->reason = ACL_REASON_EVALUATED_ALLOW;
3135
 
                                TNF_PROBE_1_DEBUG(acl__TestRights_end,"ACL","",
3136
 
                                                                tnf_string,evaled_allow,"");
3137
 
                                return ACL_RES_ALLOW;
3138
 
                        }
3139
 
                }
3140
 
        }/* for */
3141
 
        result_reason->deciding_aci = aci;
3142
 
        result_reason->reason = ACL_REASON_NO_MATCHED_SUBJECT_ALLOWS;
3143
 
 
3144
 
        TNF_PROBE_0_DEBUG(acl__TestRights_end,"ACL","");        
3145
 
 
3146
 
        return (ACL_RES_DENY);
3147
 
}
3148
 
/***************************************************************************
3149
 
*
3150
 
* acl_match_substring
3151
 
*
3152
 
*       Compare the input string to the patteren in the filter
3153
 
*
3154
 
* Input:
3155
 
*       struct slapi_filter     *f      - Filter which has the patteren
3156
 
*       char            *str            - String to compare
3157
 
*       int             exact_match     - 1; match the pattern exactly
3158
 
*                                       - 0; match the pattern as a suffix
3159
 
*
3160
 
* Returns:
3161
 
*       ACL_TRUE                - The sting matches with the patteren
3162
 
*       ACL_FALSE               - No it doesn't
3163
 
*       ACL_ERR                 - Error
3164
 
*
3165
 
* Error Handling:
3166
 
*       None.
3167
 
*
3168
 
**************************************************************************/
3169
 
int
3170
 
acl_match_substring ( Slapi_Filter *f, char *str, int exact_match)
3171
 
{
3172
 
        int             i, rc, len;
3173
 
        char            *p = NULL;
3174
 
        char            *end, *realval, *tmp;
3175
 
        char            pat[BUFSIZ];
3176
 
        char            buf[BUFSIZ];
3177
 
        char            *type, *initial, *final;
3178
 
        char            **any;
3179
 
        Slapi_Regex     *re = NULL;
3180
 
        const char  *re_result = NULL;
3181
 
 
3182
 
        if ( 0 != slapi_filter_get_subfilt ( f, &type, &initial, &any, &final ) ) {
3183
 
                return (ACL_FALSE);
3184
 
        }
3185
 
 
3186
 
        /* convert the input to lower. */
3187
 
        for (p = str; *p; p++)
3188
 
                *p = TOLOWER ( *p );
3189
 
 
3190
 
        /* construct a regular expression corresponding to the filter: */
3191
 
        pat[0] = '\0';
3192
 
        p = pat;
3193
 
        end = pat + sizeof(pat) - 2; /* leave room for null */
3194
 
 
3195
 
 
3196
 
        if ( initial != NULL) {
3197
 
                strcpy (p, "^");
3198
 
                p = strchr (p, '\0');
3199
 
 
3200
 
                /* 2 * in case every char is special */
3201
 
                if (p + 2 * strlen ( initial ) > end) {
3202
 
                        slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
3203
 
                                "not enough pattern space\n");
3204
 
 
3205
 
                        return (ACL_ERR);
3206
 
                }
3207
 
 
3208
 
                if (!exact_match) {
3209
 
                        strcpy (p, ".*");
3210
 
                        p = strchr (p, '\0');
3211
 
                }
3212
 
                acl_strcpy_special (p, initial);
3213
 
                p = strchr (p, '\0');
3214
 
        }
3215
 
 
3216
 
        if ( any != NULL) {
3217
 
                for (i = 0;  any && any[i] != NULL; i++) {
3218
 
                        /* ".*" + value */
3219
 
                        if (p + 2 * strlen ( any[i]) + 2 > end) {
3220
 
                                slapi_log_error (SLAPI_LOG_ACL, plugin_name,
3221
 
                                        "not enough pattern space\n");
3222
 
                                return (ACL_ERR);
3223
 
                        }
3224
 
 
3225
 
                        strcpy (p, ".*");
3226
 
                        p = strchr (p, '\0');
3227
 
                        acl_strcpy_special (p, any[i]);
3228
 
                        p = strchr (p, '\0');
3229
 
                }
3230
 
        }
3231
 
 
3232
 
 
3233
 
        if ( final != NULL) {
3234
 
                /* ".*" + value */
3235
 
                if (p + 2 * strlen ( final ) + 2 > end) {
3236
 
                        slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
3237
 
                                "not enough pattern space\n");
3238
 
                        return (ACL_ERR);
3239
 
                }
3240
 
        
3241
 
                strcpy (p, ".*");
3242
 
                p = strchr (p, '\0');
3243
 
                acl_strcpy_special (p, final);
3244
 
                p = strchr (p, '\0');
3245
 
                strcpy (p, "$");
3246
 
        }
3247
 
 
3248
 
        /* see if regex matches with the input string */
3249
 
        tmp = NULL;
3250
 
        len = strlen(str);
3251
 
 
3252
 
        if (len < sizeof(buf)) {
3253
 
                strcpy (buf, str);
3254
 
                realval = buf;
3255
 
        } else {
3256
 
                tmp = (char*) slapi_ch_malloc (len + 1);
3257
 
                strcpy (tmp, str);
3258
 
                realval = tmp;
3259
 
        }
3260
 
 
3261
 
        /* What we have built is a regular pattaren expression.
3262
 
        ** Now we will compile the pattern and compare wth the string to
3263
 
        ** see if the input string matches with the patteren or not.
3264
 
        */
3265
 
        re = slapi_re_comp( pat, &re_result );
3266
 
        if (NULL == re) {
3267
 
                slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
3268
 
                        "acl_match_substring:re_comp failed (%s)\n", re_result?re_result:"unknown");
3269
 
                return (ACL_ERR);
3270
 
        }
3271
 
 
3272
 
        /* slapi_re_exec() returns 1 if the string p1 matches the last compiled
3273
 
        ** regular expression, 0 if the string p1 failed to match 
3274
 
        */
3275
 
        rc = slapi_re_exec( re, realval, -1 /* no timelimit */ );
3276
 
 
3277
 
        slapi_re_free(re);
3278
 
        slapi_ch_free ( (void **) &tmp );
3279
 
 
3280
 
        if (rc == 1) {
3281
 
                return ACL_TRUE;
3282
 
        } else {
3283
 
                return ACL_FALSE;
3284
 
        }
3285
 
}
3286
 
/***************************************************************************
3287
 
*
3288
 
* acl__reset_cached_result
3289
 
*
3290
 
* Go thru the cached result and invlalidate the cached evaluation results for
3291
 
* rules which can only be cached based on the scope. 
3292
 
* If we have scope ACI_CACHE_RESULT_PER_ENTRY, then we need to invalidate the
3293
 
* cacched reult whenever we hit a new entry.
3294
 
*
3295
 
* Returns: 
3296
 
*       Null
3297
 
*
3298
 
**************************************************************************/
3299
 
static void 
3300
 
acl__reset_cached_result (struct acl_pblock *aclpb )
3301
 
{
3302
 
 
3303
 
        int             j;
3304
 
 
3305
 
        for (j =0; j < aclpb->aclpb_last_cache_result; j++) {
3306
 
                /* Unless we have to clear the result, move on */
3307
 
                if (!( aclpb->aclpb_cache_result[j].aci_ruleType & ACI_CACHE_RESULT_PER_ENTRY))
3308
 
                        continue;
3309
 
                aclpb->aclpb_cache_result[j].result = 0;
3310
 
        }
3311
 
}
3312
 
/*
3313
 
 * acl_access_allowed_disjoint_resource
3314
 
 * 
3315
 
 *      This is an internal module which can be used to verify
3316
 
 *      access to a resource which may not be inside the search scope.
3317
 
 *
3318
 
 * Returns:
3319
 
 *      - Same return val as acl_access_allowed().
3320
 
 */
3321
 
int
3322
 
acl_access_allowed_disjoint_resource(
3323
 
        Slapi_PBlock        *pb,
3324
 
        Slapi_Entry         *e,                 /* The Slapi_Entry */
3325
 
        char                *attr,              /* Attribute of the entry */
3326
 
        struct berval       *val,               /* value of attr. NOT USED */
3327
 
        int                 access              /* access rights */
3328
 
        )
3329
 
{
3330
 
 
3331
 
        int                rv;
3332
 
        struct acl_pblock  *aclpb = NULL;
3333
 
 
3334
 
        aclpb = acl_get_aclpb ( pb, ACLPB_BINDDN_PBLOCK );
3335
 
        /*
3336
 
        ** It's possible that we already have a context of ACLs. 
3337
 
        ** However once in a while, we need to test 
3338
 
        ** access to a resource which (like vlv, schema) which falls 
3339
 
        ** outside the search base. In that case, we need to  go 
3340
 
        ** thru all the ACLs and not depend upon the acls which we have
3341
 
        ** gathered.
3342
 
        */
3343
 
 
3344
 
        /* If you have the right to use the resource, then we don't need to check for
3345
 
        ** proxy right on that resource.
3346
 
        */
3347
 
        if (aclpb) 
3348
 
                aclpb->aclpb_state |= ( ACLPB_DONOT_USE_CONTEXT_ACLS| ACLPB_DONOT_EVALUATE_PROXY );
3349
 
 
3350
 
        rv = acl_access_allowed(pb, e, attr, val, access);
3351
 
 
3352
 
        if (aclpb) aclpb->aclpb_state &= ~ACLPB_DONOT_USE_CONTEXT_ACLS;
3353
 
        if (aclpb ) aclpb->aclpb_state &= ~ACLPB_DONOT_EVALUATE_PROXY;
3354
 
 
3355
 
        return rv;
3356
 
}
3357
 
 
3358
 
/*
3359
 
 * acl__attr_cached_result
3360
 
 *    Loops thru the cached result and determines if we can use the cached value.
3361
 
 *
3362
 
 *      Inputs:
3363
 
 *              Slapi_pblock    *aclpb          - acl private block
3364
 
 *              char            *attr                   - attribute name
3365
 
 *              int             access                          - access type
3366
 
 *      Returns:
3367
 
 *              LDAP_SUCCESS:                           - access is granted
3368
 
 *              LDAP_INSUFFICIENT_ACCESS        - access denied
3369
 
 *              ACL_ERR                                         - no cached info about this attr.
3370
 
 *                                                                      - or the attr had multiple result and so
3371
 
 *                                                                      - we can't determine the outcome.
3372
 
 *
3373
 
 */
3374
 
static int
3375
 
acl__attr_cached_result (struct acl_pblock *aclpb, char *attr, int access )
3376
 
{
3377
 
 
3378
 
        int                                     i, rc;
3379
 
        aclEvalContext          *c_evalContext;
3380
 
 
3381
 
        if ( !(access & ( SLAPI_ACL_SEARCH | SLAPI_ACL_READ) ))
3382
 
                return ACL_ERR;
3383
 
 
3384
 
        if (aclpb->aclpb_state & ACLPB_HAS_ACLCB_EVALCONTEXT ) {
3385
 
                c_evalContext = &aclpb->aclpb_prev_opEval_context;
3386
 
                slapi_log_error ( SLAPI_LOG_ACL, plugin_name, 
3387
 
                            "acl__attr_cached_result:Using Context: ACLPB_ACLCB\n" );
3388
 
        } else {
3389
 
                c_evalContext = &aclpb->aclpb_prev_entryEval_context;
3390
 
                slapi_log_error ( SLAPI_LOG_ACL, plugin_name, 
3391
 
                            "acl__attr_cached_result:Using Context: ACLPB_PREV\n" );
3392
 
        }
3393
 
 
3394
 
        if ( attr == NULL ) {
3395
 
                int             eval_read = 0;
3396
 
                /*
3397
 
                **  Do I have access to at least one attribute, then I have 
3398
 
                ** access to the  entry.
3399
 
                */
3400
 
                for (i=0; i < c_evalContext->acle_numof_attrs; i++ ) {
3401
 
                        AclAttrEval     *a_eval = &c_evalContext->acle_attrEval[i];
3402
 
 
3403
 
                        if (  (access & SLAPI_ACL_READ ) && a_eval->attrEval_r_status  && 
3404
 
                                a_eval->attrEval_r_status < ACL_ATTREVAL_DETERMINISTIC ) {
3405
 
                                eval_read++;
3406
 
                                if ( a_eval->attrEval_r_status & ACL_ATTREVAL_SUCCESS) 
3407
 
                                                return LDAP_SUCCESS;
3408
 
                                /* rbyrne: recompute if we have to.
3409
 
                                 * How does this cached result get turned off for
3410
 
                                 * attr style acis which acannot be cached becuase entry
3411
 
                                 * can result in a diff value.
3412
 
                                */                              
3413
 
                                else if ( a_eval->attrEval_r_status & ACL_ATTREVAL_RECOMPUTE ) {
3414
 
                                        rc = acl__recompute_acl ( aclpb, a_eval, access,
3415
 
                                                                                        a_eval->attrEval_r_aciIndex);
3416
 
                                        if ( rc != ACL_ERR ) {
3417
 
                                                acl_copyEval_context ( aclpb, c_evalContext,
3418
 
                                                                                &aclpb->aclpb_curr_entryEval_context, 1);
3419
 
                                        }
3420
 
                                        if ( rc == LDAP_SUCCESS) {
3421
 
                                                return LDAP_SUCCESS;
3422
 
                                        }
3423
 
                                }
3424
 
                        }
3425
 
                }/* for */
3426
 
                /*
3427
 
                 * If we have scanned the whole list without success then
3428
 
                 *  we are not granting access to this entry through access
3429
 
                 * to an attribute in the list--however this does not mean
3430
 
                 * that we do not have access to the entry via another attribute
3431
 
                 * not already in the list, so return -1 meaning
3432
 
                 * "don't know".
3433
 
                */
3434
 
                return(ACL_ERR);
3435
 
#if 0
3436
 
                if ( eval_read )
3437
 
                        return LDAP_INSUFFICIENT_ACCESS;
3438
 
                else
3439
 
                        return ACL_ERR;
3440
 
#endif
3441
 
        }
3442
 
 
3443
 
        for (i=0; i < c_evalContext->acle_numof_attrs; i++ ) {
3444
 
                AclAttrEval     *a_eval = &c_evalContext->acle_attrEval[i];
3445
 
 
3446
 
                if ( a_eval == NULL ) continue;
3447
 
 
3448
 
                if (strcasecmp ( attr, a_eval->attrEval_name ) == 0 ) {
3449
 
                        if ( access & SLAPI_ACL_SEARCH ) {
3450
 
                                if (a_eval->attrEval_s_status < ACL_ATTREVAL_DETERMINISTIC ) {
3451
 
                                        if ( a_eval->attrEval_s_status & ACL_ATTREVAL_SUCCESS)
3452
 
                                                return LDAP_SUCCESS;
3453
 
                                        else if ( a_eval->attrEval_s_status & ACL_ATTREVAL_FAIL)
3454
 
                                                return LDAP_INSUFFICIENT_ACCESS;
3455
 
                                        else if ( a_eval->attrEval_s_status & ACL_ATTREVAL_RECOMPUTE ) {
3456
 
                                                        rc = acl__recompute_acl ( aclpb, a_eval, access,
3457
 
                                                                                                a_eval->attrEval_s_aciIndex);
3458
 
                                                        if ( rc != ACL_ERR ) {
3459
 
                                                                acl_copyEval_context ( aclpb, c_evalContext,
3460
 
                                                                                &aclpb->aclpb_curr_entryEval_context, 1);
3461
 
                                                        }
3462
 
                                        } else
3463
 
                                                return ACL_ERR;
3464
 
                                } else {
3465
 
                                        /*  This means that for the same attribute and same type of
3466
 
                                        ** access, we had different results at different time.
3467
 
                                        ** Since we are not caching per object, we can't
3468
 
                                        ** determine exactly. So, can't touch this
3469
 
                                        */
3470
 
                                        return ACL_ERR;
3471
 
                                }
3472
 
                        } else {
3473
 
                                if (a_eval->attrEval_r_status < ACL_ATTREVAL_DETERMINISTIC ) {
3474
 
                                        if ( a_eval->attrEval_r_status & ACL_ATTREVAL_SUCCESS)
3475
 
                                                return LDAP_SUCCESS;
3476
 
                                        else if ( a_eval->attrEval_r_status & ACL_ATTREVAL_FAIL)
3477
 
                                                return LDAP_INSUFFICIENT_ACCESS;
3478
 
                                        else if ( a_eval->attrEval_r_status & ACL_ATTREVAL_RECOMPUTE ) {
3479
 
                                                        rc = acl__recompute_acl ( aclpb, a_eval, access,
3480
 
                                                                                        a_eval->attrEval_r_aciIndex);
3481
 
                                                        if ( rc != ACL_ERR ) {
3482
 
                                                                acl_copyEval_context ( aclpb, c_evalContext,
3483
 
                                                                                &aclpb->aclpb_curr_entryEval_context, 1);
3484
 
                                                        }
3485
 
                                        } else
3486
 
                                                return ACL_ERR;
3487
 
                                } else {
3488
 
                                        /* Look above for explanation */
3489
 
                                        return ACL_ERR;
3490
 
                                }
3491
 
                        }
3492
 
                }
3493
 
        }
3494
 
        return ACL_ERR;
3495
 
}
3496
 
 
3497
 
/*
3498
 
 * Had to do this juggling of casting to make 
3499
 
 * both Nt & unix compiler happy.
3500
 
 */
3501
 
static  int 
3502
 
acl__cmp(const void *a, const void *b)
3503
 
{
3504
 
        short *i = (short *) a;
3505
 
        short *j = (short *) b;
3506
 
 
3507
 
        if ( (short) *i > (short) *j )
3508
 
                return (1);
3509
 
        if ( (short)*i < (short) *j)
3510
 
                return (-1);
3511
 
        return (0);
3512
 
}
3513
 
 
3514
 
/*
3515
 
 * acl__scan_match_handles
3516
 
 *      Go thru the ACL list and determine if the list of acls selected matches
3517
 
 *      what we have in the cache.
3518
 
 *
3519
 
 *      Inputs:
3520
 
 *              Acl_PBlock *pb          - Main pblock ( blacvk hole)
3521
 
 *              int          type               - Which context to look on
3522
 
 *
3523
 
 *      Returns:
3524
 
 *              0                               - matches all the acl handles
3525
 
 *              ACL_ERR                 - sorry; no match
3526
 
 *
3527
 
 *      ASSUMPTION: A READER LOCK ON ACL LIST
3528
 
 */
3529
 
static int
3530
 
acl__scan_match_handles ( Acl_PBlock *aclpb, int type)
3531
 
{
3532
 
 
3533
 
 
3534
 
        int                             matched = 0;
3535
 
        aci_t                   *aci = NULL;
3536
 
        int                             index;
3537
 
        PRUint32                cookie;
3538
 
        aclEvalContext  *c_evalContext = NULL;
3539
 
 
3540
 
        if (type  == ACLPB_EVALCONTEXT_PREV ) {
3541
 
                c_evalContext = &aclpb->aclpb_prev_entryEval_context;
3542
 
        } else if ( type == ACLPB_EVALCONTEXT_ACLCB ){
3543
 
                c_evalContext = &aclpb->aclpb_prev_opEval_context;
3544
 
        } else {
3545
 
                return ACL_ERR;
3546
 
        }
3547
 
                
3548
 
 
3549
 
        if ( !c_evalContext->acle_numof_tmatched_handles )
3550
 
                return ACL_ERR;
3551
 
 
3552
 
        aclpb->aclpb_stat_acllist_scanned++;
3553
 
        aci = acllist_get_first_aci ( aclpb, &cookie );
3554
 
 
3555
 
        while ( aci ) {
3556
 
                index = aci->aci_index;
3557
 
                if (acl__resource_match_aci(aclpb, aci, 1 /* skip attr matching */, NULL )) {
3558
 
                        int     j;
3559
 
                        int     s_matched = matched;
3560
 
 
3561
 
                        /* We have a sorted list of handles that matched the target */
3562
 
                        
3563
 
                        for (j=0; j < c_evalContext->acle_numof_tmatched_handles ; j++ ) {
3564
 
                                if ( c_evalContext->acle_handles_matched_target[j]  > index )
3565
 
                                        
3566
 
                                        break;
3567
 
                                else if ( index == c_evalContext->acle_handles_matched_target[j] ) {
3568
 
                                        int             jj;
3569
 
                                        matched++;
3570
 
 
3571
 
                                        /* See if this is a ATTR rule that matched -- in that case we have
3572
 
                                        ** to nullify the cached result
3573
 
                                         */
3574
 
                                        if ( aci->aci_ruleType & ACI_ATTR_RULES ) {
3575
 
                                                slapi_log_error (  SLAPI_LOG_ACL, plugin_name, 
3576
 
                                                        "Found an attr Rule [Name:%s Index:%d\n", aci->aclName, 
3577
 
                                                        aci->aci_index );
3578
 
                                                for ( jj =0; jj < c_evalContext->acle_numof_attrs; jj++ ) {
3579
 
                                                        AclAttrEval     *a_eval = &c_evalContext->acle_attrEval[jj];
3580
 
                                                        if ( a_eval->attrEval_r_aciIndex == aci->aci_index )
3581
 
                                                                a_eval->attrEval_r_status = ACL_ATTREVAL_RECOMPUTE;
3582
 
                                                        if ( a_eval->attrEval_s_aciIndex == aci->aci_index )
3583
 
                                                                a_eval->attrEval_s_status = ACL_ATTREVAL_RECOMPUTE;
3584
 
                                                }
3585
 
                                        }
3586
 
                                        break;
3587
 
                                }
3588
 
                        }
3589
 
                        if ( s_matched == matched ) return ACL_ERR;
3590
 
                }
3591
 
                aci = acllist_get_next_aci ( aclpb, aci, &cookie );
3592
 
        }
3593
 
        if ( matched == c_evalContext->acle_numof_tmatched_handles )
3594
 
                return 0;
3595
 
 
3596
 
        return ACL_ERR;
3597
 
}
3598
 
/*
3599
 
 * acl_copyEval_context
3600
 
 *      Copy the context info which include attr info and handles.
3601
 
 *
3602
 
 *      Inputs
3603
 
 *              struct acl_pblock *aclpb        - acl private main block
3604
 
 *              aclEvalContext  *src            - src context
3605
 
 *              aclEvalContext  *dest           - dest context
3606
 
 *      Returns:
3607
 
 *              None.
3608
 
 *
3609
 
 */
3610
 
void
3611
 
acl_copyEval_context ( struct acl_pblock *aclpb, aclEvalContext *src, 
3612
 
                        aclEvalContext *dest , int copy_attr_only )
3613
 
{
3614
 
 
3615
 
        int             d_slot, i;
3616
 
 
3617
 
        /* Do a CLEAN copy we have nothing or else do an incremental copy.*/
3618
 
        if ( src->acle_numof_attrs < 1 )
3619
 
                return;
3620
 
 
3621
 
        /* Copy the attr info */
3622
 
        if ( dest->acle_numof_attrs < 1 )
3623
 
                acl_clean_aclEval_context (  dest, 0 /*clean */ );
3624
 
 
3625
 
        d_slot = dest->acle_numof_attrs;
3626
 
        for (i=0; i < src->acle_numof_attrs; i++ ) {
3627
 
                int     j;
3628
 
                int     attr_exists = 0;
3629
 
                int     dd_slot = d_slot;
3630
 
 
3631
 
                if ( aclpb && (i == 0) ) aclpb->aclpb_stat_num_copycontext++;
3632
 
 
3633
 
                if (  src->acle_attrEval[i].attrEval_r_status == 0 &&
3634
 
                        src->acle_attrEval[i].attrEval_s_status == 0  )
3635
 
                        continue;
3636
 
 
3637
 
                for ( j = 0; j < dest->acle_numof_attrs; j++ ) {
3638
 
                        if ( strcasecmp ( src->acle_attrEval[i].attrEval_name,
3639
 
                                          dest->acle_attrEval[j].attrEval_name ) == 0 ) {
3640
 
                                /* We have it. skip it. */
3641
 
                                attr_exists = 1;
3642
 
                                dd_slot = j;
3643
 
                                break;
3644
 
                        }
3645
 
                }
3646
 
                if ( !attr_exists ) {
3647
 
                        if ( dd_slot >= ACLPB_MAX_ATTRS -1 )
3648
 
                                break;
3649
 
 
3650
 
                        if ( aclpb) aclpb->aclpb_stat_num_copy_attrs++;
3651
 
 
3652
 
                        if ( dest->acle_attrEval[dd_slot].attrEval_name )
3653
 
                                slapi_ch_free ( (void **) &dest->acle_attrEval[dd_slot].attrEval_name );
3654
 
 
3655
 
                        dest->acle_attrEval[dd_slot].attrEval_name  = 
3656
 
                                slapi_ch_strdup ( src->acle_attrEval[i].attrEval_name );
3657
 
                }
3658
 
                /* Copy the result status and the aci index */
3659
 
                dest->acle_attrEval[dd_slot].attrEval_r_status = 
3660
 
                                src->acle_attrEval[i].attrEval_r_status;
3661
 
                dest->acle_attrEval[dd_slot].attrEval_r_aciIndex = 
3662
 
                                src->acle_attrEval[i].attrEval_r_aciIndex;
3663
 
                dest->acle_attrEval[dd_slot].attrEval_s_status = 
3664
 
                                src->acle_attrEval[i].attrEval_s_status;
3665
 
                dest->acle_attrEval[dd_slot].attrEval_s_aciIndex = 
3666
 
                                src->acle_attrEval[i].attrEval_s_aciIndex;
3667
 
 
3668
 
                if (!attr_exists ) d_slot++;
3669
 
        }
3670
 
 
3671
 
        dest->acle_numof_attrs = d_slot;
3672
 
        dest->acle_attrEval[d_slot].attrEval_name  =  NULL;
3673
 
 
3674
 
        if ( copy_attr_only )
3675
 
                return;
3676
 
 
3677
 
        /* First sort the arrays which keeps the acl index numbers */
3678
 
        qsort ( (char *) src->acle_handles_matched_target, 
3679
 
                        (size_t)src->acle_numof_tmatched_handles, sizeof( int ), acl__cmp );
3680
 
 
3681
 
        for (i=0; i < src->acle_numof_tmatched_handles; i++ )  {
3682
 
                dest->acle_handles_matched_target[i]  =
3683
 
                                src->acle_handles_matched_target[i];
3684
 
        }
3685
 
 
3686
 
        if ( src->acle_numof_tmatched_handles ) {
3687
 
                dest->acle_numof_tmatched_handles = src->acle_numof_tmatched_handles;
3688
 
                if ( aclpb) aclpb->aclpb_stat_num_tmatched_acls = src->acle_numof_tmatched_handles;
3689
 
        }
3690
 
}
3691
 
 
3692
 
/*
3693
 
 * acl_clean_aclEval_context
3694
 
 *      Clean the eval context
3695
 
 *
3696
 
 *      Inputs:
3697
 
 *              aclEvalContext *clean_me        - COntext to be cleaned
3698
 
 *              int             clean_type      -  0: clean, 1 scrub
3699
 
 *
3700
 
 */
3701
 
 
3702
 
void
3703
 
acl_clean_aclEval_context ( aclEvalContext *clean_me, int scrub_only )
3704
 
{
3705
 
        int             i;
3706
 
 
3707
 
        /* Copy the attr info */
3708
 
        for (i=0; i < clean_me->acle_numof_attrs; i++ ) {
3709
 
 
3710
 
                char    *a_name = clean_me->acle_attrEval[i].attrEval_name;
3711
 
                if ( a_name  && !scrub_only) {
3712
 
                        slapi_ch_free ( (void **)  &a_name );
3713
 
                        clean_me->acle_attrEval[i].attrEval_name = NULL;
3714
 
                }
3715
 
                clean_me->acle_attrEval[i].attrEval_r_status = 0;
3716
 
                clean_me->acle_attrEval[i].attrEval_s_status = 0;
3717
 
                clean_me->acle_attrEval[i].attrEval_r_aciIndex = 0;
3718
 
                clean_me->acle_attrEval[i].attrEval_s_aciIndex = 0;
3719
 
        }
3720
 
 
3721
 
        if ( !scrub_only ) clean_me->acle_numof_attrs = 0;
3722
 
        clean_me->acle_numof_tmatched_handles = 0;
3723
 
}
3724
 
/*
3725
 
 * acl__match_handlesFromCache
3726
 
 *
3727
 
 *      We have 2 cacheed information
3728
 
 *      1) cached info from the previous operation
3729
 
 *      2) cached info from the prev entry evaluation
3730
 
 *
3731
 
 *      What we are doing here is going thru all the acls and see if the same
3732
 
 *      set of acls apply to this resource or not. If it does, then do we have
3733
 
 *      a cached info for the attr. If we don't for both of the cases then we need 
3734
 
 *      to evaluate all over again.
3735
 
 *
3736
 
 *      Inputs:
3737
 
 *              struct  acl_pblock       - ACL private block;
3738
 
 *              char *attr               - Attribute name
3739
 
 *              int     access           - acces type
3740
 
 *
3741
 
 *      returns:
3742
 
 *              LDAP_SUCCESS (0)         - The same acls apply and we have 
3743
 
 *                                         access ALLOWED on the attr
3744
 
 *              LDAP_INSUFFICIENT_ACCESS - The same acls apply and we have 
3745
 
 *                                         access DENIED on the attr
3746
 
 *              -1                       - Acls doesn't match or we don't have
3747
 
 *                                         cached info for this attr.
3748
 
 *
3749
 
 *      ASSUMPTIONS: A reader lock has been obtained for the acl list.
3750
 
 */
3751
 
static int
3752
 
acl__match_handlesFromCache (  Acl_PBlock *aclpb, char *attr, int access)
3753
 
{
3754
 
 
3755
 
        aclEvalContext          *c_evalContext = NULL;
3756
 
        int                     context_type = 0;
3757
 
        int     ret_val = -1;   /* it doen't match by default */
3758
 
 
3759
 
        /* Before we proceed, find out if we have evaluated any ATTR RULE. If we have
3760
 
        ** then we can't use any caching mechanism
3761
 
        */
3762
 
 
3763
 
        if ( aclpb->aclpb_state & ACLPB_HAS_ACLCB_EVALCONTEXT ) {
3764
 
                context_type = ACLPB_EVALCONTEXT_ACLCB;
3765
 
                c_evalContext = &aclpb->aclpb_prev_opEval_context;
3766
 
         } else {
3767
 
                context_type =  ACLPB_EVALCONTEXT_PREV;
3768
 
                c_evalContext = &aclpb->aclpb_prev_entryEval_context;
3769
 
        }
3770
 
 
3771
 
 
3772
 
        if ( aclpb->aclpb_res_type & (ACLPB_NEW_ENTRY | ACLPB_EFFECTIVE_RIGHTS) ) { 
3773
 
                aclpb->aclpb_state |= ACLPB_MATCHES_ALL_ACLS;
3774
 
                ret_val =  acl__scan_match_handles ( aclpb, context_type );
3775
 
                if (  -1 == ret_val ) {
3776
 
                        aclpb->aclpb_state &= ~ACLPB_MATCHES_ALL_ACLS;
3777
 
                        aclpb->aclpb_state |= ACLPB_UPD_ACLCB_CACHE;
3778
 
                        /* Did not match */
3779
 
                        if ( context_type == ACLPB_EVALCONTEXT_ACLCB ) {
3780
 
                                aclpb->aclpb_state &= ~ACLPB_HAS_ACLCB_EVALCONTEXT;
3781
 
                        } else {
3782
 
                                aclpb->aclpb_state |= ACLPB_COPY_EVALCONTEXT;
3783
 
                                c_evalContext->acle_numof_tmatched_handles = 0;
3784
 
                        }
3785
 
                }
3786
 
        }
3787
 
        if ( aclpb->aclpb_state & ACLPB_MATCHES_ALL_ACLS ) {
3788
 
                /* See if we have a cached result for this attr */
3789
 
                ret_val = acl__attr_cached_result (aclpb, attr, access);
3790
 
 
3791
 
                /* It's not in the ACLCB context but we might have it in the 
3792
 
                ** current/prev context. Take a look at it. we might have evaluated
3793
 
                ** this attribute already.
3794
 
                */
3795
 
                if ( (-1 == ret_val ) &&
3796
 
                        ( aclpb->aclpb_state & ACLPB_HAS_ACLCB_EVALCONTEXT )) {
3797
 
                        aclpb->aclpb_state &= ~ACLPB_HAS_ACLCB_EVALCONTEXT ;
3798
 
                        ret_val = acl__attr_cached_result (aclpb, attr, access);
3799
 
                        aclpb->aclpb_state |= ACLPB_HAS_ACLCB_EVALCONTEXT ;
3800
 
 
3801
 
                        /* We need to do an incremental update */
3802
 
                        if  ( !ret_val ) aclpb->aclpb_state |= ACLPB_INCR_ACLCB_CACHE;
3803
 
                }
3804
 
        }
3805
 
        return ret_val;
3806
 
}
3807
 
/*
3808
 
 * acl__get_attrEval
3809
 
 *      Get the atteval from the current context and hold the ptr in aclpb.
3810
 
 *      If we have too many attrs, then allocate a new one. In that case
3811
 
 *      we let the caller know about that so that it will be deallocated.
3812
 
 *
3813
 
 *      Returns:
3814
 
 *              int             - 0: The context was indexed. So, no allocations.
3815
 
 *                              - 1; context was allocated - deallocate it.
3816
 
 */
3817
 
static int
3818
 
acl__get_attrEval ( struct acl_pblock *aclpb, char *attr )
3819
 
{
3820
 
 
3821
 
        int                                     j;
3822
 
        aclEvalContext          *c_ContextEval = &aclpb->aclpb_curr_entryEval_context;
3823
 
        int                                     deallocate_attrEval = 0;
3824
 
        AclAttrEval                     *c_attrEval = NULL;
3825
 
 
3826
 
        if ( !attr ) return deallocate_attrEval;
3827
 
 
3828
 
        aclpb->aclpb_curr_attrEval = NULL;
3829
 
 
3830
 
        /* Go thru and see if we have the attr already */
3831
 
        for (j=0; j < c_ContextEval->acle_numof_attrs; j++) {
3832
 
                c_attrEval = &c_ContextEval->acle_attrEval[j];
3833
 
                        
3834
 
                if ( c_attrEval && 
3835
 
                        slapi_attr_type_cmp ( c_attrEval->attrEval_name, attr, 1) == 0 ) {
3836
 
                        aclpb->aclpb_curr_attrEval = c_attrEval;
3837
 
                        break;
3838
 
                }
3839
 
        }
3840
 
 
3841
 
        if ( !aclpb->aclpb_curr_attrEval) {
3842
 
                if ( c_ContextEval->acle_numof_attrs == ACLPB_MAX_ATTRS -1 ) {
3843
 
                        /* Too many attrs. create a temp one  */
3844
 
                        c_attrEval =  (AclAttrEval * ) slapi_ch_calloc ( 1, sizeof ( AclAttrEval ) );
3845
 
                        deallocate_attrEval =1;
3846
 
                } else {
3847
 
                        c_attrEval = &c_ContextEval->acle_attrEval[c_ContextEval->acle_numof_attrs++];
3848
 
                        c_attrEval->attrEval_r_status = 0;
3849
 
                        c_attrEval->attrEval_s_status = 0;
3850
 
                        c_attrEval->attrEval_r_aciIndex = 0;
3851
 
                        c_attrEval->attrEval_s_aciIndex = 0;
3852
 
                }
3853
 
                /* clean it before use */
3854
 
                c_attrEval->attrEval_name = slapi_ch_strdup ( attr );
3855
 
                aclpb->aclpb_curr_attrEval = c_attrEval;
3856
 
        }
3857
 
        return deallocate_attrEval;
3858
 
}
3859
 
/*
3860
 
 * acl_skip_access_check
3861
 
 *
3862
 
 *      See if we need to go thru the ACL check or not. We don't need to if I am root
3863
 
 *      or internal operation or ...
3864
 
 *
3865
 
 * returns:
3866
 
 *      ACL_TRUE                - Yes; skip the ACL check
3867
 
 *      ACL_FALSE               - No; you have to go thru ACL check
3868
 
 * 
3869
 
 */
3870
 
int
3871
 
acl_skip_access_check ( Slapi_PBlock *pb,  Slapi_Entry *e )
3872
 
{
3873
 
        int                             rv, isRoot, accessCheckDisabled;
3874
 
        void                    *conn = NULL;
3875
 
        Slapi_Backend   *be;   
3876
 
 
3877
 
        slapi_pblock_get ( pb, SLAPI_REQUESTOR_ISROOT, &isRoot );
3878
 
        if ( isRoot ) return ACL_TRUE;
3879
 
 
3880
 
        /* See  if this is local request */
3881
 
        slapi_pblock_get ( pb, SLAPI_CONNECTION, &conn);
3882
 
 
3883
 
        if ( NULL == conn ) return  ACL_TRUE;
3884
 
 
3885
 
        /*
3886
 
         * Turn on access checking in the rootdse--this code used
3887
 
         * to skip the access check.
3888
 
         * 
3889
 
         *  check if the entry is the RootDSE entry
3890
 
        if ( e   ) {
3891
 
                char    * edn = slapi_entry_get_ndn ( e );
3892
 
                if  ( slapi_is_rootdse ( edn ) ) return ACL_TRUE;
3893
 
        }
3894
 
        */
3895
 
 
3896
 
        /* GB : when referrals are directly set in the mappin tree
3897
 
         * we can reach this code without a backend in the pblock
3898
 
         * in such a case, allow access for now 
3899
 
         * we may want to reconsider this is NULL DSE implementation happens
3900
 
         */
3901
 
        rv = slapi_pblock_get ( pb, SLAPI_BACKEND, &be );
3902
 
        if (be == NULL)
3903
 
                return ACL_TRUE;
3904
 
                        
3905
 
        rv = slapi_pblock_get ( pb, SLAPI_PLUGIN_DB_NO_ACL, &accessCheckDisabled );
3906
 
    if ( rv != -1 && accessCheckDisabled ) return ACL_TRUE;
3907
 
 
3908
 
        return ACL_FALSE;
3909
 
}
3910
 
short
3911
 
acl_get_aclsignature ()
3912
 
{
3913
 
        return acl_signature;
3914
 
}
3915
 
void
3916
 
acl_set_aclsignature ( short value)
3917
 
{
3918
 
        acl_signature = value;
3919
 
}
3920
 
void
3921
 
acl_regen_aclsignature ()
3922
 
{
3923
 
        acl_signature = aclutil_gen_signature ( acl_signature );
3924
 
}
3925
 
        
3926
 
 
3927
 
/*
3928
 
*
3929
 
* Assumptions:
3930
 
*       1) Called for read/search right.
3931
 
*/
3932
 
static int
3933
 
acl__recompute_acl (    Acl_PBlock              *aclpb,  
3934
 
                                                AclAttrEval             *a_eval,
3935
 
                                                int                             access,
3936
 
                                                int                             aciIndex
3937
 
                                        )
3938
 
{
3939
 
 
3940
 
 
3941
 
        char            *unused_str1, *unused_str2;
3942
 
        char            *acl_tag, *testRight[2];
3943
 
        int                     j, expr_num;
3944
 
        int                     result_status = ACL_RES_INVALID, cache_result;
3945
 
        PRUint32        cookie;
3946
 
        aci_t           *aci;
3947
 
 
3948
 
 
3949
 
        PR_ASSERT ( aciIndex >= 0 );
3950
 
        PR_ASSERT ( a_eval != NULL );
3951
 
        PR_ASSERT (aclpb != NULL );
3952
 
 
3953
 
 
3954
 
        /* We might have evaluated this acl just now, check it there first */
3955
 
 
3956
 
        for ( j =0; j < aclpb->aclpb_last_cache_result; j++) {
3957
 
                if (aciIndex == aclpb->aclpb_cache_result[j].aci_index) {
3958
 
                        short  result;
3959
 
                        result_status =ACL_RES_INVALID; 
3960
 
 
3961
 
                        result = aclpb->aclpb_cache_result[j].result;
3962
 
                        if ( result <= 0) break;
3963
 
                        if (!ACL_CACHED_RESULT_VALID(result)) {
3964
 
                                /* something is wrong. Need to evaluate */
3965
 
                                aclpb->aclpb_cache_result[j].result = -1;
3966
 
                                break;
3967
 
                        }
3968
 
                        
3969
 
 
3970
 
                        /*
3971
 
                        ** We have a valid cached result. Let's see if we
3972
 
                        ** have what we need.
3973
 
                        */
3974
 
                        if ((result & ACLPB_CACHE_SEARCH_RES_ALLOW) ||
3975
 
                                (result & ACLPB_CACHE_READ_RES_ALLOW) )
3976
 
                                result_status = ACL_RES_ALLOW;
3977
 
                        else if ((result & ACLPB_CACHE_SEARCH_RES_DENY) ||
3978
 
                                (result & ACLPB_CACHE_READ_RES_DENY) )
3979
 
                                result_status = ACL_RES_DENY;
3980
 
 
3981
 
                }
3982
 
        } /* end of for */
3983
 
 
3984
 
        if ( result_status != ACL_RES_INVALID ) {
3985
 
                goto set_result_status;
3986
 
        }
3987
 
 
3988
 
        slapi_log_error ( SLAPI_LOG_ACL, plugin_name,
3989
 
                        "Recomputing the ACL Index:%d for entry:%s\n",
3990
 
                        aciIndex, slapi_entry_get_ndn ( aclpb->aclpb_curr_entry) );
3991
 
                                
3992
 
        /* First find this one ACL and then evaluate it. */
3993
 
 
3994
 
        
3995
 
        aci = acllist_get_first_aci ( aclpb, &cookie );
3996
 
        while ( aci && aci->aci_index != aciIndex ) {
3997
 
                aci = acllist_get_next_aci ( aclpb, aci, &cookie );
3998
 
        }
3999
 
 
4000
 
        if (NULL == aci)
4001
 
                return -1;
4002
 
 
4003
 
 
4004
 
        ACL_SetDefaultResult (NULL, aclpb->aclpb_acleval, ACL_RES_INVALID);
4005
 
        ACL_EvalSetACL(NULL, aclpb->aclpb_acleval, aci->aci_handle);
4006
 
 
4007
 
        testRight[0] = acl_access2str ( access );
4008
 
        testRight[1] = '\0';
4009
 
        aclpb->aclpb_curr_aci = aci;
4010
 
        result_status = ACL_EvalTestRights (NULL, aclpb->aclpb_acleval, testRight,
4011
 
                                                        ds_map_generic, &unused_str1,
4012
 
                                                        &unused_str2,
4013
 
                                                        &acl_tag, &expr_num);
4014
 
 
4015
 
        cache_result = 0;
4016
 
        if ( result_status == ACL_RES_DENY && aci->aci_type & ACI_HAS_DENY_RULE ) {
4017
 
                if ( access & SLAPI_ACL_SEARCH)
4018
 
                        cache_result = ACLPB_CACHE_SEARCH_RES_DENY;
4019
 
                else
4020
 
                        cache_result = ACLPB_CACHE_READ_RES_DENY;
4021
 
        } else if ( result_status == ACL_RES_ALLOW && aci->aci_type & ACI_HAS_ALLOW_RULE ) {
4022
 
                if ( access & SLAPI_ACL_SEARCH)
4023
 
                        cache_result = ACLPB_CACHE_SEARCH_RES_ALLOW;
4024
 
                else
4025
 
                        cache_result = ACLPB_CACHE_READ_RES_ALLOW;
4026
 
 
4027
 
        } else {
4028
 
                result_status = -1;
4029
 
        }
4030
 
 
4031
 
        /* Now we need to put the cached result in the aclpb */
4032
 
 
4033
 
        for (j=0; j <aclpb->aclpb_last_cache_result; ++j) {
4034
 
                if (aciIndex == aclpb->aclpb_cache_result[j].aci_index) {
4035
 
                        break;
4036
 
                }
4037
 
        }
4038
 
 
4039
 
        if ( j < aclpb->aclpb_last_cache_result)  {
4040
 
                /* already in cache */
4041
 
        } else if ( j < aclpb_max_cache_results-1) {
4042
 
        /* rbyrneXXX: make this same as other last_cache_result code! */
4043
 
                j =  ++aclpb->aclpb_last_cache_result;
4044
 
                aclpb->aclpb_cache_result[j].aci_index = aci->aci_index;
4045
 
                aclpb->aclpb_cache_result[j].aci_ruleType = aci->aci_ruleType; 
4046
 
 
4047
 
        } else {  /*  No more space */
4048
 
                goto set_result_status;
4049
 
        }
4050
 
 
4051
 
        /* Add the cached result status */
4052
 
        aclpb->aclpb_cache_result[j].result |= cache_result;
4053
 
 
4054
 
 
4055
 
 
4056
 
set_result_status:
4057
 
        if (result_status == ACL_RES_ALLOW) {
4058
 
                if (access & SLAPI_ACL_SEARCH)
4059
 
                        /*wrong bit maskes were being used here--
4060
 
                                a_eval->attrEval_s_status = ACLPB_CACHE_SEARCH_RES_ALLOW;*/
4061
 
                        a_eval->attrEval_s_status = ACL_ATTREVAL_SUCCESS;
4062
 
                else
4063
 
                        a_eval->attrEval_r_status = ACL_ATTREVAL_SUCCESS;
4064
 
 
4065
 
        } else if ( result_status == ACL_RES_DENY) {
4066
 
                if (access & SLAPI_ACL_SEARCH)
4067
 
                        a_eval->attrEval_s_status = ACL_ATTREVAL_FAIL;
4068
 
                else
4069
 
                        a_eval->attrEval_r_status = ACL_ATTREVAL_FAIL;
4070
 
        } else {
4071
 
                /* Here, set it to recompute--try again later */
4072
 
                if (access & SLAPI_ACL_SEARCH)
4073
 
                        a_eval->attrEval_s_status = ACL_ATTREVAL_RECOMPUTE;
4074
 
                else
4075
 
                        a_eval->attrEval_r_status = ACL_ATTREVAL_RECOMPUTE;
4076
 
                result_status = -1;
4077
 
        }
4078
 
 
4079
 
        return result_status;
4080
 
}
4081
 
 
4082
 
static void 
4083
 
__acl_set_aclIndex_inResult ( Acl_PBlock *aclpb, int access, int index )
4084
 
{
4085
 
        AclAttrEval     *c_attrEval = aclpb->aclpb_curr_attrEval;
4086
 
        
4087
 
        if ( c_attrEval )  {
4088
 
                if ( access & SLAPI_ACL_SEARCH )
4089
 
                        c_attrEval->attrEval_s_aciIndex = index;
4090
 
                else if ( access & SLAPI_ACL_READ )
4091
 
                        c_attrEval->attrEval_r_aciIndex = index;
4092
 
        }
4093
 
}
4094
 
 
4095
 
/* 
4096
 
 * If filter_sense is true then return (entry satisfies f).
4097
 
 * Otherwise, return !(entry satisfies f)
4098
 
*/
4099
 
 
4100
 
static int
4101
 
acl__test_filter ( Slapi_Entry *entry, struct slapi_filter *f, int filter_sense) {
4102
 
                int     filter_matched;
4103
 
 
4104
 
                /* slapi_vattr_filter_test() returns 0 for match */
4105
 
 
4106
 
                filter_matched = !slapi_vattr_filter_test(NULL, entry, 
4107
 
                                                                                f,
4108
 
                                                                                0 /*don't do acess chk*/);
4109
 
                
4110
 
                if (filter_sense) {
4111
 
                        return(filter_matched ? ACL_TRUE : ACL_FALSE);
4112
 
                } else {
4113
 
                        return(filter_matched ? ACL_FALSE: ACL_TRUE);
4114
 
                }
4115
 
}  
4116
 
 
4117
 
/*
4118
 
 * Make an entry consisting of attr_type and attr_val and put
4119
 
 * a pointer to it in *entry.
4120
 
 * We will use this afterwards to test for against a filter.
4121
 
*/
4122
 
 
4123
 
static int
4124
 
acl__make_filter_test_entry ( Slapi_Entry **entry,  char *attr_type,
4125
 
                                                          struct berval *attr_val) {
4126
 
 
4127
 
        struct berval *vals_array[2];
4128
 
    
4129
 
    vals_array[0] = attr_val;
4130
 
    vals_array[1] = NULL;
4131
 
 
4132
 
        *entry = slapi_entry_alloc();
4133
 
        slapi_entry_init(*entry, NULL, NULL);
4134
 
 
4135
 
        return (slapi_entry_add_values( *entry, (const char *)attr_type,
4136
 
                                                                (struct berval**)&vals_array[0] ));
4137
 
                                                                                
4138
 
}
4139
 
 
4140
 
/*********************************************************************************/
4141
 
/*              E       N       D                                               */
4142
 
/*********************************************************************************/