]> git.sur5r.net Git - openldap/commitdiff
Add support for Set ACLs and ACIs. Still need to make this syntax awa
authorMark Valence <mrv@openldap.org>
Thu, 29 Jun 2000 22:02:15 +0000 (22:02 +0000)
committerMark Valence <mrv@openldap.org>
Thu, 29 Jun 2000 22:02:15 +0000 (22:02 +0000)
re.

servers/slapd/Makefile.in
servers/slapd/acl.c
servers/slapd/sets.c [new file with mode: 0644]
servers/slapd/sets.h [new file with mode: 0644]
servers/slapd/tools/Makefile.in

index c3915e37a07d3ebd79670f1e848fee49068579a9..c27ebbd31524d5c3b713a8ffe0ae68e5fc27d66f 100644 (file)
@@ -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
index ea08d0bddaac229a17430d5cf3325ab29d56c6bd..3efffe79be57038d3cf8b2bb26d0e73bf528c534 100644 (file)
@@ -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);
diff --git a/servers/slapd/sets.c b/servers/slapd/sets.c
new file mode 100644 (file)
index 0000000..6222493
--- /dev/null
@@ -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);
+}
diff --git a/servers/slapd/sets.h b/servers/slapd/sets.h
new file mode 100644 (file)
index 0000000..134707f
--- /dev/null
@@ -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);
+
index 308bf9ed7697953f6ad01c7d2fc24302d3ab56d7..fad33e3883ba94c7d79d9f04a3715ed764895245 100644 (file)
@@ -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