/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2003 The OpenLDAP Foundation.
+ * Copyright 1998-2004 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "lber_pvt.h"
#include "lutil.h"
-static char *style_strings[] = { "regex",
- "base", "one", "subtree", "children", NULL };
+static char *style_strings[] = {
+ "regex",
+ "expand",
+ "base",
+ "one",
+ "subtree",
+ "children",
+ "attrof",
+ "ip",
+ "path",
+ NULL
+};
static void split(char *line, int splitchar, char **left, char **right);
static void access_append(Access **l, Access *a);
} else if ( strcasecmp( style, "regex" ) == 0 ) {
sty = ACL_STYLE_REGEX;
+ } else if ( strcasecmp( style, "expand" ) == 0 ) {
+ sty = ACL_STYLE_EXPAND;
+
+ } else if ( strcasecmp( style, "ip" ) == 0 ) {
+ sty = ACL_STYLE_IP;
+
+ } else if ( strcasecmp( style, "path" ) == 0 ) {
+ sty = ACL_STYLE_PATH;
+#ifndef LDAP_PF_LOCAL
+ fprintf( stderr, "%s: line %d: "
+ "path style modifier is useless without local\n",
+ fname, lineno );
+#endif /* LDAP_PF_LOCAL */
+
} else {
fprintf( stderr,
"%s: line %d: unknown style \"%s\" in by clause\n",
if ( style_modifier &&
strcasecmp( style_modifier, "expand" ) == 0 )
{
- expand = 1;
+ switch ( sty ) {
+ case ACL_STYLE_REGEX:
+ fprintf( stderr, "%s: line %d: "
+ "\"regex\" style implies "
+ "\"expand\" modifier (ignored)\n",
+ fname, lineno );
+ break;
+
+ case ACL_STYLE_EXPAND:
+ fprintf( stderr, "%s: line %d: "
+ "\"expand\" style used "
+ "in conjunction with "
+ "\"expand\" modifier (ignored)\n",
+ fname, lineno );
+ break;
+
+ default:
+ /* we'll see later if it's pertinent */
+ expand = 1;
+ break;
+ }
+ }
+
+ /* expand in <who> needs regex in <what> */
+ if ( ( sty == ACL_STYLE_EXPAND || expand )
+ && a->acl_dn_style != ACL_STYLE_REGEX )
+ {
+ fprintf( stderr, "%s: line %d: "
+ "\"expand\" style or modifier used "
+ "in conjunction with "
+ "a non-regex <what> clause\n",
+ fname, lineno );
}
+
if ( strcasecmp( argv[i], "*" ) == 0 ) {
bv.bv_val = ch_strdup( "*" );
bv.bv_len = 1;
char *name = NULL;
char *value = NULL;
- if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
+ switch ( sty ) {
+ case ACL_STYLE_REGEX:
+ /* legacy, tolerated */
+ fprintf( stderr, "%s: line %d: "
+ "deprecated group style \"regex\"; "
+ "use \"expand\" instead\n",
+ fname, lineno, style );
+ sty = ACL_STYLE_EXPAND;
+ break;
+
+ case ACL_STYLE_BASE:
+ /* legal, traditional */
+ case ACL_STYLE_EXPAND:
+ /* legal, substring expansion; supersedes regex */
+ break;
+
+ default:
+ /* unknown */
fprintf( stderr, "%s: line %d: "
"inappropriate style \"%s\" in by clause\n",
- fname, lineno, style );
+ fname, lineno, style );
acl_usage();
}
}
b->a_group_style = sty;
- if (sty == ACL_STYLE_REGEX) {
+ if (sty == ACL_STYLE_EXPAND) {
acl_regex_normalized_dn( right, &bv );
if ( !ber_bvccmp( &bv, '*' ) ) {
regtest(fname, lineno, bv.bv_val);
}
if ( strcasecmp( left, "peername" ) == 0 ) {
- if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
+ switch (sty) {
+ case ACL_STYLE_REGEX:
+ case ACL_STYLE_BASE:
+ /* legal, traditional */
+ case ACL_STYLE_EXPAND:
+ /* cheap replacement to regex for simple expansion */
+ case ACL_STYLE_IP:
+ case ACL_STYLE_PATH:
+ /* legal, peername specific */
+ break;
+
+ default:
fprintf( stderr, "%s: line %d: "
"inappropriate style \"%s\" in by clause\n",
fname, lineno, style );
regtest(fname, lineno, bv.bv_val);
}
b->a_peername_pat = bv;
+
} else {
ber_str2bv( right, 0, 1, &b->a_peername_pat );
+
+ if ( sty == ACL_STYLE_IP ) {
+ char *addr = NULL,
+ *mask = NULL,
+ *port = NULL;
+
+ split( right, '{', &addr, &port );
+ split( addr, '%', &addr, &mask );
+
+ b->a_peername_addr = inet_addr( addr );
+ if ( b->a_peername_addr == (unsigned long)(-1)) {
+ /* illegal address */
+ fprintf( stderr, "%s: line %d: "
+ "illegal peername address \"%s\".\n",
+ fname, lineno, addr );
+ acl_usage();
+ }
+
+ b->a_peername_mask = (unsigned long)(-1);
+ if ( mask != NULL ) {
+ b->a_peername_mask = inet_addr( mask );
+ if ( b->a_peername_mask == (unsigned long)(-1)) {
+ /* illegal mask */
+ fprintf( stderr, "%s: line %d: "
+ "illegal peername address mask \"%s\".\n",
+ fname, lineno, mask );
+ acl_usage();
+ }
+ }
+
+ b->a_peername_port = -1;
+ if ( port ) {
+ char *end = NULL;
+
+ b->a_peername_port = strtol( port, &end, 10 );
+ if ( end[ 0 ] != '}' ) {
+ /* illegal port */
+ fprintf( stderr, "%s: line %d: "
+ "illegal peername port specification \"{%s}\".\n",
+ fname, lineno, port );
+ acl_usage();
+ }
+ }
+ }
}
continue;
}
if ( strcasecmp( left, "sockname" ) == 0 ) {
- if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
+ switch (sty) {
+ case ACL_STYLE_REGEX:
+ case ACL_STYLE_BASE:
+ /* legal, traditional */
+ case ACL_STYLE_EXPAND:
+ /* cheap replacement to regex for simple expansion */
+ break;
+
+ default:
+ /* unknown */
fprintf( stderr, "%s: line %d: "
"inappropriate style \"%s\" in by clause\n",
fname, lineno, style );
case ACL_STYLE_REGEX:
case ACL_STYLE_BASE:
case ACL_STYLE_SUBTREE:
+ /* legal, traditional */
+ break;
+
+ case ACL_STYLE_EXPAND:
+ /* tolerated: means exact,expand */
+ if ( expand ) {
+ fprintf( stderr,
+ "%s: line %d: "
+ "\"expand\" modifier with \"expand\" style\n",
+ fname, lineno );
+ }
+ sty = ACL_STYLE_BASE;
+ expand = 1;
break;
default:
+ /* unknown */
fprintf( stderr,
"%s: line %d: inappropriate style \"%s\" in by clause\n",
fname, lineno, style );
}
if ( strcasecmp( left, "sockurl" ) == 0 ) {
- if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
- fprintf( stderr,
- "%s: line %d: inappropriate style \"%s\" in by clause\n",
+ switch (sty) {
+ case ACL_STYLE_REGEX:
+ case ACL_STYLE_BASE:
+ /* legal, traditional */
+ case ACL_STYLE_EXPAND:
+ /* cheap replacement to regex for simple expansion */
+ break;
+
+ default:
+ /* unknown */
+ fprintf( stderr, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause\n",
fname, lineno, style );
acl_usage();
}
"<who> ::= [ * | anonymous | users | self | dn[.<dnstyle>]=<DN> ]\n"
"\t[dnattr=<attrname>]\n"
"\t[group[/<objectclass>[/<attrname>]][.<style>]=<group>]\n"
- "\t[peername[.<style>]=<peer>] [sockname[.<style>]=<name>]\n",
- "\t[domain[.<style>]=<domain>] [sockurl[.<style>]=<url>]\n"
+ "\t[peername[.<peernamestyle>]=<peer>] [sockname[.<style>]=<name>]\n",
+ "\t[domain[.<domainstyle>]=<domain>] [sockurl[.<style>]=<url>]\n"
#ifdef SLAPD_ACI_ENABLED
"\t[aci=<attrname>]\n"
#endif
"\t[ssf=<n>] [transport_ssf=<n>] [tls_ssf=<n>] [sasl_ssf=<n>]\n"
- "<dnstyle> ::= base | exact | one | subtree | children | regex\n"
+ "<dnstyle> ::= base | exact | one(level) | sub(tree) | children | regex\n"
"<style> ::= regex | base | exact\n"
+ "<peernamestyle> ::= regex | exact | ip | path\n"
+ "<domainstyle> ::= regex | base | exact | sub(tree)\n"
"<access> ::= [self]{<level>|<priv>}\n"
"<level> ::= none | auth | compare | search | read | write\n"
"<priv> ::= {=|+|-}{w|r|s|c|x|0}+\n"
fprintf( stderr, " sockurl=\"%s\"", b->a_sockurl_pat.bv_val );
}
+ if ( b->a_set_pat.bv_len != 0 ) {
+ fprintf( stderr, " set=\"%s\"", b->a_set_pat.bv_val );
+ }
+
#ifdef SLAPD_ACI_ENABLED
if ( b->a_aci_at != NULL ) {
fprintf( stderr, " aci=%s", b->a_aci_at->ad_cname.bv_val );
}
if ( a->acl_filter != NULL ) {
- struct berval bv = { 0, NULL };
+ struct berval bv = BER_BVNULL;
to++;
filter2bv( a->acl_filter, &bv );
fprintf( stderr, " filter=%s\n", bv.bv_val );
fprintf( stderr, "," );
}
if (an->an_oc) {
- fputc( '@', stderr);
+ fputc( an->an_oc_exclude ? '!' : '@', stderr);
}
fputs( an->an_name.bv_val, stderr );
first = 0;