AC_ARG_ENABLE(xxslapdoptions,[
SLAPD (Standalone LDAP Daemon) Options:])
OL_ARG_ENABLE(slapd,[ --enable-slapd enable building slapd], yes)dnl
-OL_ARG_ENABLE(aci,[ --enable-aci enable per-object ACIs (experimental)], no)dnl
+OL_ARG_ENABLE(dynacl,[ --enable-dynacl enable run-time loadable ACL support (experimental)], no)dnl
+OL_ARG_ENABLE(aci,[ --enable-aci enable per-object ACIs (experimental)], no, [no yes mod])dnl
OL_ARG_ENABLE(cleartext,[ --enable-cleartext enable cleartext passwords], yes)dnl
OL_ARG_ENABLE(crypt,[ --enable-crypt enable crypt(3) passwords], no)dnl
OL_ARG_ENABLE(lmpasswd,[ --enable-lmpasswd enable LAN Manager passwords], no)dnl
ol_enable_modules=no
ol_enable_multimaster=no
ol_enable_rlookups=no
+ ol_enable_dynacl=no
ol_enable_aci=no
ol_enable_wrappers=no
AC_DEFINE(SLAPD_RLOOKUPS,1,[define to support reverse lookups])
fi
if test "$ol_enable_aci" != no ; then
- AC_DEFINE(SLAPD_ACI_ENABLED,1,[define to support per-object ACIs])
- WITH_ACI_ENABLED=yes
+ if test $ol_enable_dynacl = no ; then
+ ol_enable_dynacl=yes
+ AC_MSG_WARN([ACIs need dynacl])
+ fi
+ if test "$ol_enable_aci" = mod ; then
+ MFLAG=SLAPD_MOD_DYNAMIC
+ dnl remove this after moving servers/slapd/aci.c in contrib/slapd-modules/acl
+ AC_MSG_ERROR([ACI build as dynamic module not supported (yet)])
+ else
+ MFLAG=SLAPD_MOD_STATIC
+ fi
+ WITH_ACI_ENABLED=$ol_enable_aci
+ AC_DEFINE_UNQUOTED(SLAPD_ACI_ENABLED,$MFLAG,[define to support per-object ACIs])
else
WITH_ACI_ENABLED=no
fi
+if test "$ol_enable_dynacl" != no ; then
+ AC_DEFINE(SLAP_DYNACL,1,[define to support run-time loadable ACL])
+fi
if test "$ol_link_modules" != no ; then
AC_DEFINE(SLAPD_MODULES,1,[define to support modules])
tls_ssf=<n>
sasl_ssf=<n>
- aci[=<attrname>]
- dynacl/name[/<options>][.<dynstyle>][=<pattern>]
+ dynacl/<name>[/<options>][.<dynstyle>][=<pattern>]
.fi
.LP
with
<domainstyle>={exact|regex|sub(tree)}
<setstyle>={exact|regex}
<modifier>={expand}
+ <name>=aci <pattern>=<attrname>]
.fi
.LP
They may be specified in combination.
is undocumented yet.
.LP
The statement
-.B aci[=<attrname>]
-means that the access control is determined by the values in the
-.B attrname
-of the entry itself.
-The optional
-.B <attrname>
-indicates what attributeType holds the ACI information in the entry.
-By default, the
-.B OpenLDAPaci
-operational attribute is used.
-ACIs are experimental; they must be enabled at compile time.
-.LP
-The statement
.B dynacl/<name>[/<options>][.<dynstyle>][=<pattern>]
means that access checking is delegated to the admin-defined method
indicated by
.B <pattern>
are optional, and are directly passed to the registered parsing routine.
Dynacl is experimental; it must be enabled at compile time.
-If dynacl and ACIs are both enabled, ACIs are cast into the dynacl scheme,
-where
-.B <name>=aci
-and, optionally,
-.BR <patten>=<attrname> .
-However, the original ACI syntax is preserved for backward compatibility.
+.LP
+The statement
+.B dynacl/aci[=<attrname>]
+means that the access control is determined by the values in the
+.B attrname
+of the entry itself.
+The optional
+.B <attrname>
+indicates what attributeType holds the ACI information in the entry.
+By default, the
+.B OpenLDAPaci
+operational attribute is used.
+ACIs are experimental; they must be enabled at compile time.
.LP
The statements
.BR ssf=<n> ,
.B bindmethod=simple|sasl [binddn=<simple DN>] [credentials=<simple password>]
.B [saslmech=<SASL mech>] [secprops=<properties>] [realm=<realm>]
.B [authcId=<authentication ID>] [authzId=<authorization ID>]
-.B [attr[!]=<attr list>]
+.B [attrs[!]=<attr list>]
.RS
Specify a replication site for this database. Refer to the "OpenLDAP
Administrator's Guide" for detailed information on setting up a replicated
An
.B attr list
can be given after the
-.B attr
+.B attrs
keyword to allow the selective replication of the listed attributes only;
if the optional
.B !
# option ";x-hidden" can be searched for/compared,
# but are not shown. See \fBslapd.access\fP(5).
attributeoptions x-hidden lang-
-access to attr=name;x-hidden by * =cs
+access to attrs=name;x-hidden by * =cs
# Protect passwords. See \fBslapd.access\fP(5).
access to attrs=userPassword by * auth
#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
+
+/* 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"
enum {
ACI_BV_ENTRY,
BER_BVNULL
};
-#ifdef SLAP_DYNACL
-static
-#endif /* SLAP_DYNACL */
-AttributeDescription *slap_ad_aci;
+static AttributeDescription *slap_ad_aci;
static int
OpenLDAPaciValidate(
return rc;
}
-int
+static int
aci_mask(
Operation *op,
Entry *e,
return 0;
}
-int
+static int
aci_init( void )
{
/* OpenLDAP eXperimental Syntax */
return rc;
}
-#ifdef SLAP_DYNACL
static int
dynacl_aci_parse(
const char *fname,
return rc;
}
-#endif /* SLAP_DYNACL */
/* ACI syntax validation */
int
init_module( int argc, char *argv[] )
{
- return slap_dynacl_register();
+ return dynacl_aci_init();
}
#endif /* SLAPD_ACI_ENABLED == SLAPD_MOD_DYNAMIC */
if ( state ) {
if ( state->as_vd_ad == desc ) {
- if ( state->as_recorded ) {
- if ( ( state->as_recorded & ACL_STATE_RECORDED_NV ) &&
- val == NULL )
- {
- return state->as_result;
+ if ( ( state->as_recorded & ACL_STATE_RECORDED_NV ) &&
+ val == NULL )
+ {
+ return state->as_result;
- } else if ( ( state->as_recorded & ACL_STATE_RECORDED_VD ) &&
- val != NULL && state->as_vd_acl == NULL )
- {
- return state->as_result;
- }
+ } else if ( ( state->as_recorded & ACL_STATE_RECORDED_VD ) &&
+ val != NULL && state->as_vd_acl == NULL )
+ {
+ return state->as_result;
}
st_same_attr = 1;
} else {
if ( state ) {
if ( state->as_vd_ad == desc ) {
- if ( state->as_recorded ) {
- if ( ( state->as_recorded & ACL_STATE_RECORDED_NV ) &&
- val == NULL )
- {
- return state->as_result;
+ if ( ( state->as_recorded & ACL_STATE_RECORDED_NV ) &&
+ val == NULL )
+ {
+ return state->as_result;
- } else if ( ( state->as_recorded & ACL_STATE_RECORDED_VD ) &&
- val != NULL && state->as_vd_acl == NULL )
- {
- return state->as_result;
- }
+ } else if ( ( state->as_recorded & ACL_STATE_RECORDED_VD ) &&
+ val != NULL && state->as_vd_acl == NULL )
+ {
+ return state->as_result;
}
st_same_attr = 1;
} else {
*state = state_init;
}
- state->as_vd_ad=desc;
+ state->as_vd_ad = desc;
}
Debug( LDAP_DEBUG_ACL,
return ret;
}
-#endif /* SLAP_OVERLAY_ACCESS */
+#endif /* !SLAP_OVERLAY_ACCESS */
/*
* slap_acl_get - return the acl applicable to entry e, attribute
}
} 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;
- slap_access_t grant, deny, tgrant, tdeny;
- 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 );
-
- /* this case works different from the others above.
- * since aci'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.
- */
- if ( ! ACL_GRANT( b->a_access_mask, *mask ) ) {
- continue;
- }
- /* start out with nothing granted, nothing denied */
- ACL_INIT(tgrant);
- ACL_INIT(tdeny);
-
- /* get the aci attribute */
- at = attr_find( e->e_attrs, b->a_aci_at );
- if ( at != NULL ) {
-#if 0
- /* FIXME: this breaks acl caching;
- * see also ACL_RECORD_VALUE_STATE below */
- ACL_RECORD_VALUE_STATE;
-#endif
- /* the aci is an multi-valued attribute. The
- * rights are determined by OR'ing the individual
- * rights given by the acis.
- */
- for ( i = 0; !BER_BVISNULL( &at->a_nvals[i] ); i++ ) {
- if ( aci_mask( op,
- e, desc, val,
- &at->a_nvals[i],
- nmatch, matches,
- &grant, &deny, SLAP_ACI_SCOPE_ENTRY ) != 0 )
- {
- tgrant |= grant;
- tdeny |= deny;
- }
- }
- Debug(LDAP_DEBUG_ACL, "<= aci_mask grant %s deny %s\n",
- accessmask2str(tgrant, accessmaskbuf, 1),
- accessmask2str(tdeny, accessmaskbuf1, 1), 0);
-
- }
- /* If the entry level aci didn't contain anything valid for the
- * current operation, climb up the tree and evaluate the
- * acis with scope set to subtree
- */
- if ( (tgrant == ACL_PRIV_NONE) && (tdeny == ACL_PRIV_NONE) ) {
- dnParent( &e->e_nname, &parent_ndn );
- while ( !BER_BVISEMPTY( &parent_ndn ) ) {
- Debug(LDAP_DEBUG_ACL, "checking ACI of %s\n", parent_ndn.bv_val, 0, 0);
- ret = backend_attribute(op, NULL, &parent_ndn, b->a_aci_at, &bvals, ACL_AUTH);
- switch(ret){
- case LDAP_SUCCESS :
- stop = 0;
- if (!bvals){
- break;
- }
-
- for ( i = 0; !BER_BVISNULL( &bvals[i] ); i++ ) {
-#if 0
- /* FIXME: this breaks acl caching;
- * see also ACL_RECORD_VALUE_STATE above */
- ACL_RECORD_VALUE_STATE;
-#endif
- if ( aci_mask( op, e, desc, val, &bvals[i],
- nmatch, matches,
- &grant, &deny, SLAP_ACI_SCOPE_CHILDREN ) != 0 )
- {
- tgrant |= grant;
- tdeny |= deny;
- /* evaluation stops as soon as either a "deny" or a
- * "grant" directive matches.
- */
- if( (tgrant != ACL_PRIV_NONE) || (tdeny != ACL_PRIV_NONE) ){
- stop = 1;
- }
- }
- Debug(LDAP_DEBUG_ACL, "<= aci_mask grant %s deny %s\n",
- accessmask2str(tgrant, accessmaskbuf, 1),
- accessmask2str(tdeny, accessmaskbuf1, 1), 0);
- }
- break;
-
- case LDAP_NO_SUCH_ATTRIBUTE:
- /* just go on if the aci-Attribute is not present in
- * the current entry
- */
- Debug(LDAP_DEBUG_ACL, "no such attribute\n", 0, 0, 0);
- stop = 0;
- break;
-
- case LDAP_NO_SUCH_OBJECT:
- /* We have reached the base object */
- Debug(LDAP_DEBUG_ACL, "no such object\n", 0, 0, 0);
- stop = 1;
- break;
-
- default:
- stop = 1;
- break;
- }
- if (stop){
- break;
- }
- dnParent( &parent_ndn, &parent_ndn );
- }
- }
-
-
- /* remove anything that the ACL clause does not allow */
- tgrant &= b->a_access_mask & ACL_PRIV_MASK;
- tdeny &= ACL_PRIV_MASK;
-
- /* see if we have anything to contribute */
- if( ACL_IS_INVALID(tgrant) && ACL_IS_INVALID(tdeny) ) {
- continue;
- }
-
- /* this could be improved by changing slap_acl_mask so that it can deal with
- * by clauses that return grant/deny pairs. Right now, it does either
- * additive or subtractive rights, but not both at the same time. So,
- * we need to combine the grant/deny pair into a single rights mask in
- * a smart way: if either grant or deny is "empty", then we use the
- * opposite as is, otherwise we remove any denied rights from the grant
- * rights mask and construct an additive mask.
- */
- if (ACL_IS_INVALID(tdeny)) {
- modmask = tgrant | ACL_PRIV_ADDITIVE;
-
- } else if (ACL_IS_INVALID(tgrant)) {
- modmask = tdeny | ACL_PRIV_SUBSTRACTIVE;
-
- } else {
- modmask = (tgrant & ~tdeny) | ACL_PRIV_ADDITIVE;
- }
-
- } else
-#endif /* SLAPD_ACI_ENABLED */
-#endif /* !SLAP_DYNACL */
+#endif /* SLAP_DYNACL */
{
modmask = b->a_access_mask;
}
* statically built-in dynamic ACL initialization
*/
static int (*acl_init_func[])( void ) = {
-#ifdef SLAPD_ACI_ENABLED
#ifdef SLAP_DYNACL
+ /* TODO: remove when ACI will only be dynamic */
+#if SLAPD_ACI_ENABLED == SLAPD_MOD_STATIC
dynacl_aci_init,
-#else /* !SLAP_DYNACL */
- aci_init,
-#endif /* !SLAP_DYNACL */
#endif /* SLAPD_ACI_ENABLED */
+#endif /* SLAP_DYNACL */
NULL
};
{
char *name = NULL,
*opts = NULL;
-
+
+#if 1 /* tolerate legacy "aci" <who> */
if ( strcasecmp( left, "aci" ) == 0 ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "undocumented deprecated \"aci\" directive "
+ "is superseded by \"dynacl/aci\".\n",
+ fname, lineno, 0 );
name = "aci";
- } else if ( strncasecmp( left, "dynacl/", STRLENOF( "dynacl/" ) ) == 0 ) {
+ } else
+#endif /* tolerate legacy "aci" <who> */
+ if ( strncasecmp( left, "dynacl/", STRLENOF( "dynacl/" ) ) == 0 ) {
name = &left[ STRLENOF( "dynacl/" ) ];
opts = strchr( name, '/' );
if ( opts ) {
continue;
}
}
-#else /* ! SLAP_DYNACL */
-
-#ifdef SLAPD_ACI_ENABLED
- if ( strcasecmp( left, "aci" ) == 0 ) {
- if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
- "inappropriate style \"%s\" in by clause.\n",
- fname, lineno, style );
- return acl_usage();
- }
-
- if( b->a_aci_at != NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: ACI attribute already specified.\n",
- fname, lineno, 0 );
- return acl_usage();
- }
-
- if ( right != NULL && *right != '\0' ) {
- rc = slap_str2ad( right, &b->a_aci_at, &text );
-
- if( rc != LDAP_SUCCESS ) {
- char buf[ SLAP_TEXT_BUFLEN ];
-
- snprintf( buf, sizeof( buf ),
- "aci \"%s\": %s.",
- right, text );
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: %s\n",
- fname, lineno, buf );
- return acl_usage();
- }
-
- } else {
- b->a_aci_at = slap_ad_aci;
- }
-
- if( !is_at_syntax( b->a_aci_at->ad_type,
- SLAPD_ACI_SYNTAX) )
- {
- char buf[ SLAP_TEXT_BUFLEN ];
-
- snprintf( buf, sizeof( buf ),
- "ACI \"%s\": inappropriate syntax: %s.",
- right,
- b->a_aci_at->ad_type->sat_syntax_oid );
- Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n",
- fname, lineno, buf );
- return acl_usage();
- }
-
- continue;
- }
-#endif /* SLAPD_ACI_ENABLED */
-#endif /* ! SLAP_DYNACL */
+#endif /* SLAP_DYNACL */
if ( strcasecmp( left, "ssf" ) == 0 ) {
if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
"\t[domain[.<domainstyle>]=<domain>] [sockurl[.<style>]=<url>]\n"
#ifdef SLAP_DYNACL
"\t[dynacl/<name>[/<options>][.<dynstyle>][=<pattern>]]\n"
-#else /* ! SLAP_DYNACL */
-#ifdef SLAPD_ACI_ENABLED
- "\t[aci[=<attrname>]]\n"
-#endif /* SLAPD_ACI_ENABLED */
-#endif /* ! SLAP_DYNACL */
+#endif /* SLAP_DYNACL */
"\t[ssf=<n>] [transport_ssf=<n>] [tls_ssf=<n>] [sasl_ssf=<n>]\n"
"<style> ::= exact | regex | base(Object)\n"
"<dnstyle> ::= base(Object) | one(level) | sub(tree) | children | "
}
}
}
-#else /* ! SLAP_DYNACL */
-#ifdef SLAPD_ACI_ENABLED
- if ( b->a_aci_at != NULL ) {
- ptr = lutil_strcopy( ptr, " aci=" );
- ptr = lutil_strcopy( ptr, b->a_aci_at->ad_cname.bv_val );
- }
-#endif
#endif /* SLAP_DYNACL */
/* Security Strength Factors */
/*
* aci.c
*/
-#ifdef SLAPD_ACI_ENABLED
-LDAP_SLAPD_F (int) aci_mask LDAP_P((
- Operation *op, Entry *e,
- AttributeDescription *desc,
- struct berval *val,
- struct berval *aci,
- int nmatch,
- regmatch_t *matches,
- slap_access_t *grant,
- slap_access_t *deny,
- slap_aci_scope_t scope));
#ifdef SLAP_DYNACL
+#ifdef SLAPD_ACI_ENABLED
LDAP_SLAPD_F (int) dynacl_aci_init LDAP_P(( void ));
-#else /* !SLAP_DYNACL */
-LDAP_SLAPD_F (int) aci_init LDAP_P(( void ));
-LDAP_SLAPD_V (AttributeDescription *) slap_ad_aci;
-#endif /* !SLAP_DYNACL */
#endif /* SLAPD_ACI_ENABLED */
+#endif /* SLAP_DYNACL */
/*
* acl.c
#define SLAP_ACL_HONOR_DISCLOSE /* partially implemented */
#define SLAP_ACL_HONOR_MANAGE /* not yet implemented */
-#define SLAP_DYNACL
#define SLAP_OVERLAY_ACCESS
#define LDAP_COMP_MATCH
#define LDAP_DYNAMIC_OBJECTS
#define SLAPD_ROLE_ATTR "roleOccupant"
#define SLAPD_ROLE_CLASS "organizationalRole"
-#ifdef SLAPD_ACI_ENABLED
-#define SLAPD_ACI_SYNTAX "1.3.6.1.4.1.4203.666.2.1"
-#endif /* SLAPD_ACI_ENABLED */
-
-/* change this to "OpenLDAPset" */
-#define SLAPD_ACI_SET_ATTR "template"
-
#define SLAPD_TOP_OID "2.5.6.0"
LDAP_SLAPD_V (int) slap_debug;
struct slap_acl *acl_next;
} AccessControl;
+typedef enum {
+ ACL_STATE_NOT_RECORDED = 0x0,
+ ACL_STATE_RECORDED_VD = 0x1,
+ ACL_STATE_RECORDED_NV = 0x2,
+ ACL_STATE_RECORDED = ( ACL_STATE_RECORDED_VD | ACL_STATE_RECORDED_NV )
+} slap_acl_state_t;
+
typedef struct slap_acl_state {
- unsigned as_recorded;
-#define ACL_STATE_NOT_RECORDED 0x0
-#define ACL_STATE_RECORDED_VD 0x1
-#define ACL_STATE_RECORDED_NV 0x2
-#define ACL_STATE_RECORDED 0x3
+ slap_acl_state_t as_recorded;
/* Access state */
AccessControl *as_vd_acl;
#mod#moduleload back_@BACKEND@.la
#monitormod#modulepath ../servers/slapd/back-monitor/
#monitormod#moduleload back_monitor.la
+#acimod#modulepath ../servers/slapd/
+#acimod#moduleload aci.la
#######################################################################
# database definitions
#ldbm#index cn,sn,uid pres,eq,sub
access to dn.subtree="dc=example,dc=com"
- by aci write
+ by dynacl/aci write
#monitor#database monitor