X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Facl.c;h=d523a5aa0e0107783a847b72dbbd0e9d30d1b135;hb=01c38dd6ea7f02cfdc9f77f9299771a4ef6ce968;hp=886bc745fc6f0c10e46cd3360713b13cbefdffd7;hpb=e1d1d3240208531466ae8ac1aca240b474499f73;p=openldap diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 886bc745fc..d523a5aa0e 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -40,6 +40,9 @@ #define ACL_BUF_SIZE 1024 /* use most appropriate size */ static const struct berval acl_bv_ip_eq = BER_BVC( "IP=" ); +#ifdef LDAP_PF_INET6 +static const struct berval acl_bv_ipv6_eq = BER_BVC( "IP=[" ); +#endif /* LDAP_PF_INET6 */ #ifdef LDAP_PF_LOCAL static const struct berval acl_bv_path_eq = BER_BVC("PATH="); #endif /* LDAP_PF_LOCAL */ @@ -134,7 +137,6 @@ slap_access_allowed( slap_access_t access_level; const char *attr; regmatch_t matches[MAXREMATCHES]; - int st_same_attr = 0; assert( op != NULL ); assert( e != NULL ); @@ -198,24 +200,17 @@ slap_access_allowed( ret = 0; control = ACL_BREAK; - if ( st_same_attr ) { - assert( state->as_vd_acl != NULL ); - + if ( state && state->as_vd_ad == desc ) { a = state->as_vd_acl; count = state->as_vd_acl_count; - if ( !ACL_IS_INVALID( state->as_vd_acl_mask ) ) { - mask = state->as_vd_acl_mask; - AC_MEMCPY( matches, state->as_vd_acl_matches, sizeof(matches) ); - goto vd_access; - } } else { if ( state ) state->as_vi_acl = NULL; a = NULL; - ACL_PRIV_ASSIGN( mask, *maskp ); count = 0; - memset( matches, '\0', sizeof( matches ) ); } + ACL_PRIV_ASSIGN( mask, *maskp ); + memset( matches, '\0', sizeof( matches ) ); while ( ( a = slap_acl_get( a, &count, op, e, desc, val, MAXREMATCHES, matches, state ) ) != NULL ) @@ -250,7 +245,6 @@ slap_access_allowed( } } -vd_access: control = slap_acl_mask( a, &mask, op, e, desc, val, MAXREMATCHES, matches, count, state ); @@ -340,7 +334,6 @@ access_allowed_mask( slap_mask_t mask; slap_access_t access_level; const char *attr; - int st_same_attr = 0; static AccessControlState state_init = ACL_STATE_INIT; assert( e != NULL ); @@ -363,7 +356,7 @@ access_allowed_mask( { access = ACL_AUTH; - } else if ( get_manageDIT( op ) && access_level == ACL_WRITE && + } else if ( get_relax( op ) && access_level == ACL_WRITE && desc == slap_schema.si_ad_entry ) { access = ACL_MANAGE; @@ -377,17 +370,10 @@ access_allowed_mask( { 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; } Debug( LDAP_DEBUG_ACL, @@ -403,14 +389,12 @@ access_allowed_mask( op->o_bd = LDAP_STAILQ_FIRST( &backendDB ); be_null = 1; -#ifdef LDAP_DEVEL - /* - * FIXME: experimental; use first backend rules - * iff there is no global_acl (ITS#3100) */ + /* FIXME: experimental; use first backend rules + * iff there is no global_acl (ITS#3100) + */ if ( frontendDB->be_acl != NULL ) { op->o_bd = frontendDB; } -#endif /* LDAP_DEVEL */ } assert( op->o_bd != NULL ); @@ -455,6 +439,7 @@ done: state->as_result = ret; } state->as_recorded |= ACL_STATE_RECORDED; + state->as_vd_ad = desc; } if ( be_null ) op->o_bd = NULL; if ( maskp ) ACL_PRIV_ASSIGN( *maskp, mask ); @@ -509,7 +494,7 @@ slap_acl_get( dnlen = e->e_nname.bv_len; - for ( ; a != NULL; a = a->acl_next ) { + for ( ; a != NULL; prev = a, a = a->acl_next ) { (*count) ++; if ( a->acl_dn_pat.bv_len || ( a->acl_dn_style != ACL_STYLE_REGEX )) { @@ -580,11 +565,8 @@ slap_acl_get( if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) { state->as_recorded |= ACL_STATE_RECORDED_VD; - state->as_vd_acl = a; - state->as_vd_acl_count = *count; - state->as_vd_access = a->acl_access; - state->as_vd_access_count = 1; - ACL_INVALIDATE( state->as_vd_acl_mask ); + state->as_vd_acl = prev; + state->as_vd_acl_count = *count - 1; } if ( a->acl_attrval_style == ACL_STYLE_REGEX ) { @@ -674,11 +656,7 @@ slap_acl_get( if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) { \ state->as_recorded |= ACL_STATE_RECORDED_VD; \ state->as_vd_acl = a; \ - AC_MEMCPY( state->as_vd_acl_matches, matches, \ - sizeof( state->as_vd_acl_matches )) ; \ state->as_vd_acl_count = count; \ - state->as_vd_access = b; \ - state->as_vd_access_count = i; \ } \ } while( 0 ) @@ -703,7 +681,7 @@ acl_mask_dn( * NOTE: styles "anonymous", "users" and "self" * have been moved to enum slap_style_t, whose * value is set in a_dn_style; however, the string - * is maintaned in a_dn_pat. + * is maintained in a_dn_pat. */ if ( bdn->a_style == ACL_STYLE_ANONYMOUS ) { @@ -1030,7 +1008,7 @@ acl_mask_dnattr( return 1; ACL_RECORD_VALUE_STATE; - + /* this is a self clause, check if the target is an * attribute. */ @@ -1102,16 +1080,8 @@ slap_acl_mask( accessmask2str( *mask, accessmaskbuf, 1 ) ); - if( state && ( state->as_recorded & ACL_STATE_RECORDED_VD ) - && state->as_vd_acl == a ) - { - b = state->as_vd_access; - i = state->as_vd_access_count; - - } else { - b = a->acl_access; - i = 1; - } + b = a->acl_access; + i = 1; for ( ; b != NULL; b = b->a_next, i++ ) { slap_mask_t oldmask, modmask; @@ -1131,7 +1101,7 @@ slap_acl_mask( * NOTE: styles "anonymous", "users" and "self" * have been moved to enum slap_style_t, whose * value is set in a_dn_style; however, the string - * is maintaned in a_dn_pat. + * is maintained in a_dn_pat. */ if ( acl_mask_dn( op, e, desc, val, a, nmatch, matches, @@ -1155,7 +1125,7 @@ slap_acl_mask( * NOTE: styles "anonymous", "users" and "self" * have been moved to enum slap_style_t, whose * value is set in a_dn_style; however, the string - * is maintaned in a_dn_pat. + * is maintained in a_dn_pat. */ if ( op->o_conn && !BER_BVISNULL( &op->o_conn->c_ndn ) ) @@ -1349,6 +1319,50 @@ slap_acl_mask( if ( (addr & b->a_peername_mask) != b->a_peername_addr ) continue; +#ifdef LDAP_PF_INET6 + /* extract IPv6 and try exact match */ + } else if ( b->a_peername_style == ACL_STYLE_IPV6 ) { + char *port; + char buf[] = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"; + struct berval ip; + struct in6_addr addr; + int port_number = -1, i; + + if ( strncasecmp( op->o_conn->c_peer_name.bv_val, + acl_bv_ipv6_eq.bv_val, + acl_bv_ipv6_eq.bv_len ) != 0 ) + continue; + + ip.bv_val = op->o_conn->c_peer_name.bv_val + acl_bv_ipv6_eq.bv_len; + ip.bv_len = op->o_conn->c_peer_name.bv_len - acl_bv_ipv6_eq.bv_len; + + port = strrchr( ip.bv_val, ']' ); + if ( port ) { + ip.bv_len = port - ip.bv_val; + ++port; + if ( port[0] == ':' && lutil_atoi( &port_number, ++port ) != 0 ) + continue; + } + + /* the port check can be anticipated here */ + if ( b->a_peername_port != -1 && port_number != b->a_peername_port ) + continue; + + /* address longer than expected? */ + if ( ip.bv_len >= sizeof(buf) ) + continue; + + AC_MEMCPY( buf, ip.bv_val, ip.bv_len ); + buf[ ip.bv_len ] = '\0'; + + if ( inet_pton( AF_INET6, buf, &addr ) != 1 ) + continue; + + /* check mask */ + if ( !slap_addr6_mask( &addr, &b->a_peername_mask6, &b->a_peername_addr6 ) ) + continue; +#endif /* LDAP_PF_INET6 */ + #ifdef LDAP_PF_LOCAL /* extract path and try exact match */ } else if ( b->a_peername_style == ACL_STYLE_PATH ) { @@ -1649,7 +1663,8 @@ slap_acl_mask( ACL_RECORD_VALUE_STATE; /* must have DN syntax */ - if ( desc->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) continue; + if ( desc->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName && + !is_at_syntax( desc->ad_type, SLAPD_NAMEUID_SYNTAX )) continue; /* check if the target is an attribute. */ if ( val == NULL ) continue; @@ -1703,7 +1718,8 @@ slap_acl_mask( Debug( LDAP_DEBUG_ACL, " <= check a_dynacl: %s\n", da->da_name, 0, 0 ); - (void)( *da->da_mask )( da->da_private, op, e, desc, val, nmatch, matches, &grant, &deny ); + (void)da->da_mask( da->da_private, op, e, desc, + val, nmatch, matches, &grant, &deny ); tgrant |= grant; tdeny |= deny;