#define ACI_BUF_SIZE 1024 /* use most appropriate size */
+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
+};
+
#ifdef SLAP_DYNACL
static
#endif /* SLAP_DYNACL */
}
} 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;
}
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,
}
#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,
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);
}
}
- 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 );
}
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 :
#define ACL_BUF_SIZE 1024 /* use most appropriate size */
-/*
- * speed up compares
- */
-const struct berval aci_bv[] = {
- BER_BVC("entry"),
- BER_BVC("children"),
- BER_BVC("onelevel"),
- BER_BVC("subtree"),
- BER_BVC("[entry]"),
- BER_BVC("[all]"),
- BER_BVC("access-id"),
-#if 0
- BER_BVC("anonymous"),
-#endif
- 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"),
- BER_BVC("grant"),
- BER_BVC("deny"),
-
- BER_BVC("IP="),
+static const struct berval acl_bv_ip_eq = BER_BVC( "IP=" );
#ifdef LDAP_PF_LOCAL
- BER_BVC("PATH="),
-#if 0
- BER_BVC(LDAP_DIRSEP),
-#endif
+static const struct berval acl_bv_path_eq = BER_BVC("PATH=");
#endif /* LDAP_PF_LOCAL */
-
- 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)
-};
static AccessControl * slap_acl_get(
AccessControl *ac, int *count,
Access *b;
#ifdef LDAP_DEBUG
char accessmaskbuf[ACCESSMASK_MAXLEN];
-#if !defined( SLAP_DYNACL ) && defined( SLAPD_ACI_ENABLED )
- char accessmaskbuf1[ACCESSMASK_MAXLEN];
-#endif /* !SLAP_DYNACL && SLAPD_ACI_ENABLED */
#endif /* DEBUG */
const char *attr;
slap_mask_t a2pmask = ACL_ACCESS2PRIV( *mask );
int port_number = -1;
if ( strncasecmp( op->o_conn->c_peer_name.bv_val,
- aci_bv[ ACI_BV_IP_EQ ].bv_val,
- aci_bv[ ACI_BV_IP_EQ ].bv_len ) != 0 )
+ acl_bv_ip_eq.bv_val,
+ acl_bv_ip_eq.bv_len ) != 0 )
continue;
- ip.bv_val = op->o_conn->c_peer_name.bv_val + aci_bv[ ACI_BV_IP_EQ ].bv_len;
- ip.bv_len = op->o_conn->c_peer_name.bv_len - aci_bv[ ACI_BV_IP_EQ ].bv_len;
+ ip.bv_val = op->o_conn->c_peer_name.bv_val + acl_bv_ip_eq.bv_len;
+ ip.bv_len = op->o_conn->c_peer_name.bv_len - acl_bv_ip_eq.bv_len;
port = strrchr( ip.bv_val, ':' );
if ( port ) {
struct berval path;
if ( strncmp( op->o_conn->c_peer_name.bv_val,
- aci_bv[ ACI_BV_PATH_EQ ].bv_val,
- aci_bv[ ACI_BV_PATH_EQ ].bv_len ) != 0 )
+ acl_bv_path_eq.bv_val,
+ acl_bv_path_eq.bv_len ) != 0 )
continue;
path.bv_val = op->o_conn->c_peer_name.bv_val
- + aci_bv[ ACI_BV_PATH_EQ ].bv_len;
+ + acl_bv_path_eq.bv_len;
path.bv_len = op->o_conn->c_peer_name.bv_len
- - aci_bv[ ACI_BV_PATH_EQ ].bv_len;
+ - acl_bv_path_eq.bv_len;
if ( ber_bvcmp( &b->a_peername_pat, &path ) != 0 )
continue;
bv = b->a_set_pat;
}
- if ( acl_match_set( &bv, op, e, 0 ) == 0 ) {
+ if ( acl_match_set( &bv, op, e, NULL ) == 0 ) {
continue;
}
}
0, 0, 0 );
/* this case works different from the others above.
- * since aci's themselves give permissions, we need
+ * since dynamic ACL's themselves give permissions, we need
* to first check b->a_access_mask, the ACL's access level.
*/
- if ( BER_BVISEMPTY( &e->e_nname ) ) {
- /* no ACIs in the root DSE */
- continue;
- }
-
/* first check if the right being requested
* is allowed by the ACL clause.
*/
} else
#else /* !SLAP_DYNACL */
+ /* NOTE: this entire block can be eliminated when SLAP_DYNACL
+ * moves outside of LDAP_DEVEL */
#ifdef SLAPD_ACI_ENABLED
if ( b->a_aci_at != NULL ) {
Attribute *at;
struct berval parent_ndn;
BerVarray bvals = NULL;
int ret, stop;
+#ifdef LDAP_DEBUG
+ char accessmaskbuf1[ACCESSMASK_MAXLEN];
+#endif /* DEBUG */
Debug( LDAP_DEBUG_ACL, " <= check a_aci_at: %s\n",
b->a_aci_at->ad_cname.bv_val, 0, 0 );
struct berval *subj,
Operation *op,
Entry *e,
- int setref )
+ struct berval *default_set_attribute )
{
struct berval set = BER_BVNULL;
int rc = 0;
AclSetCookie cookie;
- if ( setref == 0 ) {
+ if ( default_set_attribute == NULL ) {
ber_dupbv_x( &set, subj, op->o_tmpmemctx );
} else {
}
if ( acl_get_part( subj, 1, '/', &setat ) < 0 ) {
- setat = aci_bv[ ACI_BV_SET_ATTR ];
+ setat = *default_set_attribute;
}
/*
}
#endif /* SLAP_DYNACL */
-int
-acl_init( void )
-{
- int rc = 0;
-
+/*
+ * statically built-in dynamic ACL initialization
+ */
+static int (*acl_init_func[])( void ) = {
#ifdef SLAPD_ACI_ENABLED
#ifdef SLAP_DYNACL
- rc = dynacl_aci_init();
+ dynacl_aci_init,
#else /* !SLAP_DYNACL */
- rc = aci_init();
+ aci_init,
#endif /* !SLAP_DYNACL */
- if ( rc != 0 ) {
- return rc;
- }
#endif /* SLAPD_ACI_ENABLED */
- return rc;
+ NULL
+};
+
+int
+acl_init( void )
+{
+ int i, rc;
+
+ for ( i = 0; acl_init_func[ i ] != NULL; i++ ) {
+ rc = (*(acl_init_func[ i ]))();
+ if ( rc != 0 ) {
+ return rc;
+ }
+ }
+
+ return 0;
}
int