X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Facl.c;h=7b5d30bff6dbeab941499291d6a038abff3e9232;hb=ba37cbc233a791cde63b4e9e08b8fb5e95963ba4;hp=562eb18d55dfb510d12deb7e6971c4cdffc28433;hpb=0c6b9ce2ddf49a3337c967c4bf07134237db1724;p=openldap diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 562eb18d55..7b5d30bff6 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -14,6 +14,7 @@ #include #include "slap.h" +#include "sets.h" static AccessControl * acl_get( AccessControl *ac, int *count, @@ -23,7 +24,7 @@ static AccessControl * acl_get( int nmatches, regmatch_t *matches ); static slap_control_t acl_mask( - AccessControl *ac, slap_access_mask_t *mask, + AccessControl *ac, slap_mask_t *mask, Backend *be, Connection *conn, Operation *op, Entry *e, AttributeDescription *desc, @@ -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 @@ -81,7 +85,7 @@ access_allowed( #ifdef LDAP_DEBUG char accessmaskbuf[ACCESSMASK_MAXLEN]; #endif - slap_access_mask_t mask; + slap_mask_t mask; slap_control_t control; const char *attr = desc ? desc->ad_cname->bv_val : NULL; @@ -111,7 +115,9 @@ access_allowed( * by ACL_WRITE checking as any found here are not provided * by the user */ - if ( access >= ACL_WRITE && is_at_no_user_mod( desc->ad_type ) ) + if ( access >= ACL_WRITE && is_at_no_user_mod( desc->ad_type ) + && desc != slap_schema.si_ad_entry + && desc != slap_schema.si_ad_children ) { Debug( LDAP_DEBUG_ACL, "NoUserMod Operational attribute:" " %s access granted\n", @@ -148,7 +154,7 @@ access_allowed( a = NULL; count = 0; - while( a = acl_get( a, &count, be, op, e, desc, MAXREMATCHES, matches ) ) + while((a = acl_get( a, &count, be, op, e, desc, MAXREMATCHES, matches )) != NULL) { int i; @@ -335,7 +341,7 @@ acl_get( static slap_control_t acl_mask( AccessControl *a, - slap_access_mask_t *mask, + slap_mask_t *mask, Backend *be, Connection *conn, Operation *op, @@ -360,13 +366,13 @@ acl_mask( e->e_dn, attr, 0 ); Debug( LDAP_DEBUG_ACL, - "=> acl_mask: to value \"%s\" by \"%s\", (%s) \n", - val ? val->bv_val : "*", + "=> acl_mask: to %s by \"%s\", (%s) \n", + val ? "value" : "all values", op->o_ndn ? op->o_ndn : "", accessmask2str( *mask, accessmaskbuf ) ); for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) { - slap_access_mask_t oldmask, modmask; + slap_mask_t oldmask, modmask; ACL_INVALIDATE( modmask ); @@ -532,7 +538,7 @@ acl_mask( if ( b->a_dn_at != NULL && op->o_ndn != NULL ) { Attribute *at; struct berval bv; - int match; + int rc, match = 0; const char *text; const char *desc = b->a_dn_at->ad_cname->bv_val; @@ -555,21 +561,42 @@ acl_mask( } if( match ) { - if ( b->a_dn_self && (val == NULL - || value_match( &match, b->a_dn_at, - b->a_dn_at->ad_type->sat_equality, val, &bv, &text ) ) - != LDAP_SUCCESS - || match ) - { - continue; + /* have a dnattr match. if this is a self clause then + * the target must also match the op dn. + */ + if ( b->a_dn_self ) { + /* check if the target is an attribute. */ + if ( val == NULL ) + continue; + /* target is attribute, check if the attribute value + * is the op dn. + */ + rc = value_match( &match, b->a_dn_at, + b->a_dn_at->ad_type->sat_equality, 0, + val, &bv, &text ); + /* on match error or no match, fail the ACL clause */ + if (rc != LDAP_SUCCESS || match != 0 ) + continue; } - } else if ( ! b->a_dn_self || val == NULL - || value_match( &match, b->a_dn_at, - b->a_dn_at->ad_type->sat_equality, val, &bv, &text ) - != LDAP_SUCCESS - || match ) - { - continue; + } else { + /* no dnattr match, check if this is a self clause */ + if ( ! b->a_dn_self ) + continue; + /* this is a self clause, check if the target is an + * attribute. + */ + if ( val == NULL ) + continue; + /* target is attribute, check if the attribute value + * is the op dn. + */ + rc = value_match( &match, b->a_dn_at, + b->a_dn_at->ad_type->sat_equality, 0, + val, &bv, &text ); + + /* on match error or no match, fail the ACL clause */ + if (rc != LDAP_SUCCESS || match != 0 ) + continue; } } @@ -581,7 +608,7 @@ acl_mask( * the values in the attribute group */ /* see if asker is listed in dnattr */ - if ( b->a_group_style != ACL_STYLE_REGEX ) { + if ( b->a_group_style == ACL_STYLE_REGEX ) { string_expand(buf, sizeof(buf), b->a_group_pat, e->e_ndn, matches); if ( dn_normalize(buf) == NULL ) { /* did not expand to a valid dn */ @@ -592,13 +619,62 @@ acl_mask( buf[sizeof(buf) - 1] = 0; } - if (backend_group(be, e, buf, op->o_ndn, + if (backend_group(be, conn, op, e, buf, op->o_ndn, b->a_group_oc, b->a_group_at) != 0) { continue; } } + 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; + } + } + + if ( b->a_authz.sai_ssf ) { + Debug( LDAP_DEBUG_ACL, "<= check a_authz.sai_ssf: ACL %u > OP %u\n", + b->a_authz.sai_ssf, op->o_ssf, 0 ); + + if ( b->a_authz.sai_ssf > op->o_ssf ) { + continue; + } + } + + if ( b->a_authz.sai_transport_ssf ) { + Debug( LDAP_DEBUG_ACL, + "<= check a_authz.sai_transport_ssf: ACL %u > OP %u\n", + b->a_authz.sai_transport_ssf, op->o_transport_ssf, 0 ); + + if ( b->a_authz.sai_transport_ssf > op->o_transport_ssf ) { + continue; + } + } + + if ( b->a_authz.sai_tls_ssf ) { + Debug( LDAP_DEBUG_ACL, + "<= check a_authz.sai_tls_ssf: ACL %u > OP %u\n", + b->a_authz.sai_tls_ssf, op->o_tls_ssf, 0 ); + + if ( b->a_authz.sai_tls_ssf > op->o_tls_ssf ) { + continue; + } + } + + if ( b->a_authz.sai_sasl_ssf ) { + Debug( LDAP_DEBUG_ACL, + "<= check a_authz.sai_sasl_ssf: ACL %u > OP %u\n", + b->a_authz.sai_sasl_ssf, op->o_sasl_ssf, 0 ); + + if ( b->a_authz.sai_sasl_ssf > op->o_sasl_ssf ) { + continue; + } + } + #ifdef SLAPD_ACI_ENABLED if ( b->a_aci_at != NULL ) { Attribute *at; @@ -606,7 +682,7 @@ acl_mask( /* this case works different from the others above. * since aci's themselves give permissions, we need - * to first check b->a_mask, the ACL's access level. + * to first check b->a_access_mask, the ACL's access level. */ if( op->o_ndn == NULL || op->o_ndn[0] == '\0' ) { @@ -620,7 +696,7 @@ acl_mask( /* first check if the right being requested * is allowed by the ACL clause. */ - if ( ! ACL_GRANT( b->a_mask, *mask ) ) { + if ( ! ACL_GRANT( b->a_access_mask, *mask ) ) { continue; } @@ -649,7 +725,7 @@ acl_mask( } /* remove anything that the ACL clause does not allow */ - tgrant &= b->a_mask & ACL_PRIV_MASK; + tgrant &= b->a_access_mask & ACL_PRIV_MASK; tdeny &= ACL_PRIV_MASK; /* see if we have anything to contribute */ @@ -678,7 +754,7 @@ acl_mask( } else #endif { - modmask = b->a_mask; + modmask = b->a_access_mask; } @@ -835,7 +911,6 @@ acl_check_modlist( return( 1 ); } -#ifdef SLAPD_ACI_ENABLED static char * aci_bvstrdup( struct berval *bv ) { @@ -843,7 +918,7 @@ aci_bvstrdup( struct berval *bv ) s = (char *)ch_malloc(bv->bv_len + 1); if (s != NULL) { - memcpy(s, bv->bv_val, bv->bv_len); + AC_MEMCPY(s, bv->bv_val, bv->bv_len); s[bv->bv_len] = 0; } return(s); @@ -906,6 +981,126 @@ aci_get_part( return(bv->bv_len); } +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) { + const char *text; + AttributeDescription *desc = NULL; + if (slap_str2ad(attr, &desc, &text) == LDAP_SUCCESS) { + 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; + const 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) == LDAP_SUCCESS ) + { + 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); +} + +#ifdef SLAPD_ACI_ENABLED static int aci_list_map_rights( struct berval *list ) @@ -1067,6 +1262,7 @@ aci_group_member ( const char *defgrpat, Backend *be, Entry *e, + Connection *conn, Operation *op, regmatch_t *matches ) @@ -1115,7 +1311,7 @@ aci_group_member ( if (grp_oc != NULL && grp_ad != NULL && grpdn != NULL) { string_expand(grpdn, 1024, subjdn, e->e_ndn, matches); if ( dn_normalize(grpdn) != NULL ) { - rc = (backend_group(be, e, grpdn, op->o_ndn, grp_oc, grp_ad) == 0); + rc = (backend_group(be, conn, op, e, grpdn, op->o_ndn, grp_oc, grp_ad) == 0); } } @@ -1235,11 +1431,19 @@ aci_mask( } else if (aci_strbvcmp( "group", &bv ) == 0) { - if (aci_group_member(&sdn, SLAPD_GROUP_CLASS, SLAPD_GROUP_ATTR, be, e, op, matches)) + if (aci_group_member(&sdn, SLAPD_GROUP_CLASS, SLAPD_GROUP_ATTR, be, e, conn, op, matches)) return(1); } else if (aci_strbvcmp( "role", &bv ) == 0) { - if (aci_group_member(&sdn, SLAPD_ROLE_CLASS, SLAPD_ROLE_ATTR, be, e, op, matches)) + if (aci_group_member(&sdn, SLAPD_ROLE_CLASS, SLAPD_ROLE_ATTR, be, e, conn, 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); }