mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-25 00:59:45 -05:00
Add support for Set ACLs and ACIs. Still need to make this syntax awa
re.
This commit is contained in:
parent
6078008495
commit
3705a26f2d
5 changed files with 549 additions and 3 deletions
|
|
@ -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);
|
||||
|
|
|
|||
387
servers/slapd/sets.c
Normal file
387
servers/slapd/sets.c
Normal file
|
|
@ -0,0 +1,387 @@
|
|||
/* $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);
|
||||
}
|
||||
18
servers/slapd/sets.h
Normal file
18
servers/slapd/sets.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/* $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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue