X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Facl.c;h=fd40a97687db31fbd97d856b4ca4c7d642607ac3;hb=ae63be3894c799771d0ccabec1e376c7478cd263;hp=628adee7b8d0111bf76eacce7249ce4c7d2d6363;hpb=3350957674b6173217371f6ae289f29a7158b5c7;p=openldap diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 628adee7b8..fd40a97687 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -19,43 +19,29 @@ static AccessControl * acl_get( AccessControl *ac, int *count, Backend *be, Operation *op, Entry *e, -#ifdef SLAPD_SCHEMA_NOT_COMPAT AttributeDescription *desc, -#else - const char *attr, -#endif int nmatches, regmatch_t *matches ); static slap_control_t acl_mask( AccessControl *ac, slap_access_mask_t *mask, Backend *be, Connection *conn, Operation *op, Entry *e, -#ifdef SLAPD_SCHEMA_NOT_COMPAT AttributeDescription *desc, -#else - const char *attr, -#endif struct berval *val, regmatch_t *matches ); #ifdef SLAPD_ACI_ENABLED static int aci_mask( Backend *be, + Connection *conn, Operation *op, Entry *e, -#ifdef SLAPD_SCHEMA_NOT_COMPAT AttributeDescription *desc, -#else - const char *attr, -#endif - struct berval *val, struct berval *aci, - regmatch_t *matches, slap_access_t *grant, slap_access_t *deny ); - -char *supportedACIMechs[] = { - "1.3.6.1.4.1.4203.666.7.1", /* experimental IETF aci family */ - "1.3.6.1.4.1.4203.666.7.2", /* experimental OpenLDAP aci family */ - NULL -}; + struct berval *val, + struct berval *aci, + regmatch_t *matches, + slap_access_t *grant, + slap_access_t *deny ); #endif static int regex_matches( @@ -86,11 +72,7 @@ access_allowed( Connection *conn, Operation *op, Entry *e, -#ifdef SLAPD_SCHEMA_NOT_COMPAT - AttributeDescription *attr, -#else - const char *attr, -#endif + AttributeDescription *desc, struct berval *val, slap_access_t access ) { @@ -102,6 +84,8 @@ access_allowed( slap_access_mask_t mask; slap_control_t control; + const char *attr = desc ? desc->ad_cname->bv_val : NULL; + regmatch_t matches[MAXREMATCHES]; Debug( LDAP_DEBUG_ACL, @@ -127,11 +111,7 @@ access_allowed( * by ACL_WRITE checking as any found here are not provided * by the user */ -#ifdef SLAPD_SCHEMA_NOT_COMPAT - if ( access >= ACL_WRITE && is_at_no_user_mod( attr->ad_type ) ) -#else - if ( access >= ACL_WRITE && oc_check_op_no_usermod_attr( attr ) ) -#endif + if ( access >= ACL_WRITE && is_at_no_user_mod( desc->ad_type ) ) { Debug( LDAP_DEBUG_ACL, "NoUserMod Operational attribute:" " %s access granted\n", @@ -162,13 +142,13 @@ access_allowed( } ACL_INIT(mask); - memset(matches, 0, sizeof(matches)); + memset(matches, '\0', sizeof(matches)); control = ACL_BREAK; a = NULL; count = 0; - while( a = acl_get( a, &count, be, op, e, attr, MAXREMATCHES, matches ) ) + while( a = acl_get( a, &count, be, op, e, desc, MAXREMATCHES, matches ) ) { int i; @@ -186,13 +166,13 @@ access_allowed( } control = acl_mask( a, &mask, be, conn, op, - e, attr, val, matches ); + e, desc, val, matches ); if ( control != ACL_BREAK ) { break; } - memset(matches, 0, sizeof(matches)); + memset(matches, '\0', sizeof(matches)); } if ( ACL_IS_INVALID( mask ) ) { @@ -229,18 +209,18 @@ acl_get( Backend *be, Operation *op, Entry *e, -#ifdef SLAPD_SCHEMA_NOT_COMPAT AttributeDescription *desc, -#else - const char *desc, -#endif int nmatch, regmatch_t *matches ) { const char *attr; + int dnlen, patlen; + assert( e != NULL ); assert( count != NULL ); + attr = desc ? desc->ad_cname->bv_val : NULL; + if( a == NULL ) { if( be == NULL ) { a = global_acl; @@ -254,26 +234,67 @@ acl_get( a = a->acl_next; } -#ifdef SLAPD_SCHEMA_NOT_COMPAT - attr = desc->ad_cname->bv_val; -#else - attr = desc; -#endif + dnlen = strlen(e->e_ndn); for ( ; a != NULL; a = a->acl_next ) { (*count) ++; if (a->acl_dn_pat != NULL) { - Debug( LDAP_DEBUG_ACL, "=> dnpat: [%d] %s nsub: %d\n", - *count, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub ); + if ( a->acl_dn_style == ACL_STYLE_REGEX ) { + Debug( LDAP_DEBUG_ACL, "=> dnpat: [%d] %s nsub: %d\n", + *count, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub ); - if (regexec(&a->acl_dn_re, e->e_ndn, nmatch, matches, 0)) { - continue; + if (regexec(&a->acl_dn_re, e->e_ndn, nmatch, matches, 0)) + continue; } else { - Debug( LDAP_DEBUG_ACL, "=> acl_get: [%d] matched\n", - *count, 0, 0); + Debug( LDAP_DEBUG_ACL, "=> dn: [%d] %s\n", + *count, a->acl_dn_pat, 0 ); + + patlen = strlen( a->acl_dn_pat ); + if ( dnlen < patlen ) + continue; + + if ( a->acl_dn_style == ACL_STYLE_BASE ) { + /* base dn -- entire object DN must match */ + if ( dnlen != patlen ) + continue; + + } else if ( a->acl_dn_style == ACL_STYLE_ONE ) { + char *rdn; + int rdnlen = -1; + + if ( dnlen <= patlen ) + continue; + + if ( e->e_ndn[dnlen - patlen - 1] != ',' ) + continue; + + rdn = dn_rdn( NULL, e->e_ndn ); + if ( rdn != NULL ) { + rdnlen = strlen( rdn ); + ch_free( rdn ); + } + if ( rdnlen != dnlen - patlen - 1 ) + continue; + + } else if ( a->acl_dn_style == ACL_STYLE_SUBTREE ) { + if ( dnlen > patlen && e->e_ndn[dnlen - patlen - 1] != ',' ) + continue; + + } else if ( a->acl_dn_style == ACL_STYLE_CHILDREN ) { + if ( dnlen <= patlen ) + continue; + if ( e->e_ndn[dnlen - patlen - 1] != ',' ) + continue; + } + + if ( strcmp( a->acl_dn_pat, e->e_ndn + dnlen - patlen ) != 0 ) + continue; } + + Debug( LDAP_DEBUG_ACL, "=> acl_get: [%d] matched\n", + *count, 0, 0 ); } if ( a->acl_filter != NULL ) { @@ -319,20 +340,17 @@ acl_mask( Connection *conn, Operation *op, Entry *e, -#ifdef SLAPD_SCHEMA_NOT_COMPAT - AttributeDescription *attr, -#else - const char *attr, -#endif + AttributeDescription *desc, struct berval *val, regmatch_t *matches ) { - int i; + int i, odnlen, patlen; Access *b; #ifdef LDAP_DEBUG char accessmaskbuf[ACCESSMASK_MAXLEN]; #endif + const char *attr = desc ? desc->ad_cname->bv_val : NULL; assert( a != NULL ); assert( mask != NULL ); @@ -380,13 +398,62 @@ acl_mask( continue; } - } else if ( strcmp( b->a_dn_pat, "*" ) != 0 ) { - int ret = regex_matches( b->a_dn_pat, - op->o_ndn, e->e_ndn, matches ); + } else if ( b->a_dn_style == ACL_STYLE_REGEX ) { + if ( strcmp( b->a_dn_pat, "*" ) != 0 ) { + int ret = regex_matches( b->a_dn_pat, + op->o_ndn, e->e_ndn, matches ); + + if( ret == 0 ) { + continue; + } + } + + } else { + if ( e->e_dn == NULL ) + continue; - if( ret == 0 ) { + patlen = strlen( b->a_dn_pat ); + odnlen = strlen( op->o_ndn ); + if ( odnlen < patlen ) continue; + + if ( b->a_dn_style == ACL_STYLE_BASE ) { + /* base dn -- entire object DN must match */ + if ( odnlen != patlen ) + continue; + + } else if ( b->a_dn_style == ACL_STYLE_ONE ) { + char *rdn; + int rdnlen = -1; + + if ( odnlen <= patlen ) + continue; + + if ( op->o_ndn[odnlen - patlen - 1] != ',' ) + continue; + + rdn = dn_rdn( NULL, op->o_ndn ); + if ( rdn != NULL ) { + rdnlen = strlen( rdn ); + ch_free( rdn ); + } + if ( rdnlen != odnlen - patlen - 1 ) + continue; + + } else if ( b->a_dn_style == ACL_STYLE_SUBTREE ) { + if ( odnlen > patlen && op->o_ndn[odnlen - patlen - 1] != ',' ) + continue; + + } else if ( b->a_dn_style == ACL_STYLE_CHILDREN ) { + if ( odnlen <= patlen ) + continue; + if ( op->o_ndn[odnlen - patlen - 1] != ',' ) + continue; } + + if ( strcmp( b->a_dn_pat, op->o_ndn + odnlen - patlen ) != 0 ) + continue; + } } @@ -394,11 +461,17 @@ acl_mask( Debug( LDAP_DEBUG_ACL, "<= check a_sockurl_pat: %s\n", b->a_sockurl_pat, 0, 0 ); - if ( strcmp( b->a_sockurl_pat, "*" ) != 0 && - !regex_matches( b->a_sockurl_pat, conn->c_listener_url, - e->e_ndn, matches ) ) - { - continue; + if ( strcmp( b->a_sockurl_pat, "*" ) != 0) { + if ( b->a_sockurl_style == ACL_STYLE_REGEX) { + if (!regex_matches( b->a_sockurl_pat, conn->c_listener_url, + e->e_ndn, matches ) ) + { + continue; + } + } else { + if ( strcasecmp( b->a_sockurl_pat, conn->c_listener_url ) == 0 ) + continue; + } } } @@ -406,11 +479,17 @@ acl_mask( Debug( LDAP_DEBUG_ACL, "<= check a_domain_pat: %s\n", b->a_domain_pat, 0, 0 ); - if ( strcmp( b->a_domain_pat, "*" ) != 0 && - !regex_matches( b->a_domain_pat, conn->c_peer_domain, - e->e_ndn, matches ) ) - { - continue; + if ( strcmp( b->a_domain_pat, "*" ) != 0) { + if ( b->a_domain_style == ACL_STYLE_REGEX) { + if (!regex_matches( b->a_domain_pat, conn->c_peer_domain, + e->e_ndn, matches ) ) + { + continue; + } + } else { + if ( strcasecmp( b->a_domain_pat, conn->c_peer_domain ) == 0 ) + continue; + } } } @@ -418,11 +497,17 @@ acl_mask( Debug( LDAP_DEBUG_ACL, "<= check a_peername_path: %s\n", b->a_peername_pat, 0, 0 ); - if ( strcmp( b->a_peername_pat, "*" ) != 0 && - !regex_matches( b->a_peername_pat, conn->c_peer_name, - e->e_ndn, matches ) ) - { - continue; + if ( strcmp( b->a_peername_pat, "*" ) != 0) { + if ( b->a_peername_style == ACL_STYLE_REGEX) { + if (!regex_matches( b->a_peername_pat, conn->c_peer_name, + e->e_ndn, matches ) ) + { + continue; + } + } else { + if ( strcasecmp( b->a_peername_pat, conn->c_peer_name ) == 0 ) + continue; + } } } @@ -430,52 +515,82 @@ acl_mask( Debug( LDAP_DEBUG_ACL, "<= check a_sockname_path: %s\n", b->a_sockname_pat, 0, 0 ); - if ( strcmp( b->a_sockname_pat, "*" ) != 0 && - !regex_matches( b->a_sockname_pat, conn->c_sock_name, - e->e_ndn, matches ) ) - { - continue; + if ( strcmp( b->a_sockname_pat, "*" ) != 0) { + if ( b->a_sockname_style == ACL_STYLE_REGEX) { + if (!regex_matches( b->a_sockname_pat, conn->c_sock_name, + e->e_ndn, matches ) ) + { + continue; + } + } else { + if ( strcasecmp( b->a_sockname_pat, conn->c_sock_name ) == 0 ) + continue; + } } } if ( b->a_dn_at != NULL && op->o_ndn != NULL ) { Attribute *at; struct berval bv; + int rc, match = 0; + const char *text; + const char *desc = b->a_dn_at->ad_cname->bv_val; Debug( LDAP_DEBUG_ACL, "<= check a_dn_at: %s\n", - b->a_dn_at, 0, 0); + desc, 0, 0); bv.bv_val = op->o_ndn; bv.bv_len = strlen( bv.bv_val ); /* see if asker is listed in dnattr */ -#ifdef SLAPD_SCHEMA_NOT_COMPAT for( at = attrs_find( e->e_attrs, b->a_dn_at ); - at == NULL; - at = attrs_find( e->e_attrs->a_next, b->a_dn_at ) ) + at != NULL; + at = attrs_find( at->a_next, b->a_dn_at ) ) { if( value_find( b->a_dn_at, at->a_vals, &bv ) == 0 ) { + /* found it */ + match = 1; + break; } } -#else - /* see if asker is listed in dnattr */ - if ( (at = attr_find( e->e_attrs, b->a_dn_at )) != NULL && - value_find( at->a_vals, &bv, at->a_syntax, 3 ) == 0 ) - { - if ( b->a_dn_self && (val == NULL - || value_cmp( &bv, val, at->a_syntax, 2 ) ) ) - { - continue; + if( match ) { + /* 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, + val, &bv, &text ); + /* on match error or no match, fail the ACL clause */ + if (rc != LDAP_SUCCESS || match != 0 ) + continue; } - - /* asker not listed in dnattr - check for self access */ - } else if ( ! b->a_dn_self || val == NULL - || value_cmp( &bv, val, at->a_syntax, 2 ) != 0 ) - { - 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, + val, &bv, &text ); + /* on match error or no match, fail the ACL clause */ + if (rc != LDAP_SUCCESS || match != 0 ) + continue; } -#endif } if ( b->a_group_pat != NULL && op->o_ndn != NULL ) { @@ -486,10 +601,15 @@ acl_mask( * the values in the attribute group */ /* see if asker is listed in dnattr */ - 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 */ - continue; + 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 */ + continue; + } + } else { + strncpy( buf, b->a_group_pat, sizeof(buf) - 1 ); + buf[sizeof(buf) - 1] = 0; } if (backend_group(be, e, buf, op->o_ndn, @@ -539,8 +659,8 @@ acl_mask( * rights given by the acis. */ for ( i = 0; at->a_vals[i] != NULL; i++ ) { - if (aci_mask( be, op, - e, attr, val, at->a_vals[i], + if (aci_mask( be, conn, op, + e, desc, val, at->a_vals[i], matches, &grant, &deny ) != 0) { tgrant |= grant; @@ -690,21 +810,12 @@ acl_check_modlist( * by ACL_WRITE checking as any found here are not provided * by the user */ -#ifdef SLAPD_SCHEMA_NOT_COMPAT if ( is_at_no_user_mod( mlist->sml_desc->ad_type ) ) { Debug( LDAP_DEBUG_ACL, "acl: no-user-mod %s:" " modify access granted\n", mlist->sml_desc->ad_cname->bv_val, 0, 0 ); continue; } -#else - if ( oc_check_op_no_usermod_attr( mlist->sml_type ) ) { - Debug( LDAP_DEBUG_ACL, "acl: no-user-mod %s:" - " modify access granted\n", - mlist->sml_type, 0, 0 ); - continue; - } -#endif switch ( mlist->sml_op ) { case LDAP_MOD_REPLACE: @@ -984,14 +1095,9 @@ aci_group_member ( char *subjdn, *grpdn = NULL; char *grpoc; char *grpat; -#ifdef SLAPD_SCHEMA_NOT_COMPAT ObjectClass *grp_oc = NULL; AttributeDescription *grp_ad = NULL; char *text; -#else - char *grp_oc; - char *grp_ad; -#endif int rc; /* format of string is "group/objectClassValue/groupAttrName" */ @@ -1016,17 +1122,14 @@ aci_group_member ( grpat = aci_bvstrdup(&bv); } -#ifdef SLAPD_SCHEMA_NOT_COMPAT rc = slap_str2ad( grpat, &grp_ad, &text ); if( rc != LDAP_SUCCESS ) { rc = 0; goto done; } -#else - grp_ad = grpat; -#endif rc = 0; + grp_oc = oc_find( grpoc ); grpdn = (char *)ch_malloc(1024); if (grp_oc != NULL && grp_ad != NULL && grpdn != NULL) { @@ -1036,10 +1139,8 @@ aci_group_member ( } } -#ifdef SLAPD_SCHEMA_NOT_COMPAT done: if( grp_ad != NULL ) ad_free( grp_ad, 1 ); -#endif ch_free(grpdn); ch_free(grpat); ch_free(grpoc); @@ -1050,13 +1151,10 @@ done: static int aci_mask( Backend *be, + Connection *conn, Operation *op, Entry *e, -#ifdef SLAPD_SCHEMA_NOT_COMPAT AttributeDescription *desc, -#else - const char *attr, -#endif struct berval *val, struct berval *aci, regmatch_t *matches, @@ -1066,10 +1164,8 @@ aci_mask( { struct berval bv, perms, sdn; char *subjdn; - int rc, i; -#ifdef SLAPD_SCHEMA_NOT_COMPAT - char *attr; -#endif + int rc; + char *attr = desc->ad_cname->bv_val; /* parse an aci of the form: oid#scope#action;rights;attr;rights;attr$action;rights;attr;rights;attr#dnType#subjectDN @@ -1087,12 +1183,6 @@ aci_mask( /* check that the aci family is supported */ if (aci_get_part(aci, 0, '#', &bv) < 0) return(0); - for (i = 0; supportedACIMechs[i] != NULL; i++) { - if (aci_strbvcmp( supportedACIMechs[i], &bv ) == 0) - break; - } - if (supportedACIMechs[i] == NULL) - return(0); /* check that the scope is "entry" */ if (aci_get_part(aci, 1, '#', &bv) < 0 @@ -1134,7 +1224,6 @@ aci_mask( } else if (aci_strbvcmp( "dnattr", &bv ) == 0) { char *dnattr = aci_bvstrdup(&sdn); -#ifdef SLAPD_SCHEMA_NOT_COMPAT Attribute *at; AttributeDescription *ad = NULL; const char *text; @@ -1164,19 +1253,6 @@ aci_mask( ad_free( ad, 1 ); return rc; -#else - Attribute *at; - at = attr_find( e->e_attrs, dnattr ); - ch_free( dnattr ); - - if (at != NULL) { - bv.bv_val = op->o_ndn; - bv.bv_len = strlen( bv.bv_val ); - - if (value_find( at->a_vals, &bv, at->a_syntax, 3 ) == 0 ) - return(1); - } -#endif } else if (aci_strbvcmp( "group", &bv ) == 0) { if (aci_group_member(&sdn, SLAPD_GROUP_CLASS, SLAPD_GROUP_ATTR, be, e, op, matches)) @@ -1185,20 +1261,12 @@ aci_mask( } else if (aci_strbvcmp( "role", &bv ) == 0) { if (aci_group_member(&sdn, SLAPD_ROLE_CLASS, SLAPD_ROLE_ATTR, be, e, op, matches)) return(1); + } return(0); } -char * -get_supported_acimech( - int index ) -{ - if (index < 0 || index >= (sizeof(supportedACIMechs) / sizeof(char *))) - return(NULL); - return(supportedACIMechs[index]); -} - #endif /* SLAPD_ACI_ENABLED */ static void