Commit 3705a26f authored by Mark Valence's avatar Mark Valence
Browse files

Add support for Set ACLs and ACIs. Still need to make this syntax awa

re.
parent 60780084
......@@ -17,7 +17,7 @@ SRCS = main.c daemon.c connection.c search.c filter.c add.c charray.c \
repl.c lock.c controls.c extended.c kerberos.c passwd.c \
schema.c schema_check.c schema_init.c schema_prep.c \
schemaparse.c ad.c at.c mr.c syntax.c oc.c \
monitor.c configinfo.c starttls.c index.c \
monitor.c configinfo.c starttls.c index.c sets.c\
root_dse.c sasl.c module.c suffixalias.c $(@PLAT@_SRCS)
OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \
......@@ -28,7 +28,7 @@ OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \
repl.o lock.o controls.o extended.o kerberos.o passwd.o \
schema.o schema_check.o schema_init.o schema_prep.o \
schemaparse.o ad.o at.o mr.o syntax.o oc.o \
monitor.o configinfo.o starttls.o index.o \
monitor.o configinfo.o starttls.o index.o sets.o\
root_dse.o sasl.o module.o suffixalias.o $(@PLAT@_OBJS)
LDAP_INCDIR= ../../include
......
......@@ -14,6 +14,7 @@
#include <ac/string.h>
#include "slap.h"
#include "sets.h"
static AccessControl * acl_get(
AccessControl *ac, int *count,
......@@ -50,6 +51,9 @@ static void string_expand(
char *newbuf, int bufsiz, char *pattern,
char *match, regmatch_t *matches);
char **aci_set_gather (void *cookie, char *name, char *attr);
static int aci_match_set ( struct berval *subj, Backend *be,
Entry *e, Connection *conn, Operation *op, int setref );
/*
* access_allowed - check whether op->o_ndn is allowed the requested access
......@@ -620,6 +624,16 @@ acl_mask(
}
}
if ( b->a_set_pat != NULL ) {
struct berval bv;
bv.bv_val = b->a_set_pat;
bv.bv_len = strlen(b->a_set_pat);
if (aci_match_set( &bv, be, e, conn, op, 0 ) == 0) {
continue;
}
}
#ifdef SLAPD_ACI_ENABLED
if ( b->a_aci_at != NULL ) {
Attribute *at;
......@@ -1149,6 +1163,125 @@ done:
return(rc);
}
char **
aci_set_gather (void *cookie, char *name, char *attr)
{
struct {
Backend *be;
Entry *e;
Connection *conn;
Operation *op;
} *cp = (void *)cookie;
struct berval **bvals = NULL;
char **vals = NULL;
char *ndn;
int i;
/* this routine needs to return the bervals instead of
* plain strings, since syntax is not known. It should
* also return the syntax or some "comparison cookie".
*/
if ((ndn = ch_strdup(name)) != NULL) {
if (dn_normalize(ndn) != NULL) {
char *text;
AttributeDescription *desc = NULL;
if (slap_str2ad(attr, &desc, &text) == 0) {
backend_attribute(cp->be, NULL /*cp->conn*/,
NULL /*cp->op*/, cp->e,
ndn, desc, &bvals);
if (bvals != NULL) {
for (i = 0; bvals[i] != NULL; i++) { }
vals = ch_calloc(i + 1, sizeof(char *));
if (vals != NULL) {
while (--i >= 0) {
vals[i] = bvals[i]->bv_val;
bvals[i]->bv_val = NULL;
}
}
ber_bvecfree(bvals);
}
ad_free(desc, 1);
}
}
ch_free(ndn);
}
return(vals);
}
static int
aci_match_set (
struct berval *subj,
Backend *be,
Entry *e,
Connection *conn,
Operation *op,
int setref
)
{
char *set = NULL;
int rc = 0;
struct {
Backend *be;
Entry *e;
Connection *conn;
Operation *op;
} cookie;
if (setref == 0) {
set = aci_bvstrdup(subj);
} else {
struct berval bv;
char *subjdn;
char *setat;
struct berval **bvals;
char *text;
AttributeDescription *desc = NULL;
/* format of string is "entry/setAttrName" */
if (aci_get_part(subj, 0, '/', &bv) < 0) {
return(0);
}
subjdn = aci_bvstrdup(&bv);
if ( subjdn == NULL ) {
return(0);
}
if ( aci_get_part(subj, 1, '/', &bv) < 0 ) {
setat = ch_strdup( SLAPD_ACI_SET_ATTR );
} else {
setat = aci_bvstrdup(&bv);
}
if ( setat != NULL ) {
if ( dn_normalize(subjdn) != NULL
&& slap_str2ad(setat, &desc, &text) == 0 )
{
backend_attribute(be, NULL, NULL, e,
subjdn, desc, &bvals);
ad_free(desc, 1);
if ( bvals != NULL ) {
if ( bvals[0] != NULL )
set = ch_strdup(bvals[0]->bv_val);
ber_bvecfree(bvals);
}
}
ch_free(setat);
}
ch_free(subjdn);
}
if (set != NULL) {
cookie.be = be;
cookie.e = e;
cookie.conn = conn;
cookie.op = op;
rc = (set_filter(aci_set_gather, &cookie, set, op->o_ndn, e->e_ndn, NULL) > 0);
ch_free(set);
}
return(rc);
}
static int
aci_mask(
Backend *be,
......@@ -1263,6 +1396,14 @@ aci_mask(
if (aci_group_member(&sdn, SLAPD_ROLE_CLASS, SLAPD_ROLE_ATTR, be, e, op, matches))
return(1);
} else if (aci_strbvcmp( "set", &bv ) == 0) {
if (aci_match_set(&sdn, be, e, conn, op, 0))
return(1);
} else if (aci_strbvcmp( "set-ref", &bv ) == 0) {
if (aci_match_set(&sdn, be, e, conn, op, 1))
return(1);
}
return(0);
......
/* $OpenLDAP$ */
/*
* Copyright 2000 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
#include "portable.h"
#include <ac/string.h>
#include "sets.h"
static char **set_join (char **lset, int op, char **rset);
static char **set_chase (SET_GATHER gatherer, void *cookie, char **set, char *attr, int attrlen, int closure);
static int set_samedn (char *dn1, char *dn2);
long
set_size (char **set)
{
int i;
i = 0;
if (set != NULL) {
while (set[i])
i++;
}
return(i);
}
void
set_dispose (char **set)
{
int i;
if (set != NULL) {
for (i = 0; set[i]; i++)
ch_free(set[i]);
ch_free(set);
}
}
static char **
set_join (char **lset, int op, char **rset)
{
char **set;
long i, j, last;
set = NULL;
if (op == '|') {
if (lset == NULL || *lset == NULL) {
if (rset == NULL) {
if (lset == NULL)
return(ch_calloc(1, sizeof(char *)));
return(lset);
}
set_dispose(lset);
return(rset);
}
if (rset == NULL || *rset == NULL) {
set_dispose(rset);
return(lset);
}
i = set_size(lset) + set_size(rset) + 1;
set = ch_calloc(i, sizeof(char *));
if (set != NULL) {
/* set_chase() depends on this routine to
* keep the first elements of the result
* set the same (and in the same order)
* as the left-set.
*/
for (i = 0; lset[i]; i++)
set[i] = lset[i];
ch_free(lset);
for (i = 0; rset[i]; i++) {
for (j = 0; set[j]; j++) {
if (set_samedn(rset[i], set[j])) {
ch_free(rset[i]);
rset[i] = NULL;
break;
}
}
if (rset[i])
set[j] = rset[i];
}
ch_free(rset);
}
return(set);
}
if (op == '&') {
if (lset == NULL || *lset == NULL || rset == NULL || *rset == NULL) {
set = ch_calloc(1, sizeof(char *));
} else {
set = lset;
lset = NULL;
last = set_size(set) - 1;
for (i = 0; set[i]; i++) {
for (j = 0; rset[j]; j++) {
if (set_samedn(set[i], rset[j]))
break;
}
if (rset[j] == NULL) {
ch_free(set[i]);
set[i] = set[last];
set[last] = NULL;
last--;
i--;
}
}
}
}
set_dispose(lset);
set_dispose(rset);
return(set);
}
static char **
set_chase (SET_GATHER gatherer, void *cookie, char **set, char *attr, int attrlen, int closure)
{
char **vals, **nset;
char attrstr[32];
int i;
if (set == NULL)
return(ch_calloc(1, sizeof(char *)));
if (*set == NULL)
return(set);
if (attrlen > (sizeof(attrstr) - 1)) {
set_dispose(set);
return(NULL);
}
memcpy(attrstr, attr, attrlen);
attrstr[attrlen] = 0;
nset = ch_calloc(1, sizeof(char *));
if (nset == NULL) {
set_dispose(set);
return(NULL);
}
for (i = 0; set[i]; i++) {
vals = (gatherer)(cookie, set[i], attrstr);
if (vals != NULL)
nset = set_join(nset, '|', vals);
}
set_dispose(set);
if (closure) {
for (i = 0; nset[i]; i++) {
vals = (gatherer)(cookie, nset[i], attrstr);
if (vals != NULL) {
nset = set_join(nset, '|', vals);
if (nset == NULL)
break;
}
}
}
return(nset);
}
static int
set_samedn (char *dn1, char *dn2)
{
char c1, c2;
while (*dn1 == ' ') dn1++;
while (*dn2 == ' ') dn2++;
while (*dn1 || *dn2) {
if (*dn1 != '=' && *dn1 != ','
&& *dn2 != '=' && *dn2 != ',')
{
c1 = *dn1++;
c2 = *dn2++;
if (c1 >= 'a' && c1 <= 'z')
c1 -= 'a' - 'A';
if (c2 >= 'a' && c2 <= 'z')
c2 -= 'a' - 'A';
if (c1 != c2)
return(0);
} else {
while (*dn1 == ' ') dn1++;
while (*dn2 == ' ') dn2++;
if (*dn1++ != *dn2++)
return(0);
while (*dn1 == ' ') dn1++;
while (*dn2 == ' ') dn2++;
}
}
return(1);
}
int
set_filter (SET_GATHER gatherer, void *cookie, char *filter, char *user, char *this, char ***results)
{
#define IS_SET(x) ( (long)(x) >= 256 )
#define IS_OP(x) ( (long)(x) < 256 )
#define SF_ERROR(x) { rc = -1; goto _error; }
#define SF_TOP() (char **)( (stp < 0) ? 0 : stack[stp] )
#define SF_POP() (char **)( (stp < 0) ? 0 : stack[stp--] )
#define SF_PUSH(x) { if (stp >= 63) SF_ERROR(overflow); stack[++stp] = (char **)(long)(x); }
char c;
char **set, **lset;
int len, op, rc, stp;
char **stack[64];
if (results)
*results = NULL;
stp = -1;
while (c = *filter++) {
set = NULL;
switch (c) {
case ' ':
case '\t':
case '\x0A':
case '\x0D':
break;
case '(':
if (IS_SET(SF_TOP()))
SF_ERROR(syntax);
SF_PUSH(c);
break;
case ')':
set = SF_POP();
if (IS_OP(set))
SF_ERROR(syntax);
if (SF_TOP() == (void *)'(') {
SF_POP();
SF_PUSH(set);
set = NULL;
} else if (IS_OP(SF_TOP())) {
op = (long)SF_POP();
lset = SF_POP();
SF_POP();
set = set_join(lset, op, set);
if (set == NULL)
SF_ERROR(memory);
SF_PUSH(set);
set = NULL;
} else {
SF_ERROR(syntax);
}
break;
case '&':
case '|':
set = SF_POP();
if (IS_OP(set))
SF_ERROR(syntax);
if (SF_TOP() == 0 || SF_TOP() == (void *)'(') {
SF_PUSH(set);
set = NULL;
} else if (IS_OP(SF_TOP())) {
op = (long)SF_POP();
lset = SF_POP();
set = set_join(lset, op, set);
if (set == NULL)
SF_ERROR(memory);
SF_PUSH(set);
set = NULL;
} else {
SF_ERROR(syntax);
}
SF_PUSH(c);
break;
case '[':
if ((SF_TOP() == (void *)'/') || IS_SET(SF_TOP()))
SF_ERROR(syntax);
for ( len = 0;
(c = *filter++) && (c != ']');
len++)
{ }
if (c == 0)
SF_ERROR(syntax);
set = ch_calloc(2, sizeof(char *));
if (set == NULL)
SF_ERROR(memory);
*set = ch_calloc(len + 1, sizeof(char));
if (*set == NULL)
SF_ERROR(memory);
memcpy(*set, &filter[-len - 1], len);
SF_PUSH(set);
set = NULL;
break;
case '-':
c = *filter++;
if (c != '>')
SF_ERROR(syntax);
/* fall through to next case */
case '/':
if (IS_OP(SF_TOP()))
SF_ERROR(syntax);
SF_PUSH('/');
break;
default:
if ((c != '_')
&& (c < 'A' || c > 'Z')
&& (c < 'a' || c > 'z'))
{
SF_ERROR(syntax);
}
filter--;
for ( len = 1;
(c = filter[len])
&& ((c >= '0' && c <= '9')
|| (c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z'));
len++)
{ }
if (len == 4
&& memcmp("this", filter, len) == 0)
{
if ((SF_TOP() == (void *)'/') || IS_SET(SF_TOP()))
SF_ERROR(syntax);
set = ch_calloc(2, sizeof(char *));
if (set == NULL)
SF_ERROR(memory);
*set = ch_strdup(this);
if (*set == NULL)
SF_ERROR(memory);
} else if (len == 4
&& memcmp("user", filter, len) == 0)
{
if ((SF_TOP() == (void *)'/') || IS_SET(SF_TOP()))
SF_ERROR(syntax);
set = ch_calloc(2, sizeof(char *));
if (set == NULL)
SF_ERROR(memory);
*set = ch_strdup(user);
if (*set == NULL)
SF_ERROR(memory);
} else if (SF_TOP() != (void *)'/') {
SF_ERROR(syntax);
} else {
SF_POP();
set = set_chase(gatherer, cookie, SF_POP(), filter, len, c == '*');
if (set == NULL)
SF_ERROR(memory);
if (c == '*')
len++;
}
filter += len;
SF_PUSH(set);
set = NULL;
break;
}
}
set = SF_POP();
if (IS_OP(set))
SF_ERROR(syntax);
if (SF_TOP() == 0) {
} else if (IS_OP(SF_TOP())) {
op = (long)SF_POP();
lset = SF_POP();
set = set_join(lset, op, set);
if (set == NULL)
SF_ERROR(memory);
} else {
SF_ERROR(syntax);
}
rc = set_size(set);
if (results) {
*results = set;
set = NULL;
}
_error:
if (IS_SET(set))
set_dispose(set);
while (set = SF_POP()) {
if (IS_SET(set))
set_dispose(set);
}
return(rc);
}
/* $OpenLDAP$ */
/*
* Copyright 2000 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/* this routine needs to return the bervals instead of
* plain strings, since syntax is not known. It should
* also return the syntax or some "comparison cookie"
* that is used by set_filter.
*/
typedef char **(*SET_GATHER) (void *cookie, char *name, char *attr);
long set_size (char **set);
void set_dispose (char **set);
int set_filter (SET_GATHER gatherer, void *cookie, char *filter, char *user, char *this, char ***results);
......@@ -47,7 +47,7 @@ SLAPD_OBJS = ../config.o ../ch_malloc.o ../backend.o ../charray.o \
../acl.o ../phonetic.o ../attr.o ../value.o ../entry.o \
../dn.o ../filter.o ../str2filter.o ../ava.o ../init.o \
../controls.o ../kerberos.o ../passwd.o ../index.o \
../extended.o ../starttls.o
../extended.o ../starttls.o ../sets.o
SLAPOBJS = $(SLAPD_OBJS) slapcommon.o mimic.o
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment