/* 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-2004 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"
#include "sets.h"
#include "lber_pvt.h"
+#ifdef LDAP_SLAPI
+#include "slapi/slapi.h"
+#endif /* LDAPI_SLAPI */
+
#define ACL_BUF_SIZE 1024 /* use most appropriate size */
/*
AccessControl *ac, int *count,
Operation *op, Entry *e,
AttributeDescription *desc,
+ struct berval *val,
int nmatches, regmatch_t *matches );
static slap_control_t acl_mask(
goto done;
}
-#ifdef LDAP_SLAPI
- ret = slapi_x_access_allowed( op, e, desc, val, access, state );
- if ( ret == 0 ) {
- /* ACL plugin denied access */
- goto done;
- }
-#endif /* LDAP_SLAPI */
-
be = op->o_bd;
if ( be == NULL ) {
be = &backends[0];
}
assert( be != NULL );
+#ifdef LDAP_SLAPI
+ if ( op->o_pb != NULL ) {
+ ret = slapi_int_access_allowed( op, e, desc, val, access, state );
+ if ( ret == 0 ) {
+ /* ACL plugin denied access */
+ goto done;
+ }
+ }
+#endif /* LDAP_SLAPI */
+
/* grant database root access */
if ( be != NULL && be_isroot( be, &op->o_ndn ) ) {
#ifdef NEW_LOGGING
goto vd_access;
} else {
+ if ( state ) state->as_vi_acl = NULL;
a = NULL;
ACL_INIT(mask);
count = 0;
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;
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;
Operation *op,
Entry *e,
AttributeDescription *desc,
+ struct berval *val,
int nmatch,
regmatch_t *matches )
{
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
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 ( a->acl_attrs[0].an_desc->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) {
+ if (value_match( &match, desc,
+ desc->ad_type->sat_equality, 0,
+ val, &a->acl_attrval, &text ) != LDAP_SUCCESS ||
+ match )
+ return ACL_BREAK;
+
+ } else {
+ int patlen, vdnlen, rc, got_match = 0;
+ struct berval vdn = { 0, NULL };
+
+ /* it is a DN */
+ assert( a->acl_attrs[0].an_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName );
+
+ rc = dnNormalize( 0, NULL, NULL, val, &vdn,
+ op->o_tmpmemctx );
+ if ( rc != LDAP_SUCCESS ) {
+ /* error */
+ return ACL_BREAK;
+ }
+
+ patlen = a->acl_attrval.bv_len;
+ vdnlen = vdn.bv_len;
+
+ if ( vdnlen < patlen )
+ goto attrval_cleanup;
+
+ if ( a->acl_dn_style == ACL_STYLE_BASE ) {
+ if ( vdnlen > patlen )
+ goto attrval_cleanup;
+
+ } else if ( a->acl_dn_style == ACL_STYLE_ONE ) {
+ int rdnlen = -1;
+
+ if ( !DN_SEPARATOR( vdn.bv_val[vdnlen - patlen - 1] ) )
+ goto attrval_cleanup;
+
+ rdnlen = dn_rdnlen( NULL, &vdn );
+ if ( rdnlen != vdnlen - patlen - 1 )
+ goto attrval_cleanup;
+
+ } else if ( a->acl_dn_style == ACL_STYLE_SUBTREE ) {
+ if ( vdnlen > patlen && !DN_SEPARATOR( vdn.bv_val[vdnlen - patlen - 1] ) )
+ goto attrval_cleanup;
+
+ } else if ( a->acl_dn_style == ACL_STYLE_CHILDREN ) {
+ if ( vdnlen <= patlen )
+ goto attrval_cleanup;
+
+ if ( !DN_SEPARATOR( vdn.bv_val[vdnlen - patlen - 1] ) )
+ goto attrval_cleanup;
+ }
+
+ got_match = strcmp( a->acl_attrval.bv_val, vdn.bv_val + vdnlen - patlen );
+
+attrval_cleanup:;
+ if ( vdn.bv_val )
+ free( vdn.bv_val );
+
+ if ( !got_match )
+ return ACL_BREAK;
+
+ }
+ }
+ }
+
if( state && ( state->as_recorded & ACL_STATE_RECORDED_VD )
&& state->as_vd_acl == a )
{
{
struct berval *bv;
AccessControlState state = ACL_STATE_INIT;
+ Backend *be;
+ int be_null = 0;
+ int ret = 1; /* default is access allowed */
- assert( op->o_bd != NULL );
+ be = op->o_bd;
+ if ( be == NULL ) {
+ be = &backends[0];
+ be_null = 1;
+ op->o_bd = be;
+ }
+ assert( be != NULL );
/* short circuit root database access */
if ( be_isroot( op->o_bd, &op->o_ndn ) ) {
"<= acl_access_allowed: granted to database root\n",
0, 0, 0 );
#endif
- return 1;
+ goto done;
}
/* use backend default access if no backend acls */
access2str( ACL_WRITE ),
op->o_bd->be_dfltaccess >= ACL_WRITE ? "granted" : "denied", op->o_dn.bv_val );
#endif
- return op->o_bd->be_dfltaccess >= ACL_WRITE;
-
-#ifdef notdef
- /* op->o_bd is always non-NULL */
- /* use global default access if no global acls */
- } else if ( op->o_bd == NULL && global_acl == NULL ) {
-#ifdef NEW_LOGGING
- LDAP_LOG( ACL, DETAIL1,
- "acl_check_modlist: global default %s access %s to \"%s\"\n",
- access2str( ACL_WRITE ),
- global_default_access >= ACL_WRITE ? "granted" : "denied",
- op->o_dn );
-#else
- Debug( LDAP_DEBUG_ACL,
- "=> access_allowed: global default %s access %s to \"%s\"\n",
- access2str( ACL_WRITE ),
- global_default_access >= ACL_WRITE ? "granted" : "denied", op->o_dn );
-#endif
- return global_default_access >= ACL_WRITE;
-#endif
+ ret = (op->o_bd->be_dfltaccess >= ACL_WRITE);
+ goto done;
}
for ( ; mlist != NULL; mlist = mlist->sml_next ) {
if ( ! access_allowed( op, e,
mlist->sml_desc, NULL, ACL_WRITE, &state ) )
{
- return( 0 );
+ ret = 0;
+ goto done;
}
if ( mlist->sml_bvalues == NULL ) break;
if ( ! access_allowed( op, e,
mlist->sml_desc, bv, ACL_WRITE, &state ) )
{
- return( 0 );
+ ret = 0;
+ goto done;
}
}
break;
if ( ! access_allowed( op, e,
mlist->sml_desc, NULL, ACL_WRITE, NULL ) )
{
- return( 0 );
+ ret = 0;
+ goto done;
}
break;
}
if ( ! access_allowed( op, e,
mlist->sml_desc, bv, ACL_WRITE, &state ) )
{
- return( 0 );
+ ret = 0;
+ goto done;
}
}
break;
default:
assert( 0 );
- return( 0 );
+ /* not reached */
+ ret = 0;
+ break;
}
}
- return( 1 );
+done:
+ if (be_null) op->o_bd = NULL;
+ return( ret );
}
static int