#include <ac/string.h>
#include "slap.h"
+#include "sets.h"
static AccessControl * acl_get(
AccessControl *ac, int *count,
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
}
}
+ 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;
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,
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);
--- /dev/null
+/* $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);
+}