X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Faclparse.c;h=67081a149ff3d122280cea8f8029020f678803d6;hb=e4b899df95374d56f79350a146fea649db3b2a57;hp=7f008dfd0300248efd09249c2de6280b5c7bb778;hpb=0ec43c31bab5c343bd3b930829a695e9dcd2f15e;p=openldap
diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c
index 7f008dfd03..67081a149f 100644
--- a/servers/slapd/aclparse.c
+++ b/servers/slapd/aclparse.c
@@ -1,8 +1,27 @@
-/* acl.c - routines to parse and check acl's */
+/* aclparse.c - routines to parse and check acl's */
/* $OpenLDAP$ */
-/*
- * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* This work is part of OpenLDAP Software .
+ *
+ * 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
+ * .
+ */
+/* 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"
@@ -16,17 +35,24 @@
#include
#include "slap.h"
+#include "lber_pvt.h"
+#include "lutil.h"
+
+static char *style_strings[] = { "regex",
+ "base", "one", "subtree", "children", NULL };
static void split(char *line, int splitchar, char **left, char **right);
static void access_append(Access **l, Access *a);
static void acl_usage(void) LDAP_GCCATTR((noreturn));
+static void acl_regex_normalized_dn(const char *src, struct berval *pat);
+
#ifdef LDAP_DEBUG
static void print_acl(Backend *be, AccessControl *a);
static void print_access(Access *b);
#endif
-static int
+static void
regtest(const char *fname, int lineno, char *pat) {
int e;
regex_t re;
@@ -76,10 +102,8 @@ regtest(const char *fname, int lineno, char *pat) {
"%s: line %d: regular expression \"%s\" bad because of %s\n",
fname, lineno, pat, error );
acl_usage();
- return(0);
}
regfree(&re);
- return(1);
}
void
@@ -92,26 +116,24 @@ parse_acl(
)
{
int i;
- char *left, *right;
+ char *left, *right, *style;
+ struct berval bv;
AccessControl *a;
Access *b;
+ int rc;
+ const char *text;
a = NULL;
for ( i = 1; i < argc; i++ ) {
/* to clause - select which entries are protected */
if ( strcasecmp( argv[i], "to" ) == 0 ) {
if ( a != NULL ) {
- fprintf( stderr,
- "%s: line %d: only one to clause allowed in access line\n",
+ fprintf( stderr, "%s: line %d: "
+ "only one to clause allowed in access line\n",
fname, lineno );
acl_usage();
}
a = (AccessControl *) ch_calloc( 1, sizeof(AccessControl) );
- a->acl_filter = NULL;
- a->acl_dn_pat = NULL;
- a->acl_attrs = NULL;
- a->acl_access = NULL;
- a->acl_next = NULL;
for ( ++i; i < argc; i++ ) {
if ( strcasecmp( argv[i], "by" ) == 0 ) {
i--;
@@ -119,7 +141,9 @@ parse_acl(
}
if ( strcasecmp( argv[i], "*" ) == 0 ) {
- if( a->acl_dn_pat != NULL ) {
+ if( a->acl_dn_pat.bv_len ||
+ ( a->acl_dn_style != ACL_STYLE_REGEX ) )
+ {
fprintf( stderr,
"%s: line %d: dn pattern"
" already specified in to clause.\n",
@@ -127,14 +151,25 @@ parse_acl(
acl_usage();
}
- a->acl_dn_pat = ch_strdup( "*" );
+ a->acl_dn_pat.bv_val = ch_strdup( "*" );
+ a->acl_dn_pat.bv_len = 1;
continue;
}
split( argv[i], '=', &left, &right );
+ split( left, '.', &left, &style );
+
+ if ( right == NULL ) {
+ fprintf( stderr, "%s: line %d: "
+ "missing \"=\" in \"%s\" in to clause\n",
+ fname, lineno, left );
+ acl_usage();
+ }
if ( strcasecmp( left, "dn" ) == 0 ) {
- if( a->acl_dn_pat != NULL ) {
+ if( a->acl_dn_pat.bv_len != 0 ||
+ ( a->acl_dn_style != ACL_STYLE_REGEX ) )
+ {
fprintf( stderr,
"%s: line %d: dn pattern"
" already specified in to clause.\n",
@@ -142,43 +177,68 @@ parse_acl(
acl_usage();
}
- if ( right == NULL ) {
- fprintf( stderr,
- "%s: line %d: missing \"=\" in \"%s\" in to clause\n",
- fname, lineno, left );
- acl_usage();
- }
+ if ( style == NULL || *style == '\0' ||
+ ( strcasecmp( style, "base" ) == 0 ) ||
+ ( strcasecmp( style, "exact" ) == 0 ))
+ {
+ a->acl_dn_style = ACL_STYLE_BASE;
+ ber_str2bv( right, 0, 1, &a->acl_dn_pat );
- if( *right == '\0' ) {
- a->acl_dn_pat = ch_strdup("^$");
+ } else if ( strcasecmp( style, "one" ) == 0 ) {
+ a->acl_dn_style = ACL_STYLE_ONE;
+ ber_str2bv( right, 0, 1, &a->acl_dn_pat );
- } else if ( strcmp(right, "*") == 0
- || strcmp(right, ".*") == 0
- || strcmp(right, ".*$") == 0
- || strcmp(right, "^.*") == 0
- || strcmp(right, "^.*$$") == 0
- || strcmp(right, ".*$$") == 0
- || strcmp(right, "^.*$$") == 0 )
+ } else if ( strcasecmp( style, "subtree" ) == 0
+ || strcasecmp( style, "sub" ) == 0 )
{
- a->acl_dn_pat = ch_strdup( "*" );
+ if( *right == '\0' ) {
+ a->acl_dn_pat.bv_val = ch_strdup( "*" );
+ a->acl_dn_pat.bv_len = 1;
+
+ } else {
+ a->acl_dn_style = ACL_STYLE_SUBTREE;
+ ber_str2bv( right, 0, 1, &a->acl_dn_pat );
+ }
+
+ } else if ( strcasecmp( style, "children" ) == 0 ) {
+ a->acl_dn_style = ACL_STYLE_CHILDREN;
+ ber_str2bv( right, 0, 1, &a->acl_dn_pat );
+
+ } else if ( strcasecmp( style, "regex" ) == 0 ) {
+ a->acl_dn_style = ACL_STYLE_REGEX;
+
+ if ( *right == '\0' ) {
+ /* empty regex should match empty DN */
+ a->acl_dn_style = ACL_STYLE_BASE;
+ ber_str2bv( right, 0, 1, &a->acl_dn_pat );
+
+ } else if ( strcmp(right, "*") == 0
+ || strcmp(right, ".*") == 0
+ || strcmp(right, ".*$") == 0
+ || strcmp(right, "^.*") == 0
+ || strcmp(right, "^.*$") == 0
+ || strcmp(right, ".*$$") == 0
+ || strcmp(right, "^.*$$") == 0 )
+ {
+ a->acl_dn_pat.bv_val = ch_strdup( "*" );
+ a->acl_dn_pat.bv_len = sizeof("*")-1;
+
+ } else {
+ acl_regex_normalized_dn( right, &a->acl_dn_pat );
+ }
} else {
- a->acl_dn_pat = ch_strdup( right );
+ fprintf( stderr, "%s: line %d: "
+ "unknown dn style \"%s\" in to clause\n",
+ fname, lineno, style );
+ acl_usage();
}
continue;
}
- if ( right == NULL || *right == '\0' ) {
- fprintf( stderr,
- "%s: line %d: missing \"=\" in (or value after) \"%s\" in to clause\n",
- fname, lineno, left );
- acl_usage();
- }
-
if ( strcasecmp( left, "filter" ) == 0 ) {
- if ( (a->acl_filter = str2filter(
- right )) == NULL ) {
+ if ( (a->acl_filter = str2filter( right )) == NULL ) {
fprintf( stderr,
"%s: line %d: bad filter \"%s\" in to clause\n",
fname, lineno, right );
@@ -186,12 +246,75 @@ parse_acl(
}
} else if ( strncasecmp( left, "attr", 4 ) == 0 ) {
- char **alist;
-
- alist = str2charray( right, "," );
- charray_merge( &a->acl_attrs, alist );
- charray_free( alist );
+ a->acl_attrs = str2anlist( a->acl_attrs,
+ right, "," );
+ if ( a->acl_attrs == NULL ) {
+ fprintf( stderr,
+ "%s: line %d: unknown attr \"%s\" in to clause\n",
+ fname, lineno, right );
+ acl_usage();
+ }
+ } else if ( strncasecmp( left, "val", 3 ) == 0 ) {
+ if ( a->acl_attrval.bv_len ) {
+ fprintf( stderr,
+ "%s: line %d: attr val already specified in to clause.\n",
+ fname, lineno );
+ acl_usage();
+ }
+ if ( a->acl_attrs == NULL || a->acl_attrs[1].an_name.bv_val ) {
+ fprintf( stderr,
+ "%s: line %d: attr val requires a single attribute.\n",
+ fname, lineno );
+ acl_usage();
+ }
+ ber_str2bv( right, 0, 1, &a->acl_attrval );
+ if ( style && strcasecmp( style, "regex" ) == 0 ) {
+ int e = regcomp( &a->acl_attrval_re, a->acl_attrval.bv_val,
+ REG_EXTENDED | REG_ICASE | REG_NOSUB );
+ if ( e ) {
+ char buf[512];
+ regerror( e, &a->acl_attrval_re, buf, sizeof(buf) );
+ fprintf( stderr, "%s: line %d: "
+ "regular expression \"%s\" bad because of %s\n",
+ fname, lineno, right, buf );
+ acl_usage();
+ }
+ a->acl_attrval_style = ACL_STYLE_REGEX;
+ } else {
+ /* FIXME: if the attribute has DN syntax,
+ * we might allow one, subtree and children styles as well */
+ if ( !strcasecmp( style, "exact" ) ) {
+ a->acl_attrval_style = ACL_STYLE_BASE;
+
+ } else if ( a->acl_attrs[0].an_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) {
+ if ( !strcasecmp( style, "base" ) ) {
+ a->acl_attrval_style = ACL_STYLE_BASE;
+ } else if ( !strcasecmp( style, "onelevel" ) || !strcasecmp( style, "one" ) ) {
+ a->acl_attrval_style = ACL_STYLE_ONE;
+ } else if ( !strcasecmp( style, "subtree" ) || !strcasecmp( style, "sub" ) ) {
+ a->acl_attrval_style = ACL_STYLE_SUBTREE;
+ } else if ( !strcasecmp( style, "children" ) ) {
+ a->acl_attrval_style = ACL_STYLE_CHILDREN;
+ } else {
+ fprintf( stderr,
+ "%s: line %d: unknown val.