]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/aci.c
use slab memory for proxyauthz
[openldap] / servers / slapd / aci.c
index 7f23b4363b3cc89f2d71d9636b5ae244efe0cef7..28b99388ea2381f791e423411a116c095f774b8f 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2005 The OpenLDAP Foundation.
+ * Copyright 1998-2006 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include "lber_pvt.h"
 #include "lutil.h"
 
-#define ACI_BUF_SIZE   1024    /* use most appropriate size */
+/* use most appropriate size */
+#define ACI_BUF_SIZE                   1024
 
-#ifdef SLAP_DYNACL
-static
-#endif /* SLAP_DYNACL */
-AttributeDescription *slap_ad_aci;
+/* move to "stable" when no longer experimental */
+#define SLAPD_ACI_SYNTAX               "1.3.6.1.4.1.4203.666.2.1"
+
+/* change this to "OpenLDAPset" */
+#define SLAPD_ACI_SET_ATTR             "template"
+
+typedef enum slap_aci_scope_t {
+       SLAP_ACI_SCOPE_ENTRY            = 0x1,
+       SLAP_ACI_SCOPE_CHILDREN         = 0x2,
+       SLAP_ACI_SCOPE_SUBTREE          = ( SLAP_ACI_SCOPE_ENTRY | SLAP_ACI_SCOPE_CHILDREN )
+} slap_aci_scope_t;
+
+enum {
+       ACI_BV_ENTRY,
+       ACI_BV_CHILDREN,
+       ACI_BV_ONELEVEL,
+       ACI_BV_SUBTREE,
+
+       ACI_BV_BR_ENTRY,
+       ACI_BV_BR_ALL,
+
+       ACI_BV_ACCESS_ID,
+       ACI_BV_PUBLIC,
+       ACI_BV_USERS,
+       ACI_BV_SELF,
+       ACI_BV_DNATTR,
+       ACI_BV_GROUP,
+       ACI_BV_ROLE,
+       ACI_BV_SET,
+       ACI_BV_SET_REF,
+
+       ACI_BV_GRANT,
+       ACI_BV_DENY,
+
+       ACI_BV_GROUP_CLASS,
+       ACI_BV_GROUP_ATTR,
+       ACI_BV_ROLE_CLASS,
+       ACI_BV_ROLE_ATTR,
+
+       ACI_BV_SET_ATTR,
+
+       ACI_BV_LAST
+};
+
+static const struct berval     aci_bv[] = {
+       /* scope */
+       BER_BVC("entry"),
+       BER_BVC("children"),
+       BER_BVC("onelevel"),
+       BER_BVC("subtree"),
+
+       /* */
+       BER_BVC("[entry]"),
+       BER_BVC("[all]"),
+
+       /* type */
+       BER_BVC("access-id"),
+       BER_BVC("public"),
+       BER_BVC("users"),
+       BER_BVC("self"),
+       BER_BVC("dnattr"),
+       BER_BVC("group"),
+       BER_BVC("role"),
+       BER_BVC("set"),
+       BER_BVC("set-ref"),
+
+       /* actions */
+       BER_BVC("grant"),
+       BER_BVC("deny"),
+
+       /* schema */
+       BER_BVC(SLAPD_GROUP_CLASS),
+       BER_BVC(SLAPD_GROUP_ATTR),
+       BER_BVC(SLAPD_ROLE_CLASS),
+       BER_BVC(SLAPD_ROLE_ATTR),
+
+       BER_BVC(SLAPD_ACI_SET_ATTR),
+
+       BER_BVNULL
+};
+
+static AttributeDescription    *slap_ad_aci;
 
 static int
 OpenLDAPaciValidate(
@@ -321,7 +400,7 @@ done:
        return rc;
 }
 
-int
+static int
 aci_mask(
        Operation               *op,
        Entry                   *e,
@@ -554,12 +633,12 @@ aci_mask(
                }
 
        } else if ( ber_bvcmp( &aci_bv[ ACI_BV_SET ], &type ) == 0 ) {
-               if ( acl_match_set( &sdn, op, e, 0 ) ) {
+               if ( acl_match_set( &sdn, op, e, NULL ) ) {
                        return 1;
                }
 
        } else if ( ber_bvcmp( &aci_bv[ ACI_BV_SET_REF ], &type ) == 0 ) {
-               if ( acl_match_set( &sdn, op, e, 1 ) ) {
+               if ( acl_match_set( &sdn, op, e, (struct berval *)&aci_bv[ ACI_BV_SET_ATTR ] ) ) {
                        return 1;
                }
 
@@ -571,10 +650,10 @@ aci_mask(
        return 0;
 }
 
-int
+static int
 aci_init( void )
 {
-       /* OpenLDAP Experimental Syntax */
+       /* OpenLDAP eXperimental Syntax */
        static slap_syntax_defs_rec aci_syntax_def = {
                "( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
                        SLAP_SYNTAX_HIDE,
@@ -627,7 +706,7 @@ aci_init( void )
                &rc, &text, LDAP_SCHEMA_ALLOW_ALL );
        if ( !at ) {
                Debug( LDAP_DEBUG_ANY,
-                       "%s AttributeType load failed: %s %s\n",
+                       "aci_init: AttributeType \"%s\" parse failed: %s %s\n",
                        aci_at.name, ldap_scherr2str( rc ), text );
                return rc;
        }
@@ -635,9 +714,9 @@ aci_init( void )
        rc = at_add( at, 0, &sat, &text );
        if ( rc != LDAP_SUCCESS ) {
                ldap_attributetype_free( at );
-               fprintf( stderr, "iMUX_monitor_schema_init: "
-                       "AttributeType load failed: %s %s\n",
-                       scherr2str( rc ), text );
+               Debug( LDAP_DEBUG_ANY,
+                       "aci_init: AttributeType \"%s\" load failed: %s %s\n",
+                       aci_at.name, scherr2str( rc ), text );
                return rc;
        }
        ldap_memfree( at );
@@ -646,7 +725,7 @@ aci_init( void )
                        aci_at.ad, &text );
        if ( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY,
-                       "unable to find AttributeDescription "
+                       "aci_init: unable to find AttributeDescription "
                        "\"%s\": %d (%s)\n",
                        aci_at.name, rc, text );
                return 1;
@@ -658,12 +737,6 @@ aci_init( void )
        return rc;
 }
 
-#ifdef SLAP_DYNACL
-/*
- * FIXME: there is a silly dependence that makes it difficult
- * to move ACIs in a run-time loadable module under the "dynacl" 
- * umbrella, because sets share some helpers with ACIs.
- */
 static int
 dynacl_aci_parse(
        const char *fname,
@@ -744,6 +817,11 @@ dynacl_aci_mask(
        char                    accessmaskbuf1[ACCESSMASK_MAXLEN];
 #endif /* LDAP_DEBUG */
 
+       if ( BER_BVISEMPTY( &e->e_nname ) ) {
+               /* no ACIs in the root DSE */
+               return -1;
+       }
+
        /* start out with nothing granted, nothing denied */
        ACL_INIT(tgrant);
        ACL_INIT(tdeny);
@@ -767,7 +845,7 @@ dynacl_aci_mask(
                        }
                }
                
-               Debug( LDAP_DEBUG_ACL, "<= aci_mask grant %s deny %s\n",
+               Debug( LDAP_DEBUG_ACL, "        <= aci_mask grant %s deny %s\n",
                          accessmask2str( tgrant, accessmaskbuf, 1 ), 
                          accessmask2str( tdeny, accessmaskbuf1, 1 ), 0 );
        }
@@ -779,35 +857,41 @@ dynacl_aci_mask(
        if ( tgrant == ACL_PRIV_NONE && tdeny == ACL_PRIV_NONE ) {
                struct berval   parent_ndn;
 
-#if 1
-               /* to solve the chicken'n'egg problem of accessing
-                * the OpenLDAPaci attribute, the direct access
-                * to the entry's attribute is unchecked; however,
-                * further accesses to OpenLDAPaci values in the 
-                * ancestors occur through backend_attribute(), i.e.
-                * with the identity of the operation, requiring
-                * further access checking.  For uniformity, this
-                * makes further requests occur as the rootdn, if
-                * any, i.e. searching for the OpenLDAPaci attribute
-                * is considered an internal search.  If this is not
-                * acceptable, then the same check needs be performed
-                * when accessing the entry's attribute. */
-               Operation       op2 = *op;
-
-               if ( !BER_BVISNULL( &op->o_bd->be_rootndn ) ) {
-                       op2.o_dn = op->o_bd->be_rootdn;
-                       op2.o_ndn = op->o_bd->be_rootndn;
-               }
-#endif
-
                dnParent( &e->e_nname, &parent_ndn );
                while ( !BER_BVISEMPTY( &parent_ndn ) ){
                        int             i;
                        BerVarray       bvals = NULL;
                        int             ret, stop;
 
-                       Debug( LDAP_DEBUG_ACL, "checking ACI of \"%s\"\n", parent_ndn.bv_val, 0, 0 );
-                       ret = backend_attribute( &op2, NULL, &parent_ndn, ad, &bvals, ACL_AUTH );
+                       /* to solve the chicken'n'egg problem of accessing
+                        * the OpenLDAPaci attribute, the direct access
+                        * to the entry's attribute is unchecked; however,
+                        * further accesses to OpenLDAPaci values in the 
+                        * ancestors occur through backend_attribute(), i.e.
+                        * with the identity of the operation, requiring
+                        * further access checking.  For uniformity, this
+                        * makes further requests occur as the rootdn, if
+                        * any, i.e. searching for the OpenLDAPaci attribute
+                        * is considered an internal search.  If this is not
+                        * acceptable, then the same check needs be performed
+                        * when accessing the entry's attribute. */
+                       struct berval   save_o_dn, save_o_ndn;
+       
+                       if ( !BER_BVISNULL( &op->o_bd->be_rootndn ) ) {
+                               save_o_dn = op->o_dn;
+                               save_o_ndn = op->o_ndn;
+
+                               op->o_dn = op->o_bd->be_rootdn;
+                               op->o_ndn = op->o_bd->be_rootndn;
+                       }
+
+                       Debug( LDAP_DEBUG_ACL, "        checking ACI of \"%s\"\n", parent_ndn.bv_val, 0, 0 );
+                       ret = backend_attribute( op, NULL, &parent_ndn, ad, &bvals, ACL_AUTH );
+
+                       if ( !BER_BVISNULL( &op->o_bd->be_rootndn ) ) {
+                               op->o_dn = save_o_dn;
+                               op->o_ndn = save_o_ndn;
+                       }
 
                        switch ( ret ) {
                        case LDAP_SUCCESS :
@@ -895,7 +979,6 @@ dynacl_aci_init( void )
        return rc;
 }
 
-#endif /* SLAP_DYNACL */
 
 /* ACI syntax validation */
 
@@ -1319,16 +1402,14 @@ OpenLDAPaciValidate(
                struct berval   ocbv = BER_BVNULL,
                                atbv = BER_BVNULL;
 
-               ocbv.bv_val = strchr( type.bv_val, '/' );
-               if ( ocbv.bv_val != NULL
-                       && ( ocbv.bv_val - type.bv_val ) < type.bv_len )
-               {
+               ocbv.bv_val = ber_bvchr( &type, '/' );
+               if ( ocbv.bv_val != NULL ) {
                        ocbv.bv_val++;
+                       ocbv.bv_len = type.bv_len
+                                       - ( ocbv.bv_val - type.bv_val );
 
-                       atbv.bv_val = strchr( ocbv.bv_val, '/' );
-                       if ( atbv.bv_val != NULL
-                               && ( atbv.bv_val - ocbv.bv_val ) < ocbv.bv_len )
-                       {
+                       atbv.bv_val = ber_bvchr( &ocbv, '/' );
+                       if ( atbv.bv_val != NULL ) {
                                AttributeDescription    *ad = NULL;
                                const char              *text = NULL;
                                int                     rc;
@@ -1342,10 +1423,6 @@ OpenLDAPaciValidate(
                                if ( rc != LDAP_SUCCESS ) {
                                        return LDAP_INVALID_SYNTAX;
                                }
-                               
-                       } else {
-                               ocbv.bv_len = type.bv_len
-                                       - ( ocbv.bv_val - type.bv_val );
                        }
 
                        if ( oc_bvfind( &ocbv ) == NULL ) {
@@ -1474,10 +1551,8 @@ OpenLDAPaciPrettyNormal(
                        struct berval   ocbv = BER_BVNULL,
                                        atbv = BER_BVNULL;
 
-                       ocbv.bv_val = strchr( type.bv_val, '/' );
-                       if ( ocbv.bv_val != NULL
-                               && ( ocbv.bv_val - type.bv_val ) < type.bv_len )
-                       {
+                       ocbv.bv_val = ber_bvchr( &type, '/' );
+                       if ( ocbv.bv_val != NULL ) {
                                ObjectClass             *oc = NULL;
                                AttributeDescription    *ad = NULL;
                                const char              *text = NULL;
@@ -1489,10 +1564,8 @@ OpenLDAPaciPrettyNormal(
                                ocbv.bv_val++;
                                ocbv.bv_len = type.bv_len - ( ocbv.bv_val - type.bv_val );
 
-                               atbv.bv_val = strchr( ocbv.bv_val, '/' );
-                               if ( atbv.bv_val != NULL
-                                       && ( atbv.bv_val - ocbv.bv_val ) < ocbv.bv_len )
-                               {
+                               atbv.bv_val = ber_bvchr( &ocbv, '/' );
+                               if ( atbv.bv_val != NULL ) {
                                        atbv.bv_val++;
                                        atbv.bv_len = type.bv_len
                                                - ( atbv.bv_val - type.bv_val );
@@ -1505,10 +1578,6 @@ OpenLDAPaciPrettyNormal(
                                        }
 
                                        bv.bv_len += STRLENOF( "/" ) + ad->ad_cname.bv_len;
-                                       
-                               } else {
-                                       ocbv.bv_len = type.bv_len
-                                               - ( ocbv.bv_val - type.bv_val );
                                }
 
                                oc = oc_bvfind( &ocbv );
@@ -1633,7 +1702,7 @@ OpenLDAPaciNormalize(
 int
 init_module( int argc, char *argv[] )
 {
-       return slap_dynacl_register();
+       return dynacl_aci_init();
 }
 #endif /* SLAPD_ACI_ENABLED == SLAPD_MOD_DYNAMIC */