X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Facl.c;h=bbd89fbd3812edaddc6b3c644ae21bb4d33d7f73;hb=7ca6247395c4fb838516e4b3ec917b8f7c1769e4;hp=6243a3edf68210d9333a2be111c227fc5707581d;hpb=a86fae235b3af625a9c63dbe6f788318a428b2fd;p=openldap diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 6243a3edf6..bbd89fbd38 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2008 The OpenLDAP Foundation. + * Copyright 1998-2009 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,6 +53,7 @@ static AccessControl * slap_acl_get( AttributeDescription *desc, struct berval *val, AclRegexMatches *matches, + slap_mask_t *mask, AccessControlState *state ); static slap_control_t slap_acl_mask( @@ -66,7 +67,8 @@ static slap_control_t slap_acl_mask( slap_access_t access ); static int regex_matches( - struct berval *pat, char *str, char *buf, + struct berval *pat, char *str, + struct berval *dn_matches, struct berval *val_matches, AclRegexMatches *matches); typedef struct AclSetCookie { @@ -150,6 +152,7 @@ slap_access_allowed( const char *attr; AclRegexMatches matches; AccessControlState acl_state = ACL_STATE_INIT; + static AccessControlState state_init = ACL_STATE_INIT; assert( op != NULL ); assert( e != NULL ); @@ -215,25 +218,27 @@ slap_access_allowed( if ( state == NULL ) state = &acl_state; - if ( state->as_vd_ad == desc ) { + if ( state->as_desc == desc && + state->as_access == access && + state->as_vd_acl != NULL ) + { a = state->as_vd_acl; count = state->as_vd_acl_count; if ( state->as_fe_done ) state->as_fe_done--; + ACL_PRIV_ASSIGN( mask, state->as_vd_mask ); } else { - state->as_vi_acl = NULL; + *state = state_init; a = NULL; count = 0; + ACL_PRIV_ASSIGN( mask, *maskp ); } - if ( a == NULL ) - state->as_fe_done = 0; - ACL_PRIV_ASSIGN( mask, *maskp ); MATCHES_MEMSET( &matches ); while ( ( a = slap_acl_get( a, &count, op, e, desc, val, - &matches, state ) ) != NULL ) + &matches, &mask, state ) ) != NULL ) { int i; int dnmaxcount = MATCHES_DNMAXCOUNT( &matches ); @@ -243,10 +248,9 @@ slap_access_allowed( /* DN matches */ for ( i = 0; i < dnmaxcount && dn_data[i].rm_eo > 0; i++ ) { - char *debugmsg = "=> match[dn%d]: %d %d "; char *data = e->e_ndn; - Debug( LDAP_DEBUG_ACL, debugmsg, i, + Debug( LDAP_DEBUG_ACL, "=> match[dn%d]: %d %d ", i, (int)dn_data[i].rm_so, (int)dn_data[i].rm_eo ); if ( dn_data[i].rm_so <= dn_data[0].rm_eo ) { @@ -262,10 +266,9 @@ slap_access_allowed( /* val matches */ for ( i = 0; i < valmaxcount && val_data[i].rm_eo > 0; i++ ) { - char *debugmsg = "=> match[val%d]: %d %d "; char *data = val->bv_val; - Debug( LDAP_DEBUG_ACL, debugmsg, i, + Debug( LDAP_DEBUG_ACL, "=> match[val%d]: %d %d ", i, (int)val_data[i].rm_so, (int)val_data[i].rm_eo ); if ( val_data[i].rm_so <= val_data[0].rm_eo ) { @@ -279,22 +282,6 @@ slap_access_allowed( Debug( LDAP_DEBUG_ACL, "\n", 0, 0, 0 ); } - if ( state ) { - if ( state->as_vi_acl == a && - ( state->as_recorded & ACL_STATE_RECORDED_NV ) ) - { - Debug( LDAP_DEBUG_ACL, - "=> slap_access_allowed: result was in cache (%s)\n", - attr, 0, 0 ); - ret = state->as_result; - goto done; - } else { - Debug( LDAP_DEBUG_ACL, - "=> slap_access_allowed: result not in cache (%s)\n", - attr, 0, 0 ); - } - } - control = slap_acl_mask( a, &mask, op, e, desc, val, &matches, count, state, access ); @@ -375,7 +362,6 @@ access_allowed_mask( slap_mask_t *maskp ) { int ret = 1; - AccessControl *a = NULL; int be_null = 0; #ifdef LDAP_DEBUG @@ -384,7 +370,6 @@ access_allowed_mask( slap_mask_t mask; slap_access_t access_level; const char *attr; - static AccessControlState state_init = ACL_STATE_INIT; assert( e != NULL ); assert( desc != NULL ); @@ -416,16 +401,20 @@ access_allowed_mask( } } - if ( state ) { - if ( state->as_vd_ad == desc ) { - if ( ( state->as_recorded & ACL_STATE_RECORDED_NV ) && - val == NULL ) + if ( state != NULL ) { + if ( state->as_desc == desc && + state->as_access == access && + state->as_result != -1 && + state->as_vd_acl == NULL ) { + Debug( LDAP_DEBUG_ACL, + "=> access_allowed: result was in cache (%s)\n", + attr, 0, 0 ); return state->as_result; - - } } else { - *state = state_init; + Debug( LDAP_DEBUG_ACL, + "=> access_allowed: result not in cache (%s)\n", + attr, 0, 0 ); } } @@ -486,13 +475,9 @@ access_allowed_mask( done: if ( state != NULL ) { - /* If not value-dependent, save ACL in case of more attrs */ - if ( !( state->as_recorded & ACL_STATE_RECORDED_VD ) ) { - state->as_vi_acl = a; + state->as_access = access; state->as_result = ret; - } - state->as_recorded |= ACL_STATE_RECORDED; - state->as_vd_ad = desc; + state->as_desc = desc; } if ( be_null ) op->o_bd = NULL; if ( maskp ) ACL_PRIV_ASSIGN( *maskp, mask ); @@ -515,10 +500,11 @@ slap_acl_get( AttributeDescription *desc, struct berval *val, AclRegexMatches *matches, + slap_mask_t *mask, AccessControlState *state ) { const char *attr; - int dnlen, patlen; + ber_len_t dnlen; AccessControl *prev; assert( e != NULL ); @@ -566,6 +552,8 @@ slap_acl_get( continue; } else { + ber_len_t patlen; + Debug( LDAP_DEBUG_ACL, "=> dn: [%d] %s\n", *count, a->acl_dn_pat.bv_val, 0 ); patlen = a->acl_dn_pat.bv_len; @@ -579,7 +567,7 @@ slap_acl_get( } else if ( a->acl_dn_style == ACL_STYLE_ONE ) { ber_len_t rdnlen = 0; - int sep = 0; + ber_len_t sep = 0; if ( dnlen <= patlen ) continue; @@ -591,7 +579,7 @@ slap_acl_get( } rdnlen = dn_rdnlen( NULL, &e->e_nname ); - if ( rdnlen != dnlen - patlen - sep ) + if ( rdnlen + patlen + sep != dnlen ) continue; } else if ( a->acl_dn_style == ACL_STYLE_SUBTREE ) { @@ -627,19 +615,17 @@ slap_acl_get( continue; } - if( !( state->as_recorded & ACL_STATE_RECORDED_VD )) { - state->as_recorded |= ACL_STATE_RECORDED_VD; + if ( state->as_vd_acl == NULL ) { state->as_vd_acl = prev; state->as_vd_acl_count = *count - 1; + ACL_PRIV_ASSIGN ( state->as_vd_mask, *mask ); } if ( a->acl_attrval_style == ACL_STYLE_REGEX ) { - int rc; - Debug( LDAP_DEBUG_ACL, "acl_get: valpat %s\n", a->acl_attrval.bv_val, 0, 0 ); - if ( rc = regexec ( &a->acl_attrval_re, + if ( regexec ( &a->acl_attrval_re, val->bv_val, matches->val_count, matches->val_data, 0 ) ) @@ -662,7 +648,7 @@ slap_acl_get( continue; } else { - int patlen, vdnlen; + ber_len_t patlen, vdnlen; patlen = a->acl_attrval.bv_len; vdnlen = val->bv_len; @@ -681,7 +667,7 @@ slap_acl_get( continue; rdnlen = dn_rdnlen( NULL, val ); - if ( rdnlen != vdnlen - patlen - 1 ) + if ( rdnlen + patlen + 1 != vdnlen ) continue; } else if ( a->acl_attrval_style == ACL_STYLE_SUBTREE ) { @@ -728,10 +714,10 @@ slap_acl_get( * Record value-dependent access control state */ #define ACL_RECORD_VALUE_STATE do { \ - if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) { \ - state->as_recorded |= ACL_STATE_RECORDED_VD; \ + if( state && state->as_vd_acl == NULL ) { \ state->as_vd_acl = a; \ state->as_vd_acl_count = count; \ + ACL_PRIV_ASSIGN( state->as_vd_mask, *mask ); \ } \ } while( 0 ) @@ -739,7 +725,6 @@ static int acl_mask_dn( Operation *op, Entry *e, - AttributeDescription *desc, struct berval *val, AccessControl *a, AclRegexMatches *matches, @@ -804,7 +789,6 @@ acl_mask_dn( AclRegexMatches tmp_matches, *tmp_matchesp = &tmp_matches; int rc = 0; - int dnoffset; regmatch_t *tmp_data; MATCHES_MEMSET( &tmp_matches ); @@ -847,7 +831,7 @@ acl_mask_dn( } if ( !regex_matches( &bdn->a_pat, opndn->bv_val, - e->e_ndn, tmp_matchesp ) ) + &e->e_nname, NULL, tmp_matchesp ) ) { return 1; } @@ -914,8 +898,8 @@ acl_mask_dn( } if ( acl_string_expand( &bv, &bdn->a_pat, - e->e_nname.bv_val, - val->bv_val, tmp_matchesp ) ) + &e->e_nname, + val, tmp_matchesp ) ) { return 1; } @@ -1025,11 +1009,9 @@ acl_mask_dnattr( Entry *e, struct berval *val, AccessControl *a, - Access *b, - int i, - AclRegexMatches *matches, int count, AccessControlState *state, + slap_mask_t *mask, slap_dn_access *bdn, struct berval *opndn ) { @@ -1140,7 +1122,9 @@ slap_acl_mask( char accessmaskbuf[ACCESSMASK_MAXLEN]; #endif /* DEBUG */ const char *attr; +#ifdef SLAP_DYNACL slap_mask_t a2pmask = ACL_ACCESS2PRIV( access ); +#endif /* SLAP_DYNACL */ assert( a != NULL ); assert( mask != NULL ); @@ -1185,7 +1169,7 @@ slap_acl_mask( * is maintained in a_dn_pat. */ - if ( acl_mask_dn( op, e, desc, val, a, matches, + if ( acl_mask_dn( op, e, val, a, matches, &b->a_dn, &op->o_ndn ) ) { continue; @@ -1216,7 +1200,7 @@ slap_acl_mask( ndn = op->o_ndn; } - if ( acl_mask_dn( op, e, desc, val, a, matches, + if ( acl_mask_dn( op, e, val, a, matches, &b->a_realdn, &ndn ) ) { continue; @@ -1232,8 +1216,8 @@ slap_acl_mask( if ( !ber_bvccmp( &b->a_sockurl_pat, '*' ) ) { if ( b->a_sockurl_style == ACL_STYLE_REGEX) { - if (!regex_matches( &b->a_sockurl_pat, op->o_conn->c_listener_url.bv_val, - e->e_ndn, matches ) ) + if ( !regex_matches( &b->a_sockurl_pat, op->o_conn->c_listener_url.bv_val, + &e->e_nname, val, matches ) ) { continue; } @@ -1244,7 +1228,7 @@ slap_acl_mask( bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; - if ( acl_string_expand( &bv, &b->a_sockurl_pat, e->e_ndn, val->bv_val, matches ) ) + if ( acl_string_expand( &bv, &b->a_sockurl_pat, &e->e_nname, val, matches ) ) { continue; } @@ -1271,8 +1255,8 @@ slap_acl_mask( b->a_domain_pat.bv_val, 0, 0 ); if ( !ber_bvccmp( &b->a_domain_pat, '*' ) ) { if ( b->a_domain_style == ACL_STYLE_REGEX) { - if (!regex_matches( &b->a_domain_pat, op->o_conn->c_peer_domain.bv_val, - e->e_ndn, matches ) ) + if ( !regex_matches( &b->a_domain_pat, op->o_conn->c_peer_domain.bv_val, + &e->e_nname, val, matches ) ) { continue; } @@ -1288,7 +1272,7 @@ slap_acl_mask( bv.bv_len = sizeof(buf) - 1; bv.bv_val = buf; - if ( acl_string_expand(&bv, &b->a_domain_pat, e->e_ndn, val->bv_val, matches) ) + if ( acl_string_expand(&bv, &b->a_domain_pat, &e->e_nname, val, matches) ) { continue; } @@ -1325,8 +1309,8 @@ slap_acl_mask( b->a_peername_pat.bv_val, 0, 0 ); if ( !ber_bvccmp( &b->a_peername_pat, '*' ) ) { if ( b->a_peername_style == ACL_STYLE_REGEX ) { - if (!regex_matches( &b->a_peername_pat, op->o_conn->c_peer_name.bv_val, - e->e_ndn, matches ) ) + if ( !regex_matches( &b->a_peername_pat, op->o_conn->c_peer_name.bv_val, + &e->e_nname, val, matches ) ) { continue; } @@ -1344,7 +1328,7 @@ slap_acl_mask( bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; - if ( acl_string_expand( &bv, &b->a_peername_pat, e->e_ndn, val->bv_val, matches ) ) + if ( acl_string_expand( &bv, &b->a_peername_pat, &e->e_nname, val, matches ) ) { continue; } @@ -1477,8 +1461,8 @@ slap_acl_mask( b->a_sockname_pat.bv_val, 0, 0 ); if ( !ber_bvccmp( &b->a_sockname_pat, '*' ) ) { if ( b->a_sockname_style == ACL_STYLE_REGEX) { - if (!regex_matches( &b->a_sockname_pat, op->o_conn->c_sock_name.bv_val, - e->e_ndn, matches ) ) + if ( !regex_matches( &b->a_sockname_pat, op->o_conn->c_sock_name.bv_val, + &e->e_nname, val, matches ) ) { continue; } @@ -1489,7 +1473,7 @@ slap_acl_mask( bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; - if ( acl_string_expand( &bv, &b->a_sockname_pat, e->e_ndn, val->bv_val, matches ) ) + if ( acl_string_expand( &bv, &b->a_sockname_pat, &e->e_nname, val, matches ) ) { continue; } @@ -1507,8 +1491,8 @@ slap_acl_mask( } if ( b->a_dn_at != NULL ) { - if ( acl_mask_dnattr( op, e, val, a, b, i, - matches, count, state, + if ( acl_mask_dnattr( op, e, val, a, + count, state, mask, &b->a_dn, &op->o_ndn ) ) { continue; @@ -1525,8 +1509,8 @@ slap_acl_mask( ndn = op->o_ndn; } - if ( acl_mask_dnattr( op, e, val, a, b, i, - matches, count, state, + if ( acl_mask_dnattr( op, e, val, a, + count, state, mask, &b->a_realdn, &ndn ) ) { continue; @@ -1602,7 +1586,7 @@ slap_acl_mask( } if ( acl_string_expand( &bv, &b->a_group_pat, - e->e_nname.bv_val, val->bv_val, + &e->e_nname, val, tmp_matchesp ) ) { continue; @@ -1690,7 +1674,7 @@ slap_acl_mask( } if ( acl_string_expand( &bv, &b->a_set_pat, - e->e_nname.bv_val, val->bv_val, + &e->e_nname, val, tmp_matchesp ) ) { continue; @@ -2023,7 +2007,7 @@ acl_check_modlist( if ( ! access_allowed( op, e, mlist->sml_desc, NULL, ( mlist->sml_flags & SLAP_MOD_MANAGING ) ? ACL_MANAGE : ACL_WDEL, - NULL ) ) + &state ) ) { ret = 0; goto done; @@ -2513,8 +2497,8 @@ int acl_string_expand( struct berval *bv, struct berval *pat, - char *dn_match, - char *val_match, + struct berval *dn_matches, + struct berval *val_matches, AclRegexMatches *matches) { ber_len_t size; @@ -2576,13 +2560,15 @@ acl_string_expand( case DN_FLAG: nm = matches->dn_count; m = matches->dn_data; - data = dn_match; + data = dn_matches ? dn_matches->bv_val : NULL; break; case VAL_FLAG: nm = matches->val_count; m = matches->val_data; - data = val_match; + data = val_matches ? val_matches->bv_val : NULL; break; + default: + assert( 0 ); } if ( n >= nm ) { /* FIXME: error */ @@ -2634,7 +2620,8 @@ static int regex_matches( struct berval *pat, /* pattern to expand and match against */ char *str, /* string to match against pattern */ - char *buf, /* buffer with $N expansion variables */ + struct berval *dn_matches, /* buffer with $N expansion variables from DN */ + struct berval *val_matches, /* buffer with $N expansion variables from val */ AclRegexMatches *matches /* offsets in buffer for $N expansion variables */ ) { @@ -2650,7 +2637,7 @@ regex_matches( str = ""; }; - acl_string_expand( &bv, pat, buf, NULL, matches ); + acl_string_expand( &bv, pat, dn_matches, val_matches, matches ); rc = regcomp( &re, newbuf, REG_EXTENDED|REG_ICASE ); if ( rc ) { char error[ACL_BUF_SIZE];