X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Faclparse.c;h=9b0e8e7acb507e733e7b45a378e3745fe82fd3b9;hb=86bd3651e1bc6129cf2bd4ba271f33207843aaff;hp=8c3738c4d6186358824ec7d341e5771366437423;hpb=b34cf024884cf35572d98164381537f256b6dfee;p=openldap
diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c
index 8c3738c4d6..9b0e8e7acb 100644
--- a/servers/slapd/aclparse.c
+++ b/servers/slapd/aclparse.c
@@ -2,7 +2,7 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software .
*
- * Copyright 1998-2004 The OpenLDAP Foundation.
+ * Copyright 1998-2005 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,14 +38,19 @@
#include "lber_pvt.h"
#include "lutil.h"
-static char *style_strings[] = {
+static const char style_base[] = "base";
+char *style_strings[] = {
"regex",
"expand",
- "base",
+ "exact",
"one",
"subtree",
"children",
+ "level",
"attrof",
+ "anonymous",
+ "users",
+ "self",
"ip",
"path",
NULL
@@ -59,21 +64,63 @@ 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
-#ifdef LDAP_DEVEL
+static int check_scope( BackendDB *be, AccessControl *a );
+
+#ifdef SLAP_DYNACL
static int
-check_scope( BackendDB *be, AccessControl *a );
-#endif /* LDAP_DEVEL */
+slap_dynacl_config(
+ const char *fname,
+ int lineno,
+ Access *b,
+ const char *name,
+ const char *opts,
+ slap_style_t sty,
+ const char *right )
+{
+ slap_dynacl_t *da, *tmp;
+ int rc = 0;
+
+ for ( da = b->a_dynacl; da; da = da->da_next ) {
+ if ( strcasecmp( da->da_name, name ) == 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: dynacl \"%s\" already specified.\n",
+ fname, lineno, name );
+ acl_usage();
+ }
+ }
+
+ da = slap_dynacl_get( name );
+ if ( da == NULL ) {
+ return -1;
+ }
+
+ tmp = ch_malloc( sizeof( slap_dynacl_t ) );
+ *tmp = *da;
+
+ if ( tmp->da_parse ) {
+ rc = ( *tmp->da_parse )( fname, lineno, opts, sty, right, &tmp->da_private );
+ if ( rc ) {
+ ch_free( tmp );
+ return rc;
+ }
+ }
+
+ tmp->da_next = b->a_dynacl;
+ b->a_dynacl = tmp;
+
+ return 0;
+}
+#endif /* SLAP_DYNACL */
static void
regtest(const char *fname, int lineno, char *pat) {
int e;
regex_t re;
- char buf[512];
- unsigned size;
+ char buf[ SLAP_TEXT_BUFLEN ];
+ unsigned size;
char *sp;
char *dp;
@@ -103,26 +150,29 @@ regtest(const char *fname, int lineno, char *pat) {
}
*dp = '\0';
- if ( size >= (sizeof(buf)-1) ) {
- fprintf( stderr,
+ if ( size >= (sizeof(buf) - 1) ) {
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: regular expression \"%s\" too large\n",
fname, lineno, pat );
acl_usage();
}
if ((e = regcomp(&re, buf, REG_EXTENDED|REG_ICASE))) {
- char error[512];
+ char error[ SLAP_TEXT_BUFLEN ];
+
regerror(e, &re, error, sizeof(error));
- fprintf( stderr,
- "%s: line %d: regular expression \"%s\" bad because of %s\n",
- fname, lineno, pat, error );
+
+ snprintf( buf, sizeof( buf ),
+ "regular expression \"%s\" bad because of %s",
+ pat, error );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
acl_usage();
}
regfree(&re);
}
-#ifdef LDAP_DEVEL
-
/*
* Experimental
*
@@ -138,43 +188,59 @@ regtest(const char *fname, int lineno, char *pat) {
static int
check_scope( BackendDB *be, AccessControl *a )
{
- int patlen;
+ ber_len_t patlen;
struct berval dn;
- dn = be->be_nsuffix[ 0 ];
+ dn = be->be_nsuffix[0];
+
+ if ( BER_BVISEMPTY( &dn ) ) {
+ return ACL_SCOPE_OK;
+ }
- if ( a->acl_dn_pat.bv_len || ( a->acl_dn_style != ACL_STYLE_REGEX ) ) {
+ if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
+ a->acl_dn_style != ACL_STYLE_REGEX )
+ {
slap_style_t style = a->acl_dn_style;
if ( style == ACL_STYLE_REGEX ) {
- char dnbuf[ SLAP_LDAPDN_MAXLEN + 2 ];
- char rebuf[ SLAP_LDAPDN_MAXLEN + 1 ];
- regex_t re;
- int rc;
+ char dnbuf[SLAP_LDAPDN_MAXLEN + 2];
+ char rebuf[SLAP_LDAPDN_MAXLEN + 1];
+ ber_len_t rebuflen;
+ regex_t re;
+ int rc;
- /* add trailing '$' */
- AC_MEMCPY( dnbuf, be->be_nsuffix[ 0 ].bv_val,
- be->be_nsuffix[ 0 ].bv_len );
- dnbuf[ be->be_nsuffix[ 0 ].bv_len ] = '$';
- dnbuf[ be->be_nsuffix[ 0 ].bv_len + 1 ] = '\0';
+ /* add trailing '$' to database suffix to form
+ * a simple trial regex pattern "$" */
+ AC_MEMCPY( dnbuf, be->be_nsuffix[0].bv_val,
+ be->be_nsuffix[0].bv_len );
+ dnbuf[be->be_nsuffix[0].bv_len] = '$';
+ dnbuf[be->be_nsuffix[0].bv_len + 1] = '\0';
if ( regcomp( &re, dnbuf, REG_EXTENDED|REG_ICASE ) ) {
return ACL_SCOPE_WARN;
}
- /* remove trailing '$' */
- AC_MEMCPY( rebuf, a->acl_dn_pat.bv_val,
- a->acl_dn_pat.bv_len + 1 );
- if ( a->acl_dn_pat.bv_val[ a->acl_dn_pat.bv_len - 1 ] == '$' ) {
- rebuf[ a->acl_dn_pat.bv_len - 1 ] = '\0';
+ /* remove trailing ')$', if any, from original
+ * regex pattern */
+ rebuflen = a->acl_dn_pat.bv_len;
+ AC_MEMCPY( rebuf, a->acl_dn_pat.bv_val, rebuflen + 1 );
+ if ( rebuf[rebuflen - 1] == '$' ) {
+ rebuf[--rebuflen] = '\0';
+ }
+ while ( rebuflen > be->be_nsuffix[0].bv_len && rebuf[rebuflen - 1] == ')' ) {
+ rebuf[--rebuflen] = '\0';
+ }
+ if ( rebuflen == be->be_nsuffix[0].bv_len ) {
+ rc = ACL_SCOPE_WARN;
+ goto regex_done;
}
/* not a clear indication of scoping error, though */
rc = regexec( &re, rebuf, 0, NULL, 0 )
? ACL_SCOPE_WARN : ACL_SCOPE_OK;
+regex_done:;
regfree( &re );
-
return rc;
}
@@ -185,19 +251,19 @@ check_scope( BackendDB *be, AccessControl *a )
* match */
if ( dn.bv_len > patlen ) {
/* base is blatantly wrong */
- if ( style == ACL_STYLE_BASE ) {
- return ACL_SCOPE_ERR;
- }
+ if ( style == ACL_STYLE_BASE ) return ACL_SCOPE_ERR;
- /* one can be wrong if there is more
- * than one level between the suffix
+ /* a style of one can be wrong if there is
+ * more than one level between the suffix
* and the pattern */
if ( style == ACL_STYLE_ONE ) {
- int rdnlen = -1, sep = 0;
+ ber_len_t rdnlen = 0;
+ int sep = 0;
if ( patlen > 0 ) {
- if ( !NDN_SEPARATOR( dn.bv_val[ dn.bv_len - patlen - 1 ] ) )
+ if ( !DN_SEPARATOR( dn.bv_val[dn.bv_len - patlen - 1] )) {
return ACL_SCOPE_ERR;
+ }
sep = 1;
}
@@ -208,7 +274,9 @@ check_scope( BackendDB *be, AccessControl *a )
/* if the trailing part doesn't match,
* then it's an error */
- if ( strcmp( a->acl_dn_pat.bv_val, &dn.bv_val[ dn.bv_len - patlen ] ) != 0 ) {
+ if ( strcmp( a->acl_dn_pat.bv_val,
+ &dn.bv_val[dn.bv_len - patlen] ) != 0 )
+ {
return ACL_SCOPE_ERR;
}
@@ -227,11 +295,15 @@ check_scope( BackendDB *be, AccessControl *a )
break;
}
- if ( dn.bv_len < patlen && !NDN_SEPARATOR( a->acl_dn_pat.bv_val[ patlen -dn.bv_len - 1 ] ) ) {
+ if ( dn.bv_len < patlen &&
+ !DN_SEPARATOR( a->acl_dn_pat.bv_val[patlen - dn.bv_len - 1] ))
+ {
return ACL_SCOPE_ERR;
}
- if ( strcmp( &a->acl_dn_pat.bv_val[ patlen - dn.bv_len ], dn.bv_val ) != 0 ) {
+ if ( strcmp( &a->acl_dn_pat.bv_val[patlen - dn.bv_len], dn.bv_val )
+ != 0 )
+ {
return ACL_SCOPE_ERR;
}
@@ -240,7 +312,6 @@ check_scope( BackendDB *be, AccessControl *a )
return ACL_SCOPE_UNKNOWN;
}
-#endif /* LDAP_DEVEL */
void
parse_acl(
@@ -248,11 +319,11 @@ parse_acl(
const char *fname,
int lineno,
int argc,
- char **argv
-)
+ char **argv,
+ int pos )
{
int i;
- char *left, *right, *style;
+ char *left, *right, *style, *next;
struct berval bv;
AccessControl *a;
Access *b;
@@ -264,9 +335,9 @@ parse_acl(
/* to clause - select which entries are protected */
if ( strcasecmp( argv[i], "to" ) == 0 ) {
if ( a != NULL ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"only one to clause allowed in access line\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
a = (AccessControl *) ch_calloc( 1, sizeof(AccessControl) );
@@ -277,18 +348,17 @@ parse_acl(
}
if ( strcasecmp( argv[i], "*" ) == 0 ) {
- if( a->acl_dn_pat.bv_len ||
- ( a->acl_dn_style != ACL_STYLE_REGEX ) )
+ if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
+ a->acl_dn_style != ACL_STYLE_REGEX )
{
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: dn pattern"
" already specified in to clause.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
- a->acl_dn_pat.bv_val = ch_strdup( "*" );
- a->acl_dn_pat.bv_len = 1;
+ ber_str2bv( "*", STRLENOF( "*" ), 1, &a->acl_dn_pat );
continue;
}
@@ -296,41 +366,42 @@ parse_acl(
split( left, '.', &left, &style );
if ( right == NULL ) {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%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.bv_len != 0 ||
- ( a->acl_dn_style != ACL_STYLE_REGEX ) )
+ if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
+ a->acl_dn_style != ACL_STYLE_REGEX )
{
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: dn pattern"
" already specified in to clause.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
if ( style == NULL || *style == '\0' ||
- ( strcasecmp( style, "base" ) == 0 ) ||
- ( strcasecmp( style, "exact" ) == 0 ))
+ strcasecmp( style, "baseObject" ) == 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 );
- } else if ( strcasecmp( style, "onelevel" ) == 0
- || strcasecmp( style, "one" ) == 0 ) {
+ } else if ( strcasecmp( style, "oneLevel" ) == 0 ||
+ strcasecmp( style, "one" ) == 0 )
+ {
a->acl_dn_style = ACL_STYLE_ONE;
ber_str2bv( right, 0, 1, &a->acl_dn_pat );
- } else if ( strcasecmp( style, "subtree" ) == 0
- || strcasecmp( style, "sub" ) == 0 )
+ } else if ( strcasecmp( style, "subtree" ) == 0 ||
+ strcasecmp( style, "sub" ) == 0 )
{
if( *right == '\0' ) {
- a->acl_dn_pat.bv_val = ch_strdup( "*" );
- a->acl_dn_pat.bv_len = 1;
+ ber_str2bv( "*", STRLENOF( "*" ), 1, &a->acl_dn_pat );
} else {
a->acl_dn_style = ACL_STYLE_SUBTREE;
@@ -357,15 +428,14 @@ parse_acl(
|| strcmp(right, ".*$$") == 0
|| strcmp(right, "^.*$$") == 0 )
{
- a->acl_dn_pat.bv_val = ch_strdup( "*" );
- a->acl_dn_pat.bv_len = sizeof("*")-1;
+ ber_str2bv( "*", STRLENOF("*"), 1, &a->acl_dn_pat );
} else {
acl_regex_normalized_dn( right, &a->acl_dn_pat );
}
} else {
- fprintf( stderr, "%s: line %d: "
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"unknown dn style \"%s\" in to clause\n",
fname, lineno, style );
acl_usage();
@@ -376,122 +446,246 @@ parse_acl(
if ( strcasecmp( left, "filter" ) == 0 ) {
if ( (a->acl_filter = str2filter( right )) == NULL ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: bad filter \"%s\" in to clause\n",
fname, lineno, right );
acl_usage();
}
- } else if ( strcasecmp( left, "attr" ) == 0
- || strcasecmp( left, "attrs" ) == 0 ) {
+ } else if ( strcasecmp( left, "attr" ) == 0 /* TOLERATED */
+ || strcasecmp( left, "attrs" ) == 0 ) /* DOCUMENTED */
+ {
+ if ( strcasecmp( left, "attr" ) == 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: \"attr\" "
+ "is deprecated (and undocumented); "
+ "use \"attrs\" instead.\n",
+ fname, lineno, 0 );
+ }
+
a->acl_attrs = str2anlist( a->acl_attrs,
right, "," );
if ( a->acl_attrs == NULL ) {
- fprintf( stderr,
+ Debug( LDAP_DEBUG_ANY,
"%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,
+ char *mr;
+
+ if ( !BER_BVISEMPTY( &a->acl_attrval ) ) {
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: attr val already specified in to clause.\n",
- fname, lineno );
+ fname, lineno, 0 );
acl_usage();
}
- if ( a->acl_attrs == NULL || a->acl_attrs[1].an_name.bv_val ) {
- fprintf( stderr,
+ if ( a->acl_attrs == NULL || !BER_BVISEMPTY( &a->acl_attrs[1].an_name ) )
+ {
+ Debug( LDAP_DEBUG_ANY,
"%s: line %d: attr val requires a single attribute.\n",
- fname, lineno );
+ fname, lineno, 0 );
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 );
+ a->acl_attrval_style = ACL_STYLE_BASE;
+
+ mr = strchr( left, '/' );
+ if ( mr != NULL ) {
+ mr[ 0 ] = '\0';
+ mr++;
+
+ a->acl_attrval_mr = mr_find( mr );
+ if ( a->acl_attrval_mr == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "invalid matching rule \"%s\".\n",
+ fname, lineno, mr );
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" ) ) {
+ if( !mr_usable_with_at( a->acl_attrval_mr, a->acl_attrs[ 0 ].an_desc->ad_type ) )
+ {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "matching rule \"%s\" use "
+ "with attr \"%s\" not appropriate.",
+ mr, a->acl_attrs[ 0 ].an_name.bv_val );
+
+
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n",
+ fname, lineno, buf );
+ acl_usage();
+ }
+ }
+
+ if ( style != NULL ) {
+ if ( 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 err[SLAP_TEXT_BUFLEN],
+ buf[ SLAP_TEXT_BUFLEN ];
+
+ regerror( e, &a->acl_attrval_re, err, sizeof( err ) );
+
+ snprintf( buf, sizeof( buf ),
+ "regular expression \"%s\" bad because of %s",
+ right, err );
+
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n",
+ fname, lineno, 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, "base" ) ||
+ !strcasecmp( style, "exact" ) ) {
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 if ( a->acl_attrs[0].an_desc->ad_type->
+ sat_syntax == slap_schema.si_syn_distinguishedName )
+ {
+ struct berval bv;
+
+ if ( !strcasecmp( style, "baseObject" ) ||
+ !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 {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ /* FIXME: should be an error */
+
+ snprintf( buf, sizeof( buf ),
+ "unknown val.