/* aclparse.c - routines to parse and check acl's */
/* $OpenLDAP$ */
/*
- * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
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);
+static void acl_regex_normalized_dn(struct berval *pattern);
#ifdef LDAP_DEBUG
static void print_acl(Backend *be, AccessControl *a);
{
int i;
char *left, *right, *style;
+ struct berval bv;
AccessControl *a;
Access *b;
int rc;
a->acl_dn_pat.bv_len = 1;
} else {
- a->acl_dn_pat.bv_val = acl_regex_normalized_dn( right );
- a->acl_dn_pat.bv_len = strlen( a->acl_dn_pat.bv_val );
+ a->acl_dn_pat.bv_val = right;
+ acl_regex_normalized_dn( &a->acl_dn_pat );
}
} else if ( strcasecmp( style, "base" ) == 0 ) {
a->acl_dn_style = ACL_STYLE_BASE;
- a->acl_dn_pat.bv_val = ch_strdup( right );
- a->acl_dn_pat.bv_len = strlen( right );
-
+ ber_str2bv( right, 0, 1, &a->acl_dn_pat );
} else if ( strcasecmp( style, "one" ) == 0 ) {
a->acl_dn_style = ACL_STYLE_ONE;
- a->acl_dn_pat.bv_val = ch_strdup( right );
- a->acl_dn_pat.bv_len = strlen( right );
-
+ ber_str2bv( right, 0, 1, &a->acl_dn_pat );
} else if ( strcasecmp( style, "subtree" ) == 0 ) {
a->acl_dn_style = ACL_STYLE_SUBTREE;
- a->acl_dn_pat.bv_val = ch_strdup( right );
- a->acl_dn_pat.bv_len = strlen( right );
-
+ ber_str2bv( right, 0, 1, &a->acl_dn_pat );
} else if ( strcasecmp( style, "children" ) == 0 ) {
a->acl_dn_style = ACL_STYLE_CHILDREN;
- a->acl_dn_pat.bv_val = ch_strdup( right );
- a->acl_dn_pat.bv_len = strlen( right );
-
+ ber_str2bv( right, 0, 1, &a->acl_dn_pat );
} else {
fprintf( stderr,
"%s: line %d: unknown dn style \"%s\" in to clause\n",
}
} 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 {
fprintf( stderr,
"%s: line %d: expecting <what> got \"%s\"\n",
if( a->acl_dn_pat.bv_len != 0 ) {
if ( a->acl_dn_style != ACL_STYLE_REGEX )
{
- struct berval *bv;
- dnNormalize( NULL, &a->acl_dn_pat, &bv);
+ struct berval bv;
+ dnNormalize2( NULL, &a->acl_dn_pat, &bv);
free( a->acl_dn_pat.bv_val );
- a->acl_dn_pat = *bv;
- free( bv );
+ a->acl_dn_pat = bv;
} else {
int e = regcomp( &a->acl_dn_re, a->acl_dn_pat.bv_val,
REG_EXTENDED | REG_ICASE );
/* get <who> */
for ( ; i < argc; i++ ) {
- char *pat;
slap_style_t sty = ACL_STYLE_REGEX;
split( argv[i], '=', &left, &right );
}
if ( strcasecmp( argv[i], "*" ) == 0 ) {
- pat = ch_strdup( "*" );
+ bv.bv_val = ch_strdup( "*" );
+ bv.bv_len = 1;
} else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) {
- pat = ch_strdup( "anonymous" );
+ ber_str2bv("anonymous",
+ sizeof("anonymous")-1,
+ 1, &bv);
} else if ( strcasecmp( argv[i], "self" ) == 0 ) {
- pat = ch_strdup( "self" );
+ ber_str2bv("self",
+ sizeof("self")-1,
+ 1, &bv);
} else if ( strcasecmp( argv[i], "users" ) == 0 ) {
- pat = ch_strdup( "users" );
+ ber_str2bv("users",
+ sizeof("users")-1,
+ 1, &bv);
} else if ( strcasecmp( left, "dn" ) == 0 ) {
if ( sty == ACL_STYLE_REGEX ) {
b->a_dn_style = ACL_STYLE_REGEX;
if( right == NULL ) {
/* no '=' */
- pat = ch_strdup( "users" );
-
+ ber_str2bv("users",
+ sizeof("users")-1,
+ 1, &bv);
} else if (*right == '\0' ) {
/* dn="" */
- pat = ch_strdup( "anonymous" );
-
+ ber_str2bv("anonymous",
+ sizeof("anonymous")-1,
+ 1, &bv);
} else if ( strcmp( right, "*" ) == 0 ) {
/* dn=* */
/* any or users? users for now */
- pat = ch_strdup( "users" );
-
+ ber_str2bv("users",
+ sizeof("users")-1,
+ 1, &bv);
} else if ( strcmp( right, ".+" ) == 0
|| strcmp( right, "^.+" ) == 0
|| strcmp( right, ".+$" ) == 0
|| strcmp( right, ".+$$" ) == 0
|| strcmp( right, "^.+$$" ) == 0 )
{
- pat = ch_strdup( "users" );
-
+ ber_str2bv("users",
+ sizeof("users")-1,
+ 1, &bv);
} else if ( strcmp( right, ".*" ) == 0
|| strcmp( right, "^.*" ) == 0
|| strcmp( right, ".*$" ) == 0
|| strcmp( right, ".*$$" ) == 0
|| strcmp( right, "^.*$$" ) == 0 )
{
- pat = ch_strdup( "*" );
+ ber_str2bv("*",
+ sizeof("*")-1,
+ 1, &bv);
} else {
- pat = acl_regex_normalized_dn( right );
- regtest(fname, lineno, pat);
+ bv.bv_val = right;
+ acl_regex_normalized_dn( &bv );
+ regtest(fname, lineno, bv.bv_val);
}
} else if ( right == NULL || *right == '\0' ) {
fprintf( stderr,
acl_usage();
} else {
- pat = ch_strdup( right );
+ ber_str2bv( right, 0, 1, &bv );
}
} else {
- pat = NULL;
+ bv.bv_val = NULL;
}
- if( pat != NULL ) {
+ if( bv.bv_val != NULL ) {
if( b->a_dn_pat.bv_len != 0 ) {
fprintf( stderr,
"%s: line %d: dn pattern already specified.\n",
acl_usage();
}
- b->a_dn_pat.bv_val = pat;
- b->a_dn_pat.bv_len = strlen( pat );
+ if ( sty != ACL_STYLE_REGEX ) {
+ dnNormalize2(NULL, &bv, &b->a_dn_pat);
+ free(bv.bv_val);
+ } else {
+ b->a_dn_pat = bv;
+ }
b->a_dn_style = sty;
- if ( sty != ACL_STYLE_REGEX )
- dn_normalize(pat);
continue;
}
acl_usage();
}
- if( b->a_group_pat != NULL ) {
+ if( b->a_group_pat.bv_len ) {
fprintf( stderr,
"%s: line %d: group pattern already specified.\n",
fname, lineno );
b->a_group_style = sty;
if (sty == ACL_STYLE_REGEX) {
- char *tmp = acl_regex_normalized_dn( right );
- regtest(fname, lineno, tmp);
- b->a_group_pat = tmp;
+ bv.bv_val = right;
+ acl_regex_normalized_dn( &bv );
+ regtest(fname, lineno, bv.bv_val);
+ b->a_group_pat = bv;
} else {
- b->a_group_pat = ch_strdup( right );
- dn_normalize(b->a_group_pat);
+ ber_str2bv( right, 0, 0, &bv );
+ dnNormalize2( NULL, &bv, &b->a_group_pat );
}
if (value && *value) {
{
int rc;
- struct berval val;
- struct berval *vals[2];
+ struct berval vals[2];
- val.bv_val = b->a_group_oc->soc_oid;
- val.bv_len = strlen(val.bv_val);
- vals[0] = &val;
- vals[1] = NULL;
+ vals[0].bv_val = b->a_group_oc->soc_oid;
+ vals[0].bv_len = strlen(vals[0].bv_val);
+ vals[1].bv_val = NULL;
rc = oc_check_allowed( b->a_group_at->ad_type, vals, NULL );
b->a_peername_style = sty;
if (sty == ACL_STYLE_REGEX) {
- char *tmp = acl_regex_normalized_dn( right );
- regtest(fname, lineno, tmp);
- b->a_peername_pat = tmp;
+ bv.bv_val = right;
+ acl_regex_normalized_dn( &bv );
+ regtest(fname, lineno, bv.bv_val);
+ b->a_peername_pat = bv.bv_val;
} else {
b->a_peername_pat = ch_strdup( right );
}
b->a_sockname_style = sty;
if (sty == ACL_STYLE_REGEX) {
- char *tmp = acl_regex_normalized_dn( right );
- regtest(fname, lineno, tmp);
- b->a_sockname_pat = tmp;
+ bv.bv_val = right;
+ acl_regex_normalized_dn( &bv );
+ regtest(fname, lineno, bv.bv_val);
+ b->a_sockname_pat = bv.bv_val;
} else {
b->a_sockname_pat = ch_strdup( right );
}
b->a_domain_style = sty;
if (sty == ACL_STYLE_REGEX) {
- char *tmp = acl_regex_normalized_dn( right );
- regtest(fname, lineno, tmp);
- b->a_domain_pat = tmp;
+ bv.bv_val = right;
+ acl_regex_normalized_dn( &bv );
+ regtest(fname, lineno, bv.bv_val);
+ b->a_domain_pat = bv.bv_val;
} else {
b->a_domain_pat = ch_strdup( right );
}
b->a_sockurl_style = sty;
if (sty == ACL_STYLE_REGEX) {
- char *tmp = acl_regex_normalized_dn( right );
- regtest(fname, lineno, tmp);
- b->a_sockurl_pat = tmp;
+ bv.bv_val = right;
+ acl_regex_normalized_dn( &bv );
+ regtest(fname, lineno, bv.bv_val);
+ b->a_sockurl_pat = bv.bv_val;
} else {
b->a_sockurl_pat = ch_strdup( right );
}
}
b->a_set_style = sty;
- b->a_set_pat.bv_val = ch_strdup(right);
- b->a_set_pat.bv_len = strlen(right);
+ ber_str2bv( right, 0, 1, &b->a_set_pat );
continue;
}
accessmask2str( slap_mask_t mask, char *buf )
{
int none=1;
+ char *ptr = buf;
assert( buf != NULL );
if ( ACL_IS_LEVEL( mask ) ) {
if ( ACL_LVL_IS_NONE(mask) ) {
- strcat( buf, "none" );
+ ptr = slap_strcopy( ptr, "none" );
} else if ( ACL_LVL_IS_AUTH(mask) ) {
- strcat( buf, "auth" );
+ ptr = slap_strcopy( ptr, "auth" );
} else if ( ACL_LVL_IS_COMPARE(mask) ) {
- strcat( buf, "compare" );
+ ptr = slap_strcopy( ptr, "compare" );
} else if ( ACL_LVL_IS_SEARCH(mask) ) {
- strcat( buf, "search" );
+ ptr = slap_strcopy( ptr, "search" );
} else if ( ACL_LVL_IS_READ(mask) ) {
- strcat( buf, "read" );
+ ptr = slap_strcopy( ptr, "read" );
} else if ( ACL_LVL_IS_WRITE(mask) ) {
- strcat( buf, "write" );
+ ptr = slap_strcopy( ptr, "write" );
} else {
- strcat( buf, "unknown" );
+ ptr = slap_strcopy( ptr, "unknown" );
}
- strcat(buf, " (");
+ *ptr++ = '(';
}
if( ACL_IS_ADDITIVE( mask ) ) {
- strcat( buf, "+" );
+ *ptr++ = '+';
} else if( ACL_IS_SUBTRACTIVE( mask ) ) {
- strcat( buf, "-" );
+ *ptr++ = '-';
} else {
- strcat( buf, "=" );
+ *ptr++ = '=';
}
if ( ACL_PRIV_ISSET(mask, ACL_PRIV_WRITE) ) {
none = 0;
- strcat( buf, "w" );
+ *ptr++ = 'w';
}
if ( ACL_PRIV_ISSET(mask, ACL_PRIV_READ) ) {
none = 0;
- strcat( buf, "r" );
+ *ptr++ = 'r';
}
if ( ACL_PRIV_ISSET(mask, ACL_PRIV_SEARCH) ) {
none = 0;
- strcat( buf, "s" );
+ *ptr++ = 's';
}
if ( ACL_PRIV_ISSET(mask, ACL_PRIV_COMPARE) ) {
none = 0;
- strcat( buf, "c" );
+ *ptr++ = 'c';
}
if ( ACL_PRIV_ISSET(mask, ACL_PRIV_AUTH) ) {
none = 0;
- strcat( buf, "x" );
+ *ptr++ = 'x';
}
if ( none && ACL_PRIV_ISSET(mask, ACL_PRIV_NONE) ) {
none = 0;
- strcat( buf, "n" );
+ *ptr++ = 'n';
}
if ( none ) {
- strcat( buf, "0" );
+ *ptr++ = '0';
}
if ( ACL_IS_LEVEL( mask ) ) {
- strcat(buf, ")");
- }
+ *ptr++ = ')';
+ }
+
+ *ptr = '\0';
+
return buf;
}
* At present it simply eats the (optional) space after
* a RDN separator (,)
* Eventually will evolve in a more complete normalization
+ *
+ * Note that the input berval only needs bv_val, it ignores
+ * the input bv_len and sets it on return.
*/
-static char *
+static void
acl_regex_normalized_dn(
- const char *pattern
+ struct berval *pattern
)
{
char *str, *p;
- str = ch_strdup( pattern );
-
- if ( str == NULL ) {
- return( NULL );
- }
+ str = ch_strdup( pattern->bv_val );
- for ( p = str; p[ 0 ]; p++ ) {
+ for ( p = str; p && p[ 0 ]; p++ ) {
/* escape */
if ( p[ 0 ] == '\\' ) {
+ /*
+ * if escaping a hex pair we should
+ * increment p twice; however, in that
+ * case the second hex number does
+ * no harm
+ */
p++;
}
if ( p[ 1 ] == ' ' ) {
char *q;
+ /*
+ * too much space should be
+ * an error if we are pedantic
+ */
for ( q = &p[ 2 ]; q[ 0 ] == ' '; q++ ) {
/* DO NOTHING */ ;
}
- AC_MEMCPY( &p[ 1 ], &q[ 0 ], strlen( q ) + 1 );
+ AC_MEMCPY( p+1, q, pattern->bv_len-(q-str)+1);
}
}
}
+ pattern->bv_val = str;
+ pattern->bv_len = p-str;
- return( str );
+ return;
}
static void
free ( a->a_sockurl_pat );
if ( a->a_set_pat.bv_len )
free ( a->a_set_pat.bv_val );
- if ( a->a_group_pat )
- free ( a->a_group_pat );
+ if ( a->a_group_pat.bv_len )
+ free ( a->a_group_pat.bv_val );
free( a );
}
acl_free( AccessControl *a )
{
Access *n;
+ AttributeName *an;
if ( a->acl_filter )
filter_free( a->acl_filter );
if ( a->acl_dn_pat.bv_len )
free ( a->acl_dn_pat.bv_val );
- if ( a->acl_attrs )
- charray_free( a->acl_attrs );
+ if ( a->acl_attrs ) {
+ for ( an = a->acl_attrs; an->an_name.bv_val; an++ ) {
+ free( an->an_name.bv_val );
+ }
+ free( a->acl_attrs );
+ }
for (; a->acl_access; a->acl_access = n) {
n = a->acl_access->a_next;
access_free( a->acl_access );
fprintf( stderr, " dnattr=%s", b->a_dn_at->ad_cname.bv_val );
}
- if ( b->a_group_pat != NULL ) {
- fprintf( stderr, " group=%s", b->a_group_pat );
+ if ( b->a_group_pat.bv_len ) {
+ fprintf( stderr, " group=%s", b->a_group_pat.bv_val );
if ( b->a_group_oc ) {
fprintf( stderr, " objectClass: %s",
}
if ( a->acl_attrs != NULL ) {
- int i, first = 1;
+ int first = 1;
+ AttributeName *an;
to++;
fprintf( stderr, " attrs=" );
- for ( i = 0; a->acl_attrs[i] != NULL; i++ ) {
+ for ( an = a->acl_attrs; an && an->an_name.bv_val; an++ ) {
if ( ! first ) {
fprintf( stderr, "," );
}
- fprintf( stderr, a->acl_attrs[i] );
+ fputs( an->an_name.bv_val, stderr );
first = 0;
}
fprintf( stderr, "\n" );