mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-20 22:59:34 -05:00
ACIs from Mark Valence <kurash@sassafras.com> (ITS#261)
This commit is contained in:
parent
255e36df0b
commit
87675a953d
9 changed files with 1145 additions and 642 deletions
16
configure.in
16
configure.in
|
|
@ -111,6 +111,8 @@ OL_ARG_ENABLE(multimaster,[ --enable-multimaster enable multimaster replicati
|
||||||
OL_ARG_ENABLE(phonetic,[ --enable-phonetic enable phonetic/soundex], no)dnl
|
OL_ARG_ENABLE(phonetic,[ --enable-phonetic enable phonetic/soundex], no)dnl
|
||||||
OL_ARG_ENABLE(quipu,[ --enable-quipu build quipu migration tools], no)dnl
|
OL_ARG_ENABLE(quipu,[ --enable-quipu build quipu migration tools], no)dnl
|
||||||
OL_ARG_ENABLE(rlookups,[ --enable-rlookups enable reverse lookups], auto)dnl
|
OL_ARG_ENABLE(rlookups,[ --enable-rlookups enable reverse lookups], auto)dnl
|
||||||
|
OL_ARG_ENABLE(aci,[ --enable-aci enable per-object ACIs], no)dnl
|
||||||
|
OL_ARG_ENABLE(discreteaci,[ --enable-discreteaci enable discrete rights in ACIs], no)dnl
|
||||||
OL_ARG_ENABLE(wrappers,[ --enable-wrappers enable tcp wrapper support], no)dnl
|
OL_ARG_ENABLE(wrappers,[ --enable-wrappers enable tcp wrapper support], no)dnl
|
||||||
|
|
||||||
dnl SLAPD Backend options
|
dnl SLAPD Backend options
|
||||||
|
|
@ -203,6 +205,12 @@ if test $ol_enable_slapd = no ; then
|
||||||
if test $ol_enable_rlookups = yes ; then
|
if test $ol_enable_rlookups = yes ; then
|
||||||
AC_MSG_WARN([slapd disabled, ignoring --enable-rlookups argument])
|
AC_MSG_WARN([slapd disabled, ignoring --enable-rlookups argument])
|
||||||
fi
|
fi
|
||||||
|
if test $ol_enable_aci = yes ; then
|
||||||
|
AC_MSG_WARN([slapd disabled, ignoring --enable-aci argument])
|
||||||
|
fi
|
||||||
|
if test $ol_enable_discreteaci = yes ; then
|
||||||
|
AC_MSG_WARN([slapd disabled, ignoring --enable-discreteaci argument])
|
||||||
|
fi
|
||||||
if test $ol_with_ldbm_api != auto ; then
|
if test $ol_with_ldbm_api != auto ; then
|
||||||
AC_MSG_WARN([slapd disabled, ignoring --with-ldbm-api argument])
|
AC_MSG_WARN([slapd disabled, ignoring --with-ldbm-api argument])
|
||||||
fi
|
fi
|
||||||
|
|
@ -248,6 +256,8 @@ if test $ol_enable_slapd = no ; then
|
||||||
ol_enable_phonetic=no
|
ol_enable_phonetic=no
|
||||||
ol_enable_quipu=no
|
ol_enable_quipu=no
|
||||||
ol_enable_rlookups=no
|
ol_enable_rlookups=no
|
||||||
|
ol_enable_aci=no
|
||||||
|
ol_enable_discreteaci=no
|
||||||
ol_enable_wrappers=no
|
ol_enable_wrappers=no
|
||||||
|
|
||||||
ol_with_ldbm_api=no
|
ol_with_ldbm_api=no
|
||||||
|
|
@ -1887,6 +1897,12 @@ fi
|
||||||
if test "$ol_enable_rlookups" != no ; then
|
if test "$ol_enable_rlookups" != no ; then
|
||||||
AC_DEFINE(SLAPD_RLOOKUPS,1,[define to support reverse lookups])
|
AC_DEFINE(SLAPD_RLOOKUPS,1,[define to support reverse lookups])
|
||||||
fi
|
fi
|
||||||
|
if test "$ol_enable_aci" != no ; then
|
||||||
|
AC_DEFINE(SLAPD_ACI_ENABLED,1,[define to support per-object ACIs])
|
||||||
|
fi
|
||||||
|
if test "$ol_enable_discreteaci" != no ; then
|
||||||
|
AC_DEFINE(SLAPD_ACI_DISCRETE_RIGHTS,1,[define to support discrete rights in ACIs])
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$ol_link_modules" != no ; then
|
if test "$ol_link_modules" != no ; then
|
||||||
AC_DEFINE(SLAPD_MODULES,1,[define to support modules])
|
AC_DEFINE(SLAPD_MODULES,1,[define to support modules])
|
||||||
|
|
|
||||||
|
|
@ -789,6 +789,12 @@
|
||||||
/* define to support reverse lookups */
|
/* define to support reverse lookups */
|
||||||
#undef SLAPD_RLOOKUPS
|
#undef SLAPD_RLOOKUPS
|
||||||
|
|
||||||
|
/* define to support per-object ACIs */
|
||||||
|
#undef SLAPD_ACI_ENABLED
|
||||||
|
|
||||||
|
/* define to support discrete rights in ACIs */
|
||||||
|
#undef SLAPD_ACI_DISCRETE_RIGHTS
|
||||||
|
|
||||||
/* define to support modules */
|
/* define to support modules */
|
||||||
#undef SLAPD_MODULES
|
#undef SLAPD_MODULES
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,12 @@ typedef char * caddr_t;
|
||||||
/* define this for Reverse Lookup support */
|
/* define this for Reverse Lookup support */
|
||||||
#define SLAPD_RLOOKUPS 1
|
#define SLAPD_RLOOKUPS 1
|
||||||
|
|
||||||
|
/* define this for per-object ACIs */
|
||||||
|
/* #undef SLAPD_ACI_ENABLED */
|
||||||
|
|
||||||
|
/* define this for discrete rights in ACIs */
|
||||||
|
/* #undef SLAPD_ACI_DISCRETE_RIGHTS */
|
||||||
|
|
||||||
/* define this to use SLAPD shell backend */
|
/* define this to use SLAPD shell backend */
|
||||||
/* #undef SLAPD_SHELL */
|
/* #undef SLAPD_SHELL */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,11 @@
|
||||||
|
|
||||||
#include "slap.h"
|
#include "slap.h"
|
||||||
|
|
||||||
|
#ifdef SLAPD_ACI_ENABLED
|
||||||
|
int aci_access_allowed (struct berval *aci, char *attr, Backend *be, Entry *e,
|
||||||
|
Operation *op, int access, char *edn, regmatch_t *matches);
|
||||||
|
#endif
|
||||||
|
|
||||||
static int regex_matches(char *pat, char *str, char *buf, regmatch_t *matches);
|
static int regex_matches(char *pat, char *str, char *buf, regmatch_t *matches);
|
||||||
static void string_expand(char *newbuf, int bufsiz, char *pattern,
|
static void string_expand(char *newbuf, int bufsiz, char *pattern,
|
||||||
char *match, regmatch_t *matches);
|
char *match, regmatch_t *matches);
|
||||||
|
|
@ -83,7 +88,7 @@ access_allowed(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = acl_access_allowed( a, be, conn, e, val, op, access, edn, matches );
|
rc = acl_access_allowed( a, attr, be, conn, e, val, op, access, edn, matches );
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: exit (%s) attr (%s)\n",
|
Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: exit (%s) attr (%s)\n",
|
||||||
e->e_dn, attr, 0);
|
e->e_dn, attr, 0);
|
||||||
|
|
@ -208,6 +213,7 @@ acl_get_applicable(
|
||||||
int
|
int
|
||||||
acl_access_allowed(
|
acl_access_allowed(
|
||||||
AccessControl *a,
|
AccessControl *a,
|
||||||
|
char *attr,
|
||||||
Backend *be,
|
Backend *be,
|
||||||
Connection *conn,
|
Connection *conn,
|
||||||
Entry *e,
|
Entry *e,
|
||||||
|
|
@ -376,6 +382,52 @@ acl_access_allowed(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SLAPD_ACI_ENABLED
|
||||||
|
if ( b->a_aci_at != NULL ) {
|
||||||
|
Attribute *at;
|
||||||
|
|
||||||
|
/* this case works different from the others above.
|
||||||
|
* since aci's themselves give permissions, we need
|
||||||
|
* to first check b->a_access, the ACL's access level.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if( op->o_ndn == NULL || op->o_ndn[0] == '\0' ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( e->e_dn == NULL ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* first check if the right being requested is
|
||||||
|
* higher than allowed by the ACL clause.
|
||||||
|
*/
|
||||||
|
if ( ! ACL_GRANT( b->a_access, access ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the aci attribute */
|
||||||
|
at = attr_find( e->e_attrs, b->a_aci_at );
|
||||||
|
if ( at == NULL ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the aci is an multi-valued attribute. The
|
||||||
|
* rights are determined by OR'ing the individual
|
||||||
|
* rights given by the acis.
|
||||||
|
*/
|
||||||
|
for ( i = 0; at->a_vals[i] != NULL; i++ ) {
|
||||||
|
if ( aci_access_allowed( at->a_vals[i], attr, be, e, op, access, edn, matches ) ) {
|
||||||
|
Debug( LDAP_DEBUG_ACL,
|
||||||
|
"<= acl_access_allowed: matched by clause #%d access granted\n",
|
||||||
|
i, 0, 0 );
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_ACL,
|
Debug( LDAP_DEBUG_ACL,
|
||||||
"<= acl_access_allowed: matched by clause #%d access %s\n",
|
"<= acl_access_allowed: matched by clause #%d access %s\n",
|
||||||
i,
|
i,
|
||||||
|
|
@ -433,7 +485,7 @@ acl_check_modlist(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) {
|
for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) {
|
||||||
if ( ! acl_access_allowed( a, be, conn, e, mlist->ml_bvalues[i],
|
if ( ! acl_access_allowed( a, mlist->ml_type, be, conn, e, mlist->ml_bvalues[i],
|
||||||
op, ACL_WRITE, edn, matches) )
|
op, ACL_WRITE, edn, matches) )
|
||||||
{
|
{
|
||||||
return( LDAP_INSUFFICIENT_ACCESS );
|
return( LDAP_INSUFFICIENT_ACCESS );
|
||||||
|
|
@ -443,7 +495,7 @@ acl_check_modlist(
|
||||||
|
|
||||||
case LDAP_MOD_DELETE:
|
case LDAP_MOD_DELETE:
|
||||||
if ( mlist->ml_bvalues == NULL ) {
|
if ( mlist->ml_bvalues == NULL ) {
|
||||||
if ( ! acl_access_allowed( a, be, conn, e,
|
if ( ! acl_access_allowed( a, mlist->ml_type, be, conn, e,
|
||||||
NULL, op, ACL_WRITE, edn, matches) )
|
NULL, op, ACL_WRITE, edn, matches) )
|
||||||
{
|
{
|
||||||
return( LDAP_INSUFFICIENT_ACCESS );
|
return( LDAP_INSUFFICIENT_ACCESS );
|
||||||
|
|
@ -451,7 +503,7 @@ acl_check_modlist(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) {
|
for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) {
|
||||||
if ( ! acl_access_allowed( a, be, conn, e, mlist->ml_bvalues[i],
|
if ( ! acl_access_allowed( a, mlist->ml_type, be, conn, e, mlist->ml_bvalues[i],
|
||||||
op, ACL_WRITE, edn, matches) )
|
op, ACL_WRITE, edn, matches) )
|
||||||
{
|
{
|
||||||
return( LDAP_INSUFFICIENT_ACCESS );
|
return( LDAP_INSUFFICIENT_ACCESS );
|
||||||
|
|
@ -464,6 +516,333 @@ acl_check_modlist(
|
||||||
return( LDAP_SUCCESS );
|
return( LDAP_SUCCESS );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SLAPD_ACI_ENABLED
|
||||||
|
char *
|
||||||
|
aci_bvstrdup (struct berval *bv)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
s = (char *)ch_malloc(bv->bv_len + 1);
|
||||||
|
if (s != NULL) {
|
||||||
|
memcpy(s, bv->bv_val, bv->bv_len);
|
||||||
|
s[bv->bv_len] = 0;
|
||||||
|
}
|
||||||
|
return(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
aci_strbvcmp (char *s, struct berval *bv)
|
||||||
|
{
|
||||||
|
int res, len;
|
||||||
|
|
||||||
|
res = strncasecmp( s, bv->bv_val, bv->bv_len );
|
||||||
|
if (res)
|
||||||
|
return(res);
|
||||||
|
len = strlen(s);
|
||||||
|
if (len > bv->bv_len)
|
||||||
|
return(1);
|
||||||
|
if (len < bv->bv_len)
|
||||||
|
return(-1);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
aci_get_part (struct berval *list, int ix, char sep, struct berval *bv)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (bv) {
|
||||||
|
bv->bv_len = 0;
|
||||||
|
bv->bv_val = NULL;
|
||||||
|
}
|
||||||
|
len = list->bv_len;
|
||||||
|
p = list->bv_val;
|
||||||
|
while (len >= 0 && --ix >= 0) {
|
||||||
|
while (--len >= 0 && *p++ != sep) ;
|
||||||
|
}
|
||||||
|
while (len >= 0 && *p == ' ') {
|
||||||
|
len--;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
if (len < 0)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (!bv)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
bv->bv_val = p;
|
||||||
|
while (--len >= 0 && *p != sep) {
|
||||||
|
bv->bv_len++;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
while (bv->bv_len > 0 && *--p == ' ')
|
||||||
|
bv->bv_len--;
|
||||||
|
return(bv->bv_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
aci_list_has_right (struct berval *list, int access, int action)
|
||||||
|
{
|
||||||
|
struct berval bv;
|
||||||
|
int i, right;
|
||||||
|
|
||||||
|
for (i = 0; aci_get_part(list, i, ',', &bv) >= 0; i++) {
|
||||||
|
if (bv.bv_len <= 0)
|
||||||
|
continue;
|
||||||
|
switch (*bv.bv_val) {
|
||||||
|
case 'c':
|
||||||
|
right = ACL_COMPARE;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
/* **** NOTE: draft-ietf-ldapext-aci-model-0.3.txt defines
|
||||||
|
* the right 's' to mean "set", but in the examples states
|
||||||
|
* that the right 's' means "search". The latter definition
|
||||||
|
* is used here.
|
||||||
|
*/
|
||||||
|
right = ACL_SEARCH;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
right = ACL_READ;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
right = ACL_WRITE;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
/* **** NOTE: draft-ietf-ldapext-aci-model-0.3.txt does not
|
||||||
|
* define any equivalent to the AUTH right, so I've just used
|
||||||
|
* 'x' for now.
|
||||||
|
*/
|
||||||
|
right = ACL_AUTH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
right = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef SLAPD_ACI_DISCRETE_RIGHTS
|
||||||
|
if (right & access) {
|
||||||
|
return(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(!action);
|
||||||
|
#else
|
||||||
|
if (action != 0) {
|
||||||
|
// check granted
|
||||||
|
if (ACL_GRANT(right, access))
|
||||||
|
return(1);
|
||||||
|
} else {
|
||||||
|
// check denied
|
||||||
|
if (right <= access)
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
aci_list_has_attr (struct berval *list, char *attr)
|
||||||
|
{
|
||||||
|
struct berval bv;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; aci_get_part(list, i, ',', &bv) >= 0; i++) {
|
||||||
|
if (aci_strbvcmp(attr, &bv) == 0) {
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
aci_list_has_attr_right (struct berval *list, char *attr, int access, int action)
|
||||||
|
{
|
||||||
|
struct berval bv, entry;
|
||||||
|
int i, found;
|
||||||
|
|
||||||
|
/* loop through each rights/attr pair, skip first part (action) */
|
||||||
|
found = -1;
|
||||||
|
for (i = 1; aci_get_part(list, i + 1, ';', &bv) >= 0; i += 2) {
|
||||||
|
if (aci_list_has_attr(&bv, attr) == 0)
|
||||||
|
continue;
|
||||||
|
found = 0;
|
||||||
|
if (aci_get_part(list, i, ';', &bv) < 0)
|
||||||
|
continue;
|
||||||
|
if (aci_list_has_right(&bv, access, action) != 0)
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
return(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
aci_list_has_permission (struct berval *list, char *attr, int access)
|
||||||
|
{
|
||||||
|
struct berval perm, actn;
|
||||||
|
int i, action, specific, general;
|
||||||
|
|
||||||
|
if (attr == NULL || *attr == 0 || strcasecmp(attr, "entry") == 0) {
|
||||||
|
attr = "[entry]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* loop through each permissions clause */
|
||||||
|
for (i = 0; aci_get_part(list, i, '$', &perm) >= 0; i++) {
|
||||||
|
if (aci_get_part(&perm, 0, ';', &actn) < 0)
|
||||||
|
continue;
|
||||||
|
if (aci_strbvcmp( "grant", &actn ) == 0) {
|
||||||
|
action = 1;
|
||||||
|
} else if (aci_strbvcmp( "deny", &actn ) == 0) {
|
||||||
|
action = 0;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
specific = aci_list_has_attr_right(&perm, attr, access, action);
|
||||||
|
if (specific >= 0)
|
||||||
|
return(specific);
|
||||||
|
|
||||||
|
general = aci_list_has_attr_right(&perm, "[all]", access, action);
|
||||||
|
if (general >= 0)
|
||||||
|
return(general);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
aci_group_member (
|
||||||
|
struct berval *subj,
|
||||||
|
char *grpoc,
|
||||||
|
char *grpat,
|
||||||
|
Backend *be,
|
||||||
|
Entry *e,
|
||||||
|
Operation *op,
|
||||||
|
char *edn,
|
||||||
|
regmatch_t *matches
|
||||||
|
)
|
||||||
|
{
|
||||||
|
struct berval bv;
|
||||||
|
char *subjdn, *grpdn;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* format of string is "group/objectClassValue/groupAttrName" */
|
||||||
|
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)
|
||||||
|
grpoc = ch_strdup(grpoc);
|
||||||
|
else
|
||||||
|
grpoc = aci_bvstrdup(&bv);
|
||||||
|
|
||||||
|
if (aci_get_part(subj, 2, '/', &bv) < 0)
|
||||||
|
grpat = ch_strdup(grpat);
|
||||||
|
else
|
||||||
|
grpat = aci_bvstrdup(&bv);
|
||||||
|
|
||||||
|
grpdn = (char *)ch_malloc(1024);
|
||||||
|
if (grpoc != NULL && grpat != NULL && grpdn != NULL) {
|
||||||
|
string_expand(grpdn, 1024, subjdn, edn, matches);
|
||||||
|
if ( dn_normalize_case(grpdn) != NULL ) {
|
||||||
|
rc = (backend_group(be, e, grpdn, op->o_ndn, grpoc, grpat) == 0);
|
||||||
|
}
|
||||||
|
ch_free(grpdn);
|
||||||
|
}
|
||||||
|
if (grpat != NULL)
|
||||||
|
ch_free(grpat);
|
||||||
|
if (grpoc != NULL)
|
||||||
|
ch_free(grpoc);
|
||||||
|
ch_free(subjdn);
|
||||||
|
return(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
aci_access_allowed (
|
||||||
|
struct berval *aci,
|
||||||
|
char *attr,
|
||||||
|
Backend *be,
|
||||||
|
Entry *e,
|
||||||
|
Operation *op,
|
||||||
|
int access,
|
||||||
|
char *edn,
|
||||||
|
regmatch_t *matches
|
||||||
|
)
|
||||||
|
{
|
||||||
|
struct berval bv, perms, sdn;
|
||||||
|
char *subjdn;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_ACL,
|
||||||
|
"\n=> aci_access_allowed: %s access to entry \"%s\"\n",
|
||||||
|
access2str( access ), e->e_dn, 0 );
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_ACL,
|
||||||
|
"\n=> aci_access_allowed: %s access to attribute \"%s\" by \"%s\"\n",
|
||||||
|
access2str( access ),
|
||||||
|
attr,
|
||||||
|
op->o_ndn ? op->o_ndn : "" );
|
||||||
|
|
||||||
|
/* parse an aci of the form:
|
||||||
|
oid#scope#action;rights;attr;rights;attr$action;rights;attr;rights;attr#dnType#subjectDN
|
||||||
|
|
||||||
|
See draft-ietf-ldapext-aci-model-0.3.txt section 9.1 for
|
||||||
|
a full description of the format for this attribute.
|
||||||
|
|
||||||
|
For now, this routine only supports scope=entry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* check that the aci has all 5 components */
|
||||||
|
if (aci_get_part(aci, 4, '#', NULL) < 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
/* check that the scope is "entry" */
|
||||||
|
if (aci_get_part(aci, 1, '#', &bv) < 0
|
||||||
|
|| aci_strbvcmp( "entry", &bv ) != 0)
|
||||||
|
{
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the list of permissions clauses, bail if empty */
|
||||||
|
if (aci_get_part(aci, 2, '#', &perms) <= 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
/* check if any permissions allow desired access */
|
||||||
|
if (aci_list_has_permission(&perms, attr, access) == 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
/* see if we have a DN match */
|
||||||
|
if (aci_get_part(aci, 3, '#', &bv) < 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
if (aci_get_part(aci, 4, '#', &sdn) < 0)
|
||||||
|
return(0);
|
||||||
|
if (aci_strbvcmp( "access-id", &bv ) == 0) {
|
||||||
|
subjdn = aci_bvstrdup(&sdn);
|
||||||
|
if (subjdn == NULL)
|
||||||
|
return(0);
|
||||||
|
rc = 0;
|
||||||
|
if (dn_normalize_case(subjdn) != NULL)
|
||||||
|
rc = (strcasecmp(op->o_ndn, subjdn) == 0);
|
||||||
|
ch_free(subjdn);
|
||||||
|
return(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aci_strbvcmp( "self", &bv ) == 0) {
|
||||||
|
return(strcasecmp(op->o_ndn, edn) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aci_strbvcmp( "group", &bv ) == 0) {
|
||||||
|
return(aci_group_member(&sdn, "groupOfNames", "member", be, e, op, edn, matches));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aci_strbvcmp( "role", &bv ) == 0) {
|
||||||
|
return(aci_group_member(&sdn, "organizationalRole", "roleOccupant", be, e, op, edn, matches));
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
#endif /* SLAPD_ACI_ENABLED */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
string_expand(
|
string_expand(
|
||||||
char *newbuf,
|
char *newbuf,
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,23 @@ parse_acl(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SLAPD_ACI_ENABLED
|
||||||
|
if ( strcasecmp( left, "aci" ) == 0 ) {
|
||||||
|
if( b->a_aci_at != NULL ) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"%s: line %d: aci attribute already specified.\n",
|
||||||
|
fname, lineno );
|
||||||
|
acl_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( right != NULL && *right != '\0' )
|
||||||
|
b->a_aci_at = ch_strdup( right );
|
||||||
|
else
|
||||||
|
b->a_aci_at = ch_strdup( SLAPD_ACI_DEFAULT_ATTR );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* get <access> */
|
/* get <access> */
|
||||||
if ( ACL_IS_INVALID(ACL_SET(b->a_access, str2access( left ))) ) {
|
if ( ACL_IS_INVALID(ACL_SET(b->a_access, str2access( left ))) ) {
|
||||||
fprintf( stderr,
|
fprintf( stderr,
|
||||||
|
|
@ -441,6 +458,9 @@ acl_usage( void )
|
||||||
"\t[group[/<objectclass>[/<attrname>]]=<regex>]\n"
|
"\t[group[/<objectclass>[/<attrname>]]=<regex>]\n"
|
||||||
"\t[peername=<regex>] [sockname=<regex>]\n"
|
"\t[peername=<regex>] [sockname=<regex>]\n"
|
||||||
"\t[domain=<regex>] [sockurl=<regex>]\n"
|
"\t[domain=<regex>] [sockurl=<regex>]\n"
|
||||||
|
#ifdef SLAPD_ACI_ENABLED
|
||||||
|
"\t[aci=<attrname>]\n"
|
||||||
|
#endif
|
||||||
"<access> ::= [self]{none|auth|compare|search|read|write}\n"
|
"<access> ::= [self]{none|auth|compare|search|read|write}\n"
|
||||||
);
|
);
|
||||||
exit( EXIT_FAILURE );
|
exit( EXIT_FAILURE );
|
||||||
|
|
@ -528,6 +548,12 @@ print_access( Access *b )
|
||||||
fprintf( stderr, " sockurl=%s", b->a_sockurl_pat );
|
fprintf( stderr, " sockurl=%s", b->a_sockurl_pat );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SLAPD_ACI_ENABLED
|
||||||
|
if ( b->a_aci_at != NULL ) {
|
||||||
|
fprintf( stderr, " aci=%s", b->a_aci_at );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fprintf( stderr, "\n" );
|
fprintf( stderr, "\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ AccessControl * acl_get_applicable LDAP_P(( Backend *be,
|
||||||
char *attr, int nmatches, regmatch_t *matches ));
|
char *attr, int nmatches, regmatch_t *matches ));
|
||||||
|
|
||||||
int acl_access_allowed LDAP_P((
|
int acl_access_allowed LDAP_P((
|
||||||
AccessControl *a, Backend *be, Connection *conn, Entry *e,
|
AccessControl *a, char *attr, Backend *be, Connection *conn, Entry *e,
|
||||||
struct berval *val, Operation *op, int access, char *edn,
|
struct berval *val, Operation *op, int access, char *edn,
|
||||||
regmatch_t *matches ));
|
regmatch_t *matches ));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -572,7 +572,7 @@ send_search_entry(
|
||||||
acl = acl_get_applicable( be, op, e, a->a_type,
|
acl = acl_get_applicable( be, op, e, a->a_type,
|
||||||
MAXREMATCHES, matches );
|
MAXREMATCHES, matches );
|
||||||
|
|
||||||
if ( ! acl_access_allowed( acl, be, conn, e,
|
if ( ! acl_access_allowed( acl, a->a_type, be, conn, e,
|
||||||
NULL, op, ACL_READ, edn, matches ) )
|
NULL, op, ACL_READ, edn, matches ) )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -589,7 +589,7 @@ send_search_entry(
|
||||||
if ( ! attrsonly ) {
|
if ( ! attrsonly ) {
|
||||||
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
|
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
|
||||||
if ( a->a_syntax & SYNTAX_DN &&
|
if ( a->a_syntax & SYNTAX_DN &&
|
||||||
! acl_access_allowed( acl, be, conn, e, a->a_vals[i], op,
|
! acl_access_allowed( acl, a->a_type, be, conn, e, a->a_vals[i], op,
|
||||||
ACL_READ, edn, matches) )
|
ACL_READ, edn, matches) )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -647,7 +647,7 @@ send_search_entry(
|
||||||
acl = acl_get_applicable( be, op, e, a->a_type,
|
acl = acl_get_applicable( be, op, e, a->a_type,
|
||||||
MAXREMATCHES, matches );
|
MAXREMATCHES, matches );
|
||||||
|
|
||||||
if ( ! acl_access_allowed( acl, be, conn, e,
|
if ( ! acl_access_allowed( acl, a->a_type, be, conn, e,
|
||||||
NULL, op, ACL_READ, edn, matches ) )
|
NULL, op, ACL_READ, edn, matches ) )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -664,7 +664,7 @@ send_search_entry(
|
||||||
if ( ! attrsonly ) {
|
if ( ! attrsonly ) {
|
||||||
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
|
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
|
||||||
if ( a->a_syntax & SYNTAX_DN &&
|
if ( a->a_syntax & SYNTAX_DN &&
|
||||||
! acl_access_allowed( acl, be, conn, e, a->a_vals[i], op,
|
! acl_access_allowed( acl, a->a_type, be, conn, e, a->a_vals[i], op,
|
||||||
ACL_READ, edn, matches) )
|
ACL_READ, edn, matches) )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,8 @@ LDAP_BEGIN_DECL
|
||||||
#define SLAP_SCHERR_SYN_NOT_FOUND 11
|
#define SLAP_SCHERR_SYN_NOT_FOUND 11
|
||||||
#define SLAP_SCHERR_MR_INCOMPLETE 12
|
#define SLAP_SCHERR_MR_INCOMPLETE 12
|
||||||
|
|
||||||
|
#define SLAPD_ACI_DEFAULT_ATTR "aci"
|
||||||
|
|
||||||
extern int slap_debug;
|
extern int slap_debug;
|
||||||
|
|
||||||
struct slap_op;
|
struct slap_op;
|
||||||
|
|
@ -271,6 +273,10 @@ typedef struct slap_access {
|
||||||
char *a_domain_pat;
|
char *a_domain_pat;
|
||||||
char *a_sockurl_pat;
|
char *a_sockurl_pat;
|
||||||
|
|
||||||
|
#ifdef SLAPD_ACI_ENABLED
|
||||||
|
char *a_aci_at;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ACL Groups */
|
/* ACL Groups */
|
||||||
char *a_group_pat;
|
char *a_group_pat;
|
||||||
char *a_group_oc;
|
char *a_group_oc;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue