]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/acl.c
notices
[openldap] / servers / slapd / acl.c
index 5b1f0434b84f1e19589728a7ec6502811c334519..c648d4ef6fb6dcabf90ac232bfe29f5b718c7231 100644 (file)
@@ -1,8 +1,27 @@
 /* acl.c - routines to parse and check acl's */
 /* $OpenLDAP$ */
-/*
- * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2003 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
  */
 
 #include "portable.h"
@@ -50,6 +69,7 @@ static AccessControl * acl_get(
        AccessControl *ac, int *count,
        Operation *op, Entry *e,
        AttributeDescription *desc,
+       struct berval *val,
        int nmatches, regmatch_t *matches );
 
 static slap_control_t acl_mask(
@@ -177,8 +197,8 @@ access_allowed(
        }
 
 #ifdef LDAP_SLAPI
-       ret = slapi_x_access_allowed( op, e, desc, val, access, state );
-       if ( ret == 0 ) {
+       if ( op->o_pb && 
+               !slapi_x_access_allowed( op, e, desc, val, access, state )) {
                /* ACL plugin denied access */
                goto done;
        }
@@ -286,7 +306,7 @@ access_allowed(
                memset(matches, '\0', sizeof(matches));
        }
 
-       while((a = acl_get( a, &count, op, e, desc,
+       while((a = acl_get( a, &count, op, e, desc, val,
                MAXREMATCHES, matches )) != NULL)
        {
                int i;
@@ -379,10 +399,11 @@ vd_access:
 done:
        if( state != NULL ) {
                /* If not value-dependent, save ACL in case of more attrs */
-               if ( !(state->as_recorded & ACL_STATE_RECORDED_VD) )
+               if ( !(state->as_recorded & ACL_STATE_RECORDED_VD) ) {
                        state->as_vi_acl = a;
+                       state->as_result = ret;
+               }
                state->as_recorded |= ACL_STATE_RECORDED;
-               state->as_result = ret;
        }
        if (be_null) op->o_bd = NULL;
        return ret;
@@ -401,6 +422,7 @@ acl_get(
        Operation       *op,
        Entry           *e,
        AttributeDescription *desc,
+       struct berval   *val,
        int                     nmatch,
        regmatch_t      *matches )
 {
@@ -515,7 +537,7 @@ acl_get(
                Debug( LDAP_DEBUG_ACL, "=> acl_get: [%d] check attr %s\n",
                       *count, attr, 0);
 #endif
-               if ( attr == NULL || a->acl_attrs == NULL ||
+               if ( a->acl_attrs == NULL ||
                        ad_inlist( desc, a->acl_attrs ) )
                {
 #ifdef NEW_LOGGING
@@ -612,6 +634,48 @@ acl_mask(
                accessmask2str( *mask, accessmaskbuf ) );
 #endif
 
+       /* Is this ACL only for a specific value? */
+       if ( a->acl_attrval.bv_len ) {
+               if ( state && !state->as_vd_acl ) {
+                       state->as_vd_acl = a;
+                       state->as_vd_access = a->acl_access;
+                       state->as_vd_access_count = 1;
+               }
+               if ( val == NULL ) {
+                       return ACL_BREAK;
+               }
+               if ( a->acl_attrval_style == ACL_STYLE_REGEX ) {
+#ifdef NEW_LOGGING
+                       LDAP_LOG( ACL, DETAIL1, 
+                               "acl_get: valpat %s\n",
+                               a->acl_attrval.bv_val, 0, 0 );
+#else
+                       Debug( LDAP_DEBUG_ACL,
+                               "acl_get: valpat %s\n",
+                               a->acl_attrval.bv_val, 0, 0 );
+#endif
+                       if (regexec(&a->acl_attrval_re, val->bv_val, 0, NULL, 0))
+                               return ACL_BREAK;
+               } else {
+                       int match = 0;
+                       const char *text;
+#ifdef NEW_LOGGING
+                       LDAP_LOG( ACL, DETAIL1, 
+                               "acl_get: val %s\n",
+                               a->acl_attrval.bv_val, 0, 0 );
+#else
+                       Debug( LDAP_DEBUG_ACL,
+                               "acl_get: val %s\n",
+                               a->acl_attrval.bv_val, 0, 0 );
+#endif
+                       if (value_match( &match, desc,
+                               desc->ad_type->sat_equality, 0,
+                               val, &a->acl_attrval, &text ) != LDAP_SUCCESS ||
+                                       match )
+                               return ACL_BREAK;
+               }
+       }
+
        if( state && ( state->as_recorded & ACL_STATE_RECORDED_VD )
                && state->as_vd_acl == a )
        {