static void access_append(Access **l, Access *a);
static void acl_usage(void) LDAP_GCCATTR((noreturn));
+static char *acl_regex_normalized_dn(const char *pattern);
+
#ifdef LDAP_DEBUG
static void print_acl(Backend *be, AccessControl *a);
static void print_access(Access *b);
split( argv[i], '=', &left, &right );
split( left, '.', &left, &style );
- if ( right == NULL || *right == '\0' ) {
+ if ( right == NULL ) {
fprintf( stderr,
- "%s: line %d: missing \"=\" in (or value after) \"%s\" in to clause\n",
+ "%s: line %d: missing \"=\" in \"%s\" in to clause\n",
fname, lineno, left );
acl_usage();
}
a->acl_dn_pat = ch_strdup( "*" );
} else {
- a->acl_dn_pat = ch_strdup( right );
+ a->acl_dn_pat = acl_regex_normalized_dn( right );
}
} else if ( strcasecmp( style, "base" ) == 0 ) {
a->acl_dn_style = ACL_STYLE_BASE;
pat = ch_strdup( "*" );
} else {
- regtest(fname, lineno, right);
- pat = ch_strdup( right );
+ pat = acl_regex_normalized_dn( right );
+ regtest(fname, lineno, pat);
}
} else if ( right == NULL || *right == '\0' ) {
fprintf( stderr,
}
if ( strcasecmp( left, "dnattr" ) == 0 ) {
+ if ( right == NULL || right[ 0 ] == '\0' ) {
+ fprintf( stderr,
+ "%s: line %d: missing \"=\" in (or value after) \"%s\" in by clause\n",
+ fname, lineno, left );
+ acl_usage();
+ }
+
if( b->a_dn_at != NULL ) {
fprintf( stderr,
"%s: line %d: dnattr already specified.\n",
if( !is_at_syntax( b->a_dn_at->ad_type,
- SLAPD_DN_SYNTAX ) )
+ SLAPD_DN_SYNTAX ) &&
+ !is_at_syntax( b->a_dn_at->ad_type,
+ SLAPD_NAMEUID_SYNTAX ))
{
fprintf( stderr,
"%s: line %d: dnattr \"%s\": "
char *name = NULL;
char *value = NULL;
+ if ( right == NULL || right[ 0 ] == '\0' ) {
+ fprintf( stderr,
+ "%s: line %d: missing \"=\" in (or value after) \"%s\" in by clause\n",
+ fname, lineno, left );
+ acl_usage();
+ }
+
if( b->a_group_pat != NULL ) {
fprintf( stderr,
"%s: line %d: group pattern already specified.\n",
b->a_group_style = sty;
if (sty == ACL_STYLE_REGEX) {
- regtest(fname, lineno, right);
- b->a_group_pat = ch_strdup( right );
+ char *tmp = acl_regex_normalized_dn( right );
+ regtest(fname, lineno, tmp);
+ b->a_group_pat = tmp;
} else {
b->a_group_pat = ch_strdup( right );
dn_normalize(b->a_group_pat);
fprintf( stderr,
"%s: line %d: group: \"%s\" not allowed by \"%s\"\n",
fname, lineno,
- b->a_group_at->ad_cname->bv_val,
+ b->a_group_at->ad_cname.bv_val,
b->a_group_oc->soc_oid );
acl_usage();
}
}
if ( strcasecmp( left, "peername" ) == 0 ) {
+ if ( right == NULL || right[ 0 ] == '\0' ) {
+ fprintf( stderr,
+ "%s: line %d: missing \"=\" in (or value after) \"%s\" in by clause\n",
+ fname, lineno, left );
+ acl_usage();
+ }
+
if( b->a_peername_pat != NULL ) {
fprintf( stderr,
"%s: line %d: peername pattern already specified.\n",
b->a_peername_style = sty;
if (sty == ACL_STYLE_REGEX) {
- regtest(fname, lineno, right);
+ char *tmp = acl_regex_normalized_dn( right );
+ regtest(fname, lineno, tmp);
+ b->a_peername_pat = tmp;
+ } else {
+ b->a_peername_pat = ch_strdup( right );
}
- b->a_peername_pat = ch_strdup( right );
continue;
}
if ( strcasecmp( left, "sockname" ) == 0 ) {
+ if ( right == NULL || right[ 0 ] == '\0' ) {
+ fprintf( stderr,
+ "%s: line %d: missing \"=\" in (or value after) \"%s\" in by clause\n",
+ fname, lineno, left );
+ acl_usage();
+ }
+
if( b->a_sockname_pat != NULL ) {
fprintf( stderr,
"%s: line %d: sockname pattern already specified.\n",
b->a_sockname_style = sty;
if (sty == ACL_STYLE_REGEX) {
- regtest(fname, lineno, right);
+ char *tmp = acl_regex_normalized_dn( right );
+ regtest(fname, lineno, tmp);
+ b->a_sockname_pat = tmp;
+ } else {
+ b->a_sockname_pat = ch_strdup( right );
}
- b->a_sockname_pat = ch_strdup( right );
continue;
}
if ( strcasecmp( left, "domain" ) == 0 ) {
+ if ( right == NULL || right[ 0 ] == '\0' ) {
+ fprintf( stderr,
+ "%s: line %d: missing \"=\" in (or value after) \"%s\" in by clause\n",
+ fname, lineno, left );
+ acl_usage();
+ }
+
if( b->a_domain_pat != NULL ) {
fprintf( stderr,
"%s: line %d: domain pattern already specified.\n",
b->a_domain_style = sty;
if (sty == ACL_STYLE_REGEX) {
- regtest(fname, lineno, right);
+ char *tmp = acl_regex_normalized_dn( right );
+ regtest(fname, lineno, tmp);
+ b->a_domain_pat = tmp;
+ } else {
+ b->a_domain_pat = ch_strdup( right );
}
- b->a_domain_pat = ch_strdup( right );
continue;
}
if ( strcasecmp( left, "sockurl" ) == 0 ) {
+ if ( right == NULL || right[ 0 ] == '\0' ) {
+ fprintf( stderr,
+ "%s: line %d: missing \"=\" in (or value after) \"%s\" in by clause\n",
+ fname, lineno, left );
+ acl_usage();
+ }
+
if( b->a_sockurl_pat != NULL ) {
fprintf( stderr,
"%s: line %d: sockurl pattern already specified.\n",
b->a_sockurl_style = sty;
if (sty == ACL_STYLE_REGEX) {
- regtest(fname, lineno, right);
+ char *tmp = acl_regex_normalized_dn( right );
+ regtest(fname, lineno, tmp);
+ b->a_sockurl_pat = tmp;
+ } else {
+ b->a_sockurl_pat = ch_strdup( right );
}
- b->a_sockurl_pat = ch_strdup( right );
continue;
}
{
fprintf( stderr, "\n"
"<access clause> ::= access to <what> "
- "[ by <who> <access> <control> ]+ \n"
- "<what> ::= * | [dn=<regex>] [filter=<ldapfilter>] [attrs=<attrlist>]\n"
+ "[ by <who> <access> [ <control> ] ]+ \n"
+ "<what> ::= * | [dn[.<dnstyle>]=<regex>] [filter=<ldapfilter>] [attrs=<attrlist>]\n"
"<attrlist> ::= <attr> | <attr> , <attrlist>\n"
"<attr> ::= <attrname> | entry | children\n"
- "<who> ::= [ * | anonymous | users | self | dn=<regex> ]\n"
+ "<who> ::= [ * | anonymous | users | self | dn[.<dnstyle>]=<regex> ]\n"
"\t[dnattr=<attrname>]\n"
- "\t[group[/<objectclass>[/<attrname>]]=<regex>]\n"
- "\t[peername=<regex>] [sockname=<regex>]\n"
- "\t[domain=<regex>] [sockurl=<regex>]\n"
+ "\t[group[/<objectclass>[/<attrname>]][.<style>]=<regex>]\n"
+ "\t[peername[.<style>]=<regex>] [sockname[.<style>]=<regex>]\n"
+ "\t[domain[.<style>]=<regex>] [sockurl[.<style>]=<regex>]\n"
#ifdef SLAPD_ACI_ENABLED
"\t[aci=<attrname>]\n"
#endif
"\t[ssf=<n>] [transport_ssf=<n>] [tls_ssf=<n>] [sasl_ssf=<n>]\n"
+ "<dnstyle> ::= regex | base | exact (alias of base) | one | sub | children\n"
+ "<style> ::= regex | base | exact (alias of base)\n"
+ "<groupflags> ::= R\n"
"<access> ::= [self]{<level>|<priv>}\n"
"<level> ::= none | auth | compare | search | read | write\n"
"<priv> ::= {=|+|-}{w|r|s|c|x}+\n"
exit( EXIT_FAILURE );
}
+/*
+ * At present it simply eats the (optional) space after
+ * a RDN separator (,)
+ * Eventually will evolve in a more complete normalization
+ */
+static char *
+acl_regex_normalized_dn(
+ const char *pattern
+)
+{
+ char *str, *p;
+
+ str = ch_strdup( pattern );
+
+ if ( str == NULL ) {
+ return( NULL );
+ }
+
+ for ( p = str; p[ 0 ]; p++ ) {
+ /* escape */
+ if ( p[ 0 ] == '\\' ) {
+ p++;
+ }
+
+ if ( p[ 0 ] == ',' ) {
+ if ( p[ 1 ] == ' ' ) {
+ char *q;
+
+ for ( q = &p[ 2 ]; q[ 0 ] == ' '; q++ ) {
+ /* DO NOTHING */ ;
+ }
+ AC_MEMCPY( &p[ 1 ], &q[ 0 ], strlen( q ) + 1 );
+ }
+ }
+ }
+
+ return( str );
+}
+
static void
split(
char *line,
}
if ( b->a_dn_at != NULL ) {
- fprintf( stderr, " dnattr=%s", b->a_dn_at->ad_cname->bv_val );
+ fprintf( stderr, " dnattr=%s", b->a_dn_at->ad_cname.bv_val );
}
if ( b->a_group_pat != NULL ) {
b->a_group_oc->soc_oclass.oc_oid );
if ( b->a_group_at ) {
- fprintf( stderr, " attributeType: %s", b->a_group_at->ad_cname->bv_val );
+ fprintf( stderr, " attributeType: %s", b->a_group_at->ad_cname.bv_val );
}
}
}
#ifdef SLAPD_ACI_ENABLED
if ( b->a_aci_at != NULL ) {
- fprintf( stderr, " aci=%s", b->a_aci_at->ad_cname->bv_val );
+ fprintf( stderr, " aci=%s", b->a_aci_at->ad_cname.bv_val );
}
#endif