[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
bugs in aclparse.c of slapd server.
Hi Folks,
I attach a version of aclparse.c with two changes. Both changes are in
the group acl section. The removed lines have been tagged with "gerrit
thomson" as part of the comment removing them.
207 /* Gerrit Thomson } else if ( strcasecmp( left,
"group" )
== 0 ) { */
208 } else if ( strncasecmp( "group", left,5 )
== 0
) {
and
215 /* Gerrit Thomson if ((value =
strchr(right, '/')) != NULL) { */
216 if ((value = strchr(left, '/')) !=
NULL) {
Both of these problems were found when tring to use a "by group" acl using
the form
group/objectclass/attribute
to specify a netsacpe style group as
group/groupofuniquenames/uniquemember
Cheers,
Gerrit Thomson.
/* acl.c - routines to parse and check acl's */
#include "portable.h"
#include <stdio.h>
#include <ac/ctype.h>
#include <ac/regex.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/unistd.h>
#include "slap.h"
static void split(char *line, int splitchar, char **left, char **right);
static void acl_append(struct acl **l, struct acl *a);
static void access_append(struct access **l, struct access *a);
static void acl_usage(void);
#ifdef LDAP_DEBUG
static void print_acl(struct acl *a);
static void print_access(struct access *b);
#endif
static int
regtest(char *fname, int lineno, char *pat) {
int e;
regex_t re;
char buf[512];
unsigned size;
char *sp;
char *dp;
int flag;
sp = pat;
dp = buf;
size = 0;
buf[0] = '\0';
for (size = 0, flag = 0; (size < sizeof(buf)) && *sp; sp++) {
if (flag) {
if (*sp == '$'|| (*sp >= '0' && *sp <= '9')) {
*dp++ = *sp;
size++;
}
flag = 0;
} else {
if (*sp == '$') {
flag = 1;
} else {
*dp++ = *sp;
size++;
}
}
}
*dp = '\0';
if ( size >= (sizeof(buf)-1) ) {
fprintf( stderr,
"%s: line %d: regular expression \"%s\" too large\n",
fname, lineno, pat, 0 );
acl_usage();
}
if ((e = regcomp(&re, buf, REG_EXTENDED|REG_ICASE))) {
char error[512];
regerror(e, &re, error, sizeof(error));
fprintf( stderr,
"%s: line %d: regular expression \"%s\" bad because of %s\n",
fname, lineno, pat, error );
acl_usage();
return(0);
}
regfree(&re);
return(1);
}
void
parse_acl(
Backend *be,
char *fname,
int lineno,
int argc,
char **argv
)
{
int i;
char *e, *left, *right;
struct acl *a;
struct access *b;
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",
fname, lineno );
acl_usage();
}
a = (struct acl *) ch_calloc( 1, sizeof(struct acl) );
for ( ++i; i < argc; i++ ) {
if ( strcasecmp( argv[i], "by" ) == 0 ) {
i--;
break;
}
if ( strcasecmp( argv[i], "*" ) == 0 ) {
int e;
if ((e = regcomp( &a->acl_dnre, ".*",
REG_EXTENDED|REG_ICASE)))
{
char buf[512];
regerror(e, &a->acl_dnre, buf, sizeof(buf));
fprintf( stderr,
"%s: line %d: regular expression \"%s\" bad because of %s\n",
fname, lineno, right, buf );
acl_usage();
}
a->acl_dnpat = ch_strdup( ".*" );
continue;
}
split( argv[i], '=', &left, &right );
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 ) {
fprintf( stderr,
"%s: line %d: bad filter \"%s\" in to clause\n",
fname, lineno, right );
acl_usage();
}
} else if ( strcasecmp( left, "dn" ) == 0 ) {
int e;
if ((e = regcomp(&a->acl_dnre, right,
REG_EXTENDED|REG_ICASE))) {
char buf[512];
regerror(e, &a->acl_dnre, buf, sizeof(buf));
fprintf( stderr,
"%s: line %d: regular expression \"%s\" bad because of %s\n",
fname, lineno, right, buf );
acl_usage();
} else {
a->acl_dnpat = dn_upcase(ch_strdup( right ));
}
} else if ( strncasecmp( left, "attr", 4 )
== 0 ) {
char **alist;
alist = str2charray( right, "," );
charray_merge( &a->acl_attrs, alist );
charray_free( alist );
} else {
fprintf( stderr,
"%s: line %d: expecting <what> got \"%s\"\n",
fname, lineno, left );
acl_usage();
}
}
/* by clause - select who has what access to entries */
} else if ( strcasecmp( argv[i], "by" ) == 0 ) {
if ( a == NULL ) {
fprintf( stderr,
"%s: line %d: to clause required before by clause in access line\n",
fname, lineno );
acl_usage();
}
/*
* by clause consists of <who> and <access>
*/
b = (struct access *) ch_calloc( 1,
sizeof(struct access) );
if ( ++i == argc ) {
fprintf( stderr,
"%s: line %d: premature eol: expecting <who>\n",
fname, lineno );
acl_usage();
}
/* get <who> */
split( argv[i], '=', &left, &right );
if ( strcasecmp( argv[i], "*" ) == 0 ) {
b->a_dnpat = ch_strdup( ".*" );
} else if ( strcasecmp( argv[i], "self" ) == 0 ) {
b->a_dnpat = ch_strdup( "self" );
} else if ( strcasecmp( left, "dn" ) == 0 ) {
regtest(fname, lineno, right);
b->a_dnpat = dn_upcase( ch_strdup( right ) );
} else if ( strcasecmp( left, "dnattr" ) == 0 ) {
b->a_dnattr = ch_strdup( right );
#ifdef SLAPD_ACLGROUPS
/* Gerrit Thomson } else if ( strcasecmp( left, "group" ) == 0 ) { */
} else if ( strncasecmp( "group", left,5 ) == 0 ) {
char *name = NULL;
char *value = NULL;
regtest(fname, lineno, right);
/* format of string is "group/objectClassValue/groupAttrName"
*/
/* Gerrit Thomson if ((value = strchr(right, '/')) != NULL) { */
if ((value = strchr(left, '/')) != NULL) {
*value++ = '\0';
if (value && *value && (name = strchr(value, '/')) != NULL)
*name++ = '\0';
}
b->a_group = dn_upcase(ch_strdup( right ));
if (value && *value) {
b->a_objectclassvalue = ch_strdup(value);
*--value = '/';
}
else
b->a_objectclassvalue = ch_strdup("groupOfNames");
if (name && *name) {
b->a_groupattrname = ch_strdup(name);
*--name = '/';
}
else
b->a_groupattrname = ch_strdup("member");
#endif /* SLAPD_ACLGROUPS */
} else if ( strcasecmp( left, "domain" ) == 0 ) {
char *s;
regtest(fname, lineno, right);
b->a_domainpat = ch_strdup( right );
/* normalize the domain */
for ( s = b->a_domainpat; *s; s++ ) {
*s = TOLOWER( *s );
}
} else if ( strcasecmp( left, "addr" ) == 0 ) {
regtest(fname, lineno, right);
b->a_addrpat = ch_strdup( right );
} else {
fprintf( stderr,
"%s: line %d: expecting <who> got \"%s\"\n",
fname, lineno, left );
acl_usage();
}
if ( ++i == argc ) {
fprintf( stderr,
"%s: line %d: premature eol: expecting <access>\n",
fname, lineno );
acl_usage();
}
/* get <access> */
split( argv[i], '=', &left, &right );
if ( (b->a_access = str2access( left )) == -1 ) {
fprintf( stderr,
"%s: line %d: expecting <access> got \"%s\"\n",
fname, lineno, left );
acl_usage();
}
access_append( &a->acl_access, b );
} else {
fprintf( stderr,
"%s: line %d: expecting \"to\" or \"by\" got \"%s\"\n",
fname, lineno, argv[i] );
acl_usage();
}
}
/* if we have no real access clause, complain and do nothing */
if ( a == NULL ) {
fprintf( stderr,
"%s: line %d: warning: no access clause(s) specified in access line\n",
fname, lineno );
} else {
#ifdef LDAP_DEBUG
if (ldap_debug & LDAP_DEBUG_ACL)
print_acl(a);
#endif
if ( a->acl_access == NULL ) {
fprintf( stderr,
"%s: line %d: warning: no by clause(s) specified in access line\n",
fname, lineno );
}
if ( be != NULL ) {
acl_append( &be->be_acl, a );
} else {
acl_append( &global_acl, a );
}
}
}
char *
access2str( int access )
{
static char buf[12];
if ( access & ACL_SELF ) {
strcpy( buf, "self" );
} else {
buf[0] = '\0';
}
if ( access & ACL_NONE ) {
strcat( buf, "none" );
} else if ( access & ACL_COMPARE ) {
strcat( buf, "compare" );
} else if ( access & ACL_SEARCH ) {
strcat( buf, "search" );
} else if ( access & ACL_READ ) {
strcat( buf, "read" );
} else if ( access & ACL_WRITE ) {
strcat( buf, "write" );
} else {
strcat( buf, "unknown" );
}
return( buf );
}
int
str2access( char *str )
{
int access;
access = 0;
if ( strncasecmp( str, "self", 4 ) == 0 ) {
access |= ACL_SELF;
str += 4;
}
if ( strcasecmp( str, "none" ) == 0 ) {
access |= ACL_NONE;
} else if ( strcasecmp( str, "compare" ) == 0 ) {
access |= ACL_COMPARE;
} else if ( strcasecmp( str, "search" ) == 0 ) {
access |= ACL_SEARCH;
} else if ( strcasecmp( str, "read" ) == 0 ) {
access |= ACL_READ;
} else if ( strcasecmp( str, "write" ) == 0 ) {
access |= ACL_WRITE;
} else {
access = -1;
}
return( access );
}
static void
acl_usage( void )
{
fprintf( stderr, "\n<access clause> ::= access to <what> [ by <who> <access> ]+ \n" );
fprintf( stderr, "<what> ::= * | [dn=<regex>] [filter=<ldapfilter>] [attrs=<attrlist>]\n" );
fprintf( stderr, "<attrlist> ::= <attr> | <attr> , <attrlist>\n" );
fprintf( stderr, "<attr> ::= <attrname> | entry | children\n" );
fprintf( stderr, "<who> ::= * | self | dn=<regex> | addr=<regex> |\n\tdomain=<regex> | dnattr=<dnattrname>\n" );
fprintf( stderr, "<access> ::= [self]{none | compare | search | read | write }\n" );
exit( 1 );
}
static void
split(
char *line,
int splitchar,
char **left,
char **right
)
{
*left = line;
if ( (*right = strchr( line, splitchar )) != NULL ) {
*((*right)++) = '\0';
}
}
static void
access_append( struct access **l, struct access *a )
{
for ( ; *l != NULL; l = &(*l)->a_next )
; /* NULL */
*l = a;
}
static void
acl_append( struct acl **l, struct acl *a )
{
for ( ; *l != NULL; l = &(*l)->acl_next )
; /* NULL */
*l = a;
}
#ifdef LDAP_DEBUG
static void
print_access( struct access *b )
{
fprintf( stderr, "\tby" );
if ( b->a_dnpat != NULL ) {
fprintf( stderr, " dn=%s", b->a_dnpat );
} else if ( b->a_addrpat != NULL ) {
fprintf( stderr, " addr=%s", b->a_addrpat );
} else if ( b->a_domainpat != NULL ) {
fprintf( stderr, " domain=%s", b->a_domainpat );
} else if ( b->a_dnattr != NULL ) {
fprintf( stderr, " dnattr=%s", b->a_dnattr );
}
#ifdef SLAPD_ACLGROUPS
else if ( b->a_group != NULL ) {
fprintf( stderr, " group: %s", b->a_group );
if ( b->a_objectclassvalue )
fprintf( stderr, " objectClassValue: %s", b->a_objectclassvalue );
if ( b->a_groupattrname )
fprintf( stderr, " groupAttrName: %s", b->a_groupattrname );
}
#endif
fprintf( stderr, "\n" );
}
static void
print_acl( struct acl *a )
{
int i;
struct access *b;
if ( a == NULL ) {
fprintf( stderr, "NULL\n" );
}
fprintf( stderr, "ACL: access to" );
if ( a->acl_filter != NULL ) {
fprintf( stderr," filter=" );
filter_print( a->acl_filter );
}
if ( a->acl_dnpat != NULL ) {
fprintf( stderr, " dn=" );
fprintf( stderr, a->acl_dnpat );
}
if ( a->acl_attrs != NULL ) {
int first = 1;
fprintf( stderr, "\n attrs=" );
for ( i = 0; a->acl_attrs[i] != NULL; i++ ) {
if ( ! first ) {
fprintf( stderr, "," );
}
fprintf( stderr, a->acl_attrs[i] );
first = 0;
}
}
fprintf( stderr, "\n" );
for ( b = a->acl_access; b != NULL; b = b->a_next ) {
print_access( b );
}
fprintf( stderr, "\n" );
}
#endif /* LDAP_DEBUG */