X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Facl.c;h=4b11753d38769fcf780c242334c7105ce51e1aa7;hb=b74b7c232d9d02e9c20d7144c6cbe17f93cf0d5b;hp=886bc745fc6f0c10e46cd3360713b13cbefdffd7;hpb=e1d1d3240208531466ae8ac1aca240b474499f73;p=openldap diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 886bc745fc..4b11753d38 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-2006 The OpenLDAP Foundation. + * Copyright 1998-2009 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -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 */ @@ -49,7 +52,7 @@ static AccessControl * slap_acl_get( Operation *op, Entry *e, AttributeDescription *desc, struct berval *val, - int nmatch, regmatch_t *matches, + AclRegexMatches *matches, AccessControlState *state ); static slap_control_t slap_acl_mask( @@ -57,14 +60,15 @@ static slap_control_t slap_acl_mask( Operation *op, Entry *e, AttributeDescription *desc, struct berval *val, - int nmatch, - regmatch_t *matches, + AclRegexMatches *matches, int count, - AccessControlState *state ); + AccessControlState *state, + slap_access_t access ); static int regex_matches( - struct berval *pat, char *str, char *buf, - int nmatch, regmatch_t *matches); + struct berval *pat, char *str, + struct berval *dn_matches, struct berval *val_matches, + AclRegexMatches *matches); typedef struct AclSetCookie { SetCookie asc_cookie; @@ -72,6 +76,7 @@ typedef struct AclSetCookie { Entry *asc_e; } AclSetCookie; + SLAP_SET_GATHER acl_set_gather; SLAP_SET_GATHER acl_set_gather2; @@ -112,6 +117,17 @@ slap_access_always_allowed( return 1; } +#define MATCHES_DNMAXCOUNT(m) \ + ( sizeof ( (m)->dn_data ) / sizeof( *(m)->dn_data ) ) +#define MATCHES_VALMAXCOUNT(m) \ + ( sizeof ( (m)->val_data ) / sizeof( *(m)->val_data ) ) +#define MATCHES_MEMSET(m) do { \ + memset( (m)->dn_data, '\0', sizeof( (m)->dn_data ) ); \ + memset( (m)->val_data, '\0', sizeof( (m)->val_data ) ); \ + (m)->dn_count = MATCHES_DNMAXCOUNT( (m) ); \ + (m)->val_count = MATCHES_VALMAXCOUNT( (m) ); \ +} while ( 0 /* CONSTCOND */ ) + int slap_access_allowed( Operation *op, @@ -133,8 +149,8 @@ slap_access_allowed( slap_control_t control; slap_access_t access_level; const char *attr; - regmatch_t matches[MAXREMATCHES]; - int st_same_attr = 0; + AclRegexMatches matches; + AccessControlState acl_state = ACL_STATE_INIT; assert( op != NULL ); assert( e != NULL ); @@ -176,7 +192,7 @@ slap_access_allowed( } /* use backend default access if no backend acls */ - if ( op->o_bd->be_acl == NULL ) { + if ( op->o_bd->be_acl == NULL && frontendDB->be_acl == NULL ) { int i; Debug( LDAP_DEBUG_ACL, @@ -198,40 +214,68 @@ slap_access_allowed( ret = 0; control = ACL_BREAK; - if ( st_same_attr ) { - assert( state->as_vd_acl != NULL ); - + if ( state == NULL ) + state = &acl_state; + if ( 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; - } - + if ( state->as_fe_done ) + state->as_fe_done--; } else { - if ( state ) state->as_vi_acl = NULL; + state->as_vi_acl = NULL; + a = NULL; - ACL_PRIV_ASSIGN( mask, *maskp ); count = 0; - memset( matches, '\0', sizeof( matches ) ); } + 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, - MAXREMATCHES, matches, state ) ) != NULL ) + &matches, state ) ) != NULL ) { - int i; + int i; + int dnmaxcount = MATCHES_DNMAXCOUNT( &matches ); + int valmaxcount = MATCHES_VALMAXCOUNT( &matches ); + regmatch_t *dn_data = matches.dn_data; + regmatch_t *val_data = matches.val_data; + + /* DN matches */ + for ( i = 0; i < dnmaxcount && dn_data[i].rm_eo > 0; i++ ) { + char *data = e->e_ndn; + + 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 ) { + int n; + for ( n = dn_data[i].rm_so; + n < dn_data[i].rm_eo; n++ ) { + Debug( LDAP_DEBUG_ACL, "%c", + data[n], 0, 0 ); + } + } + Debug( LDAP_DEBUG_ACL, "\n", 0, 0, 0 ); + } + + /* val matches */ + for ( i = 0; i < valmaxcount && val_data[i].rm_eo > 0; i++ ) { + char *data = val->bv_val; - for ( i = 0; i < MAXREMATCHES && matches[i].rm_so > 0; i++ ) { - Debug( LDAP_DEBUG_ACL, "=> match[%d]: %d %d ", i, - (int)matches[i].rm_so, (int)matches[i].rm_eo ); - if ( matches[i].rm_so <= matches[0].rm_eo ) { + 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 ) { int n; - for ( n = matches[i].rm_so; n < matches[i].rm_eo; n++ ) { - Debug( LDAP_DEBUG_ACL, "%c", e->e_ndn[n], 0, 0 ); + for ( n = val_data[i].rm_so; + n < val_data[i].rm_eo; n++ ) { + Debug( LDAP_DEBUG_ACL, "%c", + data[n], 0, 0 ); } } - Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_ACL, "\n", 0, 0, 0 ); } if ( state ) { @@ -239,26 +283,25 @@ slap_access_allowed( ( state->as_recorded & ACL_STATE_RECORDED_NV ) ) { Debug( LDAP_DEBUG_ACL, - "=> slap_access_allowed: result from state (%s)\n", + "=> 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: no res from state (%s)\n", + "=> slap_access_allowed: result not in cache (%s)\n", attr, 0, 0 ); } } -vd_access: control = slap_acl_mask( a, &mask, op, - e, desc, val, MAXREMATCHES, matches, count, state ); + e, desc, val, &matches, count, state, access ); if ( control != ACL_BREAK ) { break; } - memset( matches, '\0', sizeof( matches ) ); + MATCHES_MEMSET( &matches ); } if ( ACL_IS_INVALID( mask ) ) { @@ -310,7 +353,7 @@ fe_access_allowed( be_orig = op->o_bd; if ( op->o_bd == NULL ) { - op->o_bd = select_backend( &op->o_req_ndn, 0, 0 ); + op->o_bd = select_backend( &op->o_req_ndn, 0 ); if ( op->o_bd == NULL ) op->o_bd = frontendDB; } @@ -340,7 +383,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 ); @@ -358,12 +400,15 @@ access_allowed_mask( assert( attr != NULL ); if ( op ) { - if ( op->o_is_auth_check && + if ( op->o_acl_priv != ACL_NONE ) { + access = op->o_acl_priv; + + } else if ( op->o_is_auth_check && ( access_level == ACL_SEARCH || access_level == ACL_READ ) ) { 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 +422,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 +441,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 +491,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 ); @@ -476,24 +513,24 @@ slap_acl_get( Entry *e, AttributeDescription *desc, struct berval *val, - int nmatch, - regmatch_t *matches, + AclRegexMatches *matches, AccessControlState *state ) { const char *attr; - int dnlen, patlen; + ber_len_t dnlen; AccessControl *prev; assert( e != NULL ); assert( count != NULL ); assert( desc != NULL ); + assert( state != NULL ); attr = desc->ad_cname.bv_val; assert( attr != NULL ); if( a == NULL ) { - if( op->o_bd == NULL ) { + if( op->o_bd == NULL || op->o_bd->be_acl == NULL ) { a = frontendDB->be_acl; } else { a = op->o_bd->be_acl; @@ -501,7 +538,8 @@ slap_acl_get( prev = NULL; assert( a != NULL ); - + if ( a == frontendDB->be_acl ) + state->as_fe_done = 1; } else { prev = a; a = a->acl_next; @@ -509,17 +547,26 @@ slap_acl_get( dnlen = e->e_nname.bv_len; - for ( ; a != NULL; a = a->acl_next ) { + retry: + for ( ; a != NULL; prev = a, a = a->acl_next ) { (*count) ++; + if ( a != frontendDB->be_acl && state->as_fe_done ) + state->as_fe_done++; + if ( a->acl_dn_pat.bv_len || ( a->acl_dn_style != ACL_STYLE_REGEX )) { if ( a->acl_dn_style == ACL_STYLE_REGEX ) { Debug( LDAP_DEBUG_ACL, "=> dnpat: [%d] %s nsub: %d\n", *count, a->acl_dn_pat.bv_val, (int) a->acl_dn_re.re_nsub ); - if (regexec(&a->acl_dn_re, e->e_ndn, nmatch, matches, 0)) + if ( regexec ( &a->acl_dn_re, + e->e_ndn, + matches->dn_count, + matches->dn_data, 0 ) ) 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; @@ -533,7 +580,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; @@ -545,7 +592,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 ) { @@ -568,7 +615,10 @@ slap_acl_get( } if ( a->acl_attrs && !ad_inlist( desc, a->acl_attrs ) ) { - matches[0].rm_so = matches[0].rm_eo = -1; + matches->dn_data[0].rm_so = -1; + matches->dn_data[0].rm_eo = -1; + matches->val_data[0].rm_so = -1; + matches->val_data[0].rm_eo = -1; continue; } @@ -578,20 +628,20 @@ slap_acl_get( continue; } - if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) { + if( !( 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 ) { Debug( LDAP_DEBUG_ACL, "acl_get: valpat %s\n", a->acl_attrval.bv_val, 0, 0 ); - if ( regexec( &a->acl_attrval_re, val->bv_val, 0, NULL, 0 ) ) + if ( regexec ( &a->acl_attrval_re, + val->bv_val, + matches->val_count, + matches->val_data, 0 ) ) { continue; } @@ -611,7 +661,7 @@ slap_acl_get( continue; } else { - int patlen, vdnlen; + ber_len_t patlen, vdnlen; patlen = a->acl_attrval.bv_len; vdnlen = val->bv_len; @@ -630,7 +680,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 ) { @@ -663,6 +713,12 @@ slap_acl_get( return a; } + if ( !state->as_fe_done ) { + state->as_fe_done = 1; + a = frontendDB->be_acl; + goto retry; + } + Debug( LDAP_DEBUG_ACL, "<= acl_get: done.\n", 0, 0, 0 ); return( NULL ); } @@ -674,11 +730,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 ) @@ -686,11 +738,9 @@ static int acl_mask_dn( Operation *op, Entry *e, - AttributeDescription *desc, struct berval *val, AccessControl *a, - int nmatch, - regmatch_t *matches, + AclRegexMatches *matches, slap_dn_access *bdn, struct berval *opndn ) { @@ -703,7 +753,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 ) { @@ -749,35 +799,38 @@ acl_mask_dn( } else if ( bdn->a_style == ACL_STYLE_REGEX ) { if ( !ber_bvccmp( &bdn->a_pat, '*' ) ) { - int tmp_nmatch; - regmatch_t tmp_matches[2], - *tmp_matchesp = tmp_matches; - + AclRegexMatches tmp_matches, + *tmp_matchesp = &tmp_matches; int rc = 0; + regmatch_t *tmp_data; + + MATCHES_MEMSET( &tmp_matches ); + tmp_data = &tmp_matches.dn_data[0]; - switch ( a->acl_dn_style ) { + if ( a->acl_attrval_style == ACL_STYLE_REGEX ) + tmp_matchesp = matches; + else switch ( a->acl_dn_style ) { case ACL_STYLE_REGEX: if ( !BER_BVISNULL( &a->acl_dn_pat ) ) { - tmp_matchesp = matches; - tmp_nmatch = nmatch; + tmp_matchesp = matches; break; } /* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */ case ACL_STYLE_BASE: - tmp_matches[0].rm_so = 0; - tmp_matches[0].rm_eo = e->e_nname.bv_len; - tmp_nmatch = 1; + tmp_data[0].rm_so = 0; + tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_matches.dn_count = 1; break; case ACL_STYLE_ONE: case ACL_STYLE_SUBTREE: case ACL_STYLE_CHILDREN: - tmp_matches[0].rm_so = 0; - tmp_matches[0].rm_eo = e->e_nname.bv_len; - tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len; - tmp_matches[1].rm_eo = e->e_nname.bv_len; - tmp_nmatch = 2; + tmp_data[0].rm_so = 0; + tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len; + tmp_data[1].rm_eo = e->e_nname.bv_len; + tmp_matches.dn_count = 2; break; default: @@ -791,7 +844,7 @@ acl_mask_dn( } if ( !regex_matches( &bdn->a_pat, opndn->bv_val, - e->e_ndn, tmp_nmatch, tmp_matchesp ) ) + &e->e_nname, NULL, tmp_matchesp ) ) { return 1; } @@ -809,38 +862,42 @@ acl_mask_dn( struct berval bv; char buf[ACL_BUF_SIZE]; - int tmp_nmatch; - regmatch_t tmp_matches[2], - *tmp_matchesp = tmp_matches; - + AclRegexMatches tmp_matches, + *tmp_matchesp = &tmp_matches; int rc = 0; + regmatch_t *tmp_data; + + MATCHES_MEMSET( &tmp_matches ); + tmp_data = &tmp_matches.dn_data[0]; bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; - switch ( a->acl_dn_style ) { + /* Expand value regex */ + if ( a->acl_attrval_style == ACL_STYLE_REGEX ) + tmp_matchesp = matches; + else switch ( a->acl_dn_style ) { case ACL_STYLE_REGEX: if ( !BER_BVISNULL( &a->acl_dn_pat ) ) { tmp_matchesp = matches; - tmp_nmatch = nmatch; break; } /* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */ case ACL_STYLE_BASE: - tmp_matches[0].rm_so = 0; - tmp_matches[0].rm_eo = e->e_nname.bv_len; - tmp_nmatch = 1; + tmp_data[0].rm_so = 0; + tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_matches.dn_count = 1; break; case ACL_STYLE_ONE: case ACL_STYLE_SUBTREE: case ACL_STYLE_CHILDREN: - tmp_matches[0].rm_so = 0; - tmp_matches[0].rm_eo = e->e_nname.bv_len; - tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len; - tmp_matches[1].rm_eo = e->e_nname.bv_len; - tmp_nmatch = 2; + tmp_data[0].rm_so = 0; + tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len; + tmp_data[1].rm_eo = e->e_nname.bv_len; + tmp_matches.dn_count = 2; break; default: @@ -854,8 +911,8 @@ acl_mask_dn( } if ( acl_string_expand( &bv, &bdn->a_pat, - e->e_nname.bv_val, - tmp_nmatch, tmp_matchesp ) ) + &e->e_nname, + val, tmp_matchesp ) ) { return 1; } @@ -965,9 +1022,6 @@ acl_mask_dnattr( Entry *e, struct berval *val, AccessControl *a, - Access *b, - int i, - regmatch_t *matches, int count, AccessControlState *state, slap_dn_access *bdn, @@ -993,11 +1047,10 @@ acl_mask_dnattr( at != NULL; at = attrs_find( at->a_next, bdn->a_at ) ) { - if ( value_find_ex( bdn->a_at, + if ( attr_valfind( at, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, - at->a_nvals, - &bv, op->o_tmpmemctx ) == 0 ) + &bv, NULL, op->o_tmpmemctx ) == 0 ) { /* found it */ match = 1; @@ -1030,7 +1083,7 @@ acl_mask_dnattr( return 1; ACL_RECORD_VALUE_STATE; - + /* this is a self clause, check if the target is an * attribute. */ @@ -1070,10 +1123,10 @@ slap_acl_mask( Entry *e, AttributeDescription *desc, struct berval *val, - int nmatch, - regmatch_t *matches, + AclRegexMatches *matches, int count, - AccessControlState *state ) + AccessControlState *state, + slap_access_t access ) { int i; Access *b; @@ -1081,7 +1134,9 @@ slap_acl_mask( char accessmaskbuf[ACCESSMASK_MAXLEN]; #endif /* DEBUG */ const char *attr; - slap_mask_t a2pmask = ACL_ACCESS2PRIV( *mask ); +#ifdef SLAP_DYNACL + slap_mask_t a2pmask = ACL_ACCESS2PRIV( access ); +#endif /* SLAP_DYNACL */ assert( a != NULL ); assert( mask != NULL ); @@ -1102,16 +1157,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,10 +1178,10 @@ 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, + if ( acl_mask_dn( op, e, val, a, matches, &b->a_dn, &op->o_ndn ) ) { continue; @@ -1155,7 +1202,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 ) ) @@ -1165,7 +1212,7 @@ slap_acl_mask( ndn = op->o_ndn; } - if ( acl_mask_dn( op, e, desc, val, a, nmatch, matches, + if ( acl_mask_dn( op, e, val, a, matches, &b->a_realdn, &ndn ) ) { continue; @@ -1181,8 +1228,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, nmatch, matches ) ) + if ( !regex_matches( &b->a_sockurl_pat, op->o_conn->c_listener_url.bv_val, + &e->e_nname, val, matches ) ) { continue; } @@ -1193,8 +1240,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, nmatch, matches ) ) + if ( acl_string_expand( &bv, &b->a_sockurl_pat, &e->e_nname, val, matches ) ) { continue; } @@ -1221,8 +1267,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, nmatch, matches ) ) + if ( !regex_matches( &b->a_domain_pat, op->o_conn->c_peer_domain.bv_val, + &e->e_nname, val, matches ) ) { continue; } @@ -1238,8 +1284,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, nmatch, matches) ) + if ( acl_string_expand(&bv, &b->a_domain_pat, &e->e_nname, val, matches) ) { continue; } @@ -1276,8 +1321,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, nmatch, matches ) ) + if ( !regex_matches( &b->a_peername_pat, op->o_conn->c_peer_name.bv_val, + &e->e_nname, val, matches ) ) { continue; } @@ -1295,8 +1340,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, nmatch, matches ) ) + if ( acl_string_expand( &bv, &b->a_peername_pat, &e->e_nname, val, matches ) ) { continue; } @@ -1308,7 +1352,7 @@ slap_acl_mask( /* extract IP and try exact match */ } else if ( b->a_peername_style == ACL_STYLE_IP ) { char *port; - char buf[] = "255.255.255.255"; + char buf[STRLENOF("255.255.255.255") + 1]; struct berval ip; unsigned long addr; int port_number = -1; @@ -1349,6 +1393,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[STRLENOF("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF") + 1]; + struct berval ip; + struct in6_addr addr; + int port_number = -1; + + 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 ) { @@ -1385,8 +1473,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, nmatch, matches ) ) + if ( !regex_matches( &b->a_sockname_pat, op->o_conn->c_sock_name.bv_val, + &e->e_nname, val, matches ) ) { continue; } @@ -1397,8 +1485,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, nmatch, matches ) ) + if ( acl_string_expand( &bv, &b->a_sockname_pat, &e->e_nname, val, matches ) ) { continue; } @@ -1416,8 +1503,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, &b->a_dn, &op->o_ndn ) ) { continue; @@ -1434,8 +1521,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, &b->a_realdn, &ndn ) ) { continue; @@ -1461,38 +1548,43 @@ slap_acl_mask( /* see if asker is listed in dnattr */ if ( b->a_group_style == ACL_STYLE_EXPAND ) { char buf[ACL_BUF_SIZE]; - int tmp_nmatch; - regmatch_t tmp_matches[2], - *tmp_matchesp = tmp_matches; + AclRegexMatches tmp_matches, + *tmp_matchesp = &tmp_matches; + regmatch_t *tmp_data; + + MATCHES_MEMSET( &tmp_matches ); + tmp_data = &tmp_matches.dn_data[0]; bv.bv_len = sizeof(buf) - 1; bv.bv_val = buf; rc = 0; - switch ( a->acl_dn_style ) { + if ( a->acl_attrval_style == ACL_STYLE_REGEX ) + tmp_matchesp = matches; + else switch ( a->acl_dn_style ) { case ACL_STYLE_REGEX: if ( !BER_BVISNULL( &a->acl_dn_pat ) ) { tmp_matchesp = matches; - tmp_nmatch = nmatch; break; } /* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */ case ACL_STYLE_BASE: - tmp_matches[0].rm_so = 0; - tmp_matches[0].rm_eo = e->e_nname.bv_len; - tmp_nmatch = 1; + tmp_data[0].rm_so = 0; + tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_matches.dn_count = 1; break; case ACL_STYLE_ONE: case ACL_STYLE_SUBTREE: case ACL_STYLE_CHILDREN: - tmp_matches[0].rm_so = 0; - tmp_matches[0].rm_eo = e->e_nname.bv_len; - tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len; - tmp_matches[1].rm_eo = e->e_nname.bv_len; - tmp_nmatch = 2; + tmp_data[0].rm_so = 0; + tmp_data[0].rm_eo = e->e_nname.bv_len; + + tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len; + tmp_data[1].rm_eo = e->e_nname.bv_len; + tmp_matches.dn_count = 2; break; default: @@ -1506,8 +1598,8 @@ slap_acl_mask( } if ( acl_string_expand( &bv, &b->a_group_pat, - e->e_nname.bv_val, - tmp_nmatch, tmp_matchesp ) ) + &e->e_nname, val, + tmp_matchesp ) ) { continue; } @@ -1545,39 +1637,42 @@ slap_acl_mask( b->a_set_pat.bv_val, 0, 0 ); if ( b->a_set_style == ACL_STYLE_EXPAND ) { - int tmp_nmatch; - regmatch_t tmp_matches[2], - *tmp_matchesp = tmp_matches; + AclRegexMatches tmp_matches, + *tmp_matchesp = &tmp_matches; int rc = 0; + regmatch_t *tmp_data; + + MATCHES_MEMSET( &tmp_matches ); + tmp_data = &tmp_matches.dn_data[0]; bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; rc = 0; - switch ( a->acl_dn_style ) { + if ( a->acl_attrval_style == ACL_STYLE_REGEX ) + tmp_matchesp = matches; + else switch ( a->acl_dn_style ) { case ACL_STYLE_REGEX: if ( !BER_BVISNULL( &a->acl_dn_pat ) ) { tmp_matchesp = matches; - tmp_nmatch = nmatch; break; } /* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */ case ACL_STYLE_BASE: - tmp_matches[0].rm_so = 0; - tmp_matches[0].rm_eo = e->e_nname.bv_len; - tmp_nmatch = 1; + tmp_data[0].rm_so = 0; + tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_matches.dn_count = 1; break; case ACL_STYLE_ONE: case ACL_STYLE_SUBTREE: case ACL_STYLE_CHILDREN: - tmp_matches[0].rm_so = 0; - tmp_matches[0].rm_eo = e->e_nname.bv_len; - tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len; - tmp_matches[1].rm_eo = e->e_nname.bv_len; - tmp_nmatch = 2; + tmp_data[0].rm_so = 0; + tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len; + tmp_data[1].rm_eo = e->e_nname.bv_len; tmp_matches.dn_count = 2; break; default: @@ -1591,8 +1686,8 @@ slap_acl_mask( } if ( acl_string_expand( &bv, &b->a_set_pat, - e->e_nname.bv_val, - tmp_nmatch, tmp_matchesp ) ) + &e->e_nname, val, + tmp_matchesp ) ) { continue; } @@ -1649,7 +1744,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 +1799,14 @@ 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 ); + /* + * XXXmanu Only DN matches are supplied + * sending attribute values matches require + * an API update + */ + (void)da->da_mask( da->da_private, op, e, desc, + val, matches->dn_count, matches->dn_data, + &grant, &deny ); tgrant |= grant; tdeny |= deny; @@ -1772,8 +1875,6 @@ slap_acl_mask( *mask = modmask; } - a2pmask = *mask; - Debug( LDAP_DEBUG_ACL, "<= acl_mask: [%d] mask: %s\n", i, accessmask2str(*mask, accessmaskbuf, 1), 0 ); @@ -1825,6 +1926,10 @@ acl_check_modlist( } assert( be != NULL ); + /* If ADD attribute checking is not enabled, just allow it */ + if ( op->o_tag == LDAP_REQ_ADD && !SLAP_DBACL_ADD( be )) + return 1; + /* short circuit root database access */ if ( be_isroot( op ) ) { Debug( LDAP_DEBUG_ACL, @@ -1834,7 +1939,7 @@ acl_check_modlist( } /* use backend default access if no backend acls */ - if( op->o_bd != NULL && op->o_bd->be_acl == NULL ) { + if( op->o_bd != NULL && op->o_bd->be_acl == NULL && frontendDB->be_acl == NULL ) { Debug( LDAP_DEBUG_ACL, "=> access_allowed: backend default %s access %s to \"%s\"\n", access2str( ACL_WRITE ), @@ -2013,6 +2118,10 @@ acl_set_cb_gather( Operation *op, SlapReply *rs ) for ( j = 0; !BER_BVISNULL( &rs->sr_attrs[ j ].an_name ); j++ ) { AttributeDescription *desc = rs->sr_attrs[ j ].an_desc; + + if ( desc == NULL ) { + continue; + } if ( desc == slap_schema.si_ad_entryDN ) { bvalsp = bvals; @@ -2024,19 +2133,14 @@ acl_set_cb_gather( Operation *op, SlapReply *rs ) a = attr_find( rs->sr_entry->e_attrs, desc ); if ( a != NULL ) { - int i; - - for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) - ; - bvalsp = a->a_nvals; } } - } - if ( bvals ) { - p->bvals = slap_set_join( p->cookie, p->bvals, - ( '|' | SLAP_SET_RREF ), bvalsp ); + if ( bvalsp ) { + p->bvals = slap_set_join( p->cookie, p->bvals, + ( '|' | SLAP_SET_RREF ), bvalsp ); + } } } else { @@ -2058,8 +2162,6 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de int nattrs = 0; slap_callback cb = { NULL, acl_set_cb_gather, NULL, NULL }; acl_set_gather_t p = { 0 }; - const char *text = NULL; - static struct berval defaultFilter_bv = BER_BVC( "(objectClass=*)" ); /* this routine needs to return the bervals instead of * plain strings, since syntax is not known. It should @@ -2071,6 +2173,10 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de rc = ldap_url_parse( name->bv_val, &ludp ); if ( rc != LDAP_URL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + "%s acl_set_gather: unable to parse URL=\"%s\"\n", + cp->asc_op->o_log_prefix, name->bv_val, 0 ); + rc = LDAP_PROTOCOL_ERROR; goto url_done; } @@ -2079,6 +2185,10 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de { /* host part must be empty */ /* extensions parts must be empty */ + Debug( LDAP_DEBUG_TRACE, + "%s acl_set_gather: host/exts must be absent in URL=\"%s\"\n", + cp->asc_op->o_log_prefix, name->bv_val, 0 ); + rc = LDAP_PROTOCOL_ERROR; goto url_done; } @@ -2089,11 +2199,19 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de &op2.o_req_ndn, cp->asc_op->o_tmpmemctx ); BER_BVZERO( &op2.o_req_dn ); if ( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + "%s acl_set_gather: DN=\"%s\" normalize failed\n", + cp->asc_op->o_log_prefix, ludp->lud_dn, 0 ); + goto url_done; } - op2.o_bd = select_backend( &op2.o_req_ndn, 0, 1 ); + op2.o_bd = select_backend( &op2.o_req_ndn, 1 ); if ( ( op2.o_bd == NULL ) || ( op2.o_bd->be_search == NULL ) ) { + Debug( LDAP_DEBUG_TRACE, + "%s acl_set_gather: no database could be selected for DN=\"%s\"\n", + cp->asc_op->o_log_prefix, op2.o_req_ndn.bv_val, 0 ); + rc = LDAP_NO_SUCH_OBJECT; goto url_done; } @@ -2102,35 +2220,46 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de if ( ludp->lud_filter ) { ber_str2bv_x( ludp->lud_filter, 0, 0, &op2.ors_filterstr, cp->asc_op->o_tmpmemctx ); + op2.ors_filter = str2filter_x( cp->asc_op, op2.ors_filterstr.bv_val ); + if ( op2.ors_filter == NULL ) { + Debug( LDAP_DEBUG_TRACE, + "%s acl_set_gather: unable to parse filter=\"%s\"\n", + cp->asc_op->o_log_prefix, op2.ors_filterstr.bv_val, 0 ); + + rc = LDAP_PROTOCOL_ERROR; + goto url_done; + } } else { - op2.ors_filterstr = defaultFilter_bv; + op2.ors_filterstr = *slap_filterstr_objectClass_pres; + op2.ors_filter = (Filter *)slap_filter_objectClass_pres; } - op2.ors_filter = str2filter_x( cp->asc_op, op2.ors_filterstr.bv_val ); - if ( op2.ors_filter == NULL ) { - rc = LDAP_PROTOCOL_ERROR; - goto url_done; - } /* Grab the scope */ op2.ors_scope = ludp->lud_scope; /* Grap the attributes */ if ( ludp->lud_attrs ) { + int i; + for ( ; ludp->lud_attrs[ nattrs ]; nattrs++ ) ; - anlistp = slap_sl_malloc( sizeof( AttributeName ) * ( nattrs + 2 ), + anlistp = slap_sl_calloc( sizeof( AttributeName ), nattrs + 2, cp->asc_op->o_tmpmemctx ); - for ( ; ludp->lud_attrs[ nattrs ]; nattrs++ ) { - ber_str2bv( ludp->lud_attrs[ nattrs ], 0, 0, &anlistp[ nattrs ].an_name ); - anlistp[ nattrs ].an_desc = NULL; - rc = slap_bv2ad( &anlistp[ nattrs ].an_name, - &anlistp[ nattrs ].an_desc, &text ); - if ( rc != LDAP_SUCCESS ) { - goto url_done; + for ( i = 0, nattrs = 0; ludp->lud_attrs[ i ]; i++ ) { + struct berval name; + AttributeDescription *desc = NULL; + const char *text = NULL; + + ber_str2bv( ludp->lud_attrs[ i ], 0, 0, &name ); + rc = slap_bv2ad( &name, &desc, &text ); + if ( rc == LDAP_SUCCESS ) { + anlistp[ nattrs ].an_name = name; + anlistp[ nattrs ].an_desc = desc; + nattrs++; } } @@ -2158,6 +2287,7 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de op2.ors_attrs = anlistp; op2.ors_attrsonly = 0; op2.o_private = cp->asc_op->o_private; + op2.o_extra = cp->asc_op->o_extra; cb.sc_private = &p; @@ -2167,8 +2297,8 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de } url_done:; - if ( op2.ors_filter ) { - filter_free_x( cp->asc_op, op2.ors_filter ); + if ( op2.ors_filter && op2.ors_filter != slap_filter_objectClass_pres ) { + filter_free_x( cp->asc_op, op2.ors_filter, 1 ); } if ( !BER_BVISNULL( &op2.o_req_ndn ) ) { slap_sl_free( op2.o_req_ndn.bv_val, cp->asc_op->o_tmpmemctx ); @@ -2232,7 +2362,7 @@ acl_match_set ( AclSetCookie cookie; if ( default_set_attribute == NULL ) { - ber_dupbv_x( &set, subj, op->o_tmpmemctx ); + set = *subj; } else { struct berval subjdn, ndn = BER_BVNULL; @@ -2281,7 +2411,9 @@ acl_match_set ( acl_set_gather, (SetCookie *)&cookie, &set, &op->o_ndn, &e->e_nname, NULL ) > 0 ); - slap_sl_free( set.bv_val, op->o_tmpmemctx ); + if ( set.bv_val != subj->bv_val ) { + slap_sl_free( set.bv_val, op->o_tmpmemctx ); + } } return(rc); @@ -2377,20 +2509,22 @@ int acl_string_expand( struct berval *bv, struct berval *pat, - char *match, - int nmatch, - regmatch_t *matches) + struct berval *dn_matches, + struct berval *val_matches, + AclRegexMatches *matches) { ber_len_t size; char *sp; char *dp; int flag; + enum { DN_FLAG, VAL_FLAG } tflag; size = 0; bv->bv_val[0] = '\0'; bv->bv_len--; /* leave space for lone $ */ flag = 0; + tflag = DN_FLAG; for ( dp = bv->bv_val, sp = pat->bv_val; size < bv->bv_len && sp < pat->bv_val + pat->bv_len ; sp++ ) { @@ -2400,11 +2534,21 @@ acl_string_expand( *dp++ = '$'; size++; flag = 0; + tflag = DN_FLAG; + + } else if ( flag == 2 && *sp == 'v' /*'}'*/) { + tflag = VAL_FLAG; + + } else if ( flag == 2 && *sp == 'd' /*'}'*/) { + tflag = DN_FLAG; } else if ( flag == 1 && *sp == '{' /*'}'*/) { flag = 2; } else if ( *sp >= '0' && *sp <= '9' ) { + int nm; + regmatch_t *m; + char *data; int n; int i; int l; @@ -2424,20 +2568,40 @@ acl_string_expand( } } - if ( n >= nmatch ) { + switch (tflag) { + case DN_FLAG: + nm = matches->dn_count; + m = matches->dn_data; + data = dn_matches ? dn_matches->bv_val : NULL; + break; + case VAL_FLAG: + nm = matches->val_count; + m = matches->val_data; + data = val_matches ? val_matches->bv_val : NULL; + break; + default: + assert( 0 ); + } + if ( n >= nm ) { + /* FIXME: error */ + return 1; + } + if ( data == NULL ) { /* FIXME: error */ return 1; } *dp = '\0'; - i = matches[n].rm_so; - l = matches[n].rm_eo; + i = m[n].rm_so; + l = m[n].rm_eo; + for ( ; size < bv->bv_len && i < l; size++, i++ ) { - *dp++ = match[i]; + *dp++ = data[i]; } *dp = '\0'; flag = 0; + tflag = DN_FLAG; } } else { if (*sp == '$') { @@ -2458,8 +2622,8 @@ acl_string_expand( *dp = '\0'; bv->bv_len = size; - Debug( LDAP_DEBUG_TRACE, "=> acl_string_expand: pattern: %.*s\n", (int)pat->bv_len, pat->bv_val, 0 ); - Debug( LDAP_DEBUG_TRACE, "=> acl_string_expand: expanded: %s\n", bv->bv_val, 0, 0 ); + Debug( LDAP_DEBUG_ACL, "=> acl_string_expand: pattern: %.*s\n", (int)pat->bv_len, pat->bv_val, 0 ); + Debug( LDAP_DEBUG_ACL, "=> acl_string_expand: expanded: %s\n", bv->bv_val, 0, 0 ); return 0; } @@ -2468,9 +2632,9 @@ 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 */ - int nmatch, /* size of the matches array */ - regmatch_t *matches /* offsets in buffer for $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 */ ) { regex_t re; @@ -2485,7 +2649,7 @@ regex_matches( str = ""; }; - acl_string_expand( &bv, pat, buf, nmatch, 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];