From 4204aee7b906aa918ef3c983222789ec56f43fce Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Wed, 6 Oct 2004 22:03:33 +0000 Subject: [PATCH] extend the availability of submatches to non-regex DN patterns --- servers/slapd/acl.c | 280 +++++++++++++++++++++++++++++---------- servers/slapd/aclparse.c | 31 +++-- 2 files changed, 228 insertions(+), 83 deletions(-) diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index c655bd1e28..6f63a9c0bf 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -81,7 +81,7 @@ static AccessControl * acl_get( Operation *op, Entry *e, AttributeDescription *desc, struct berval *val, - int nmatches, regmatch_t *matches, + int nmatch, regmatch_t *matches, AccessControlState *state ); static slap_control_t acl_mask( @@ -89,6 +89,7 @@ static slap_control_t acl_mask( Operation *op, Entry *e, AttributeDescription *desc, struct berval *val, + int nmatch, regmatch_t *matches, int count, AccessControlState *state ); @@ -99,6 +100,7 @@ static int aci_mask( AttributeDescription *desc, struct berval *val, struct berval *aci, + int nmatch, regmatch_t *matches, slap_access_t *grant, slap_access_t *deny, @@ -106,10 +108,11 @@ static int aci_mask( #endif static int regex_matches( - struct berval *pat, char *str, char *buf, regmatch_t *matches); + struct berval *pat, char *str, char *buf, + int nmatch, regmatch_t *matches); static int string_expand( struct berval *newbuf, struct berval *pattern, - char *match, regmatch_t *matches); + char *match, int nmatch, regmatch_t *matches); typedef struct AciSetCookie { Operation *op; @@ -142,12 +145,12 @@ static int aci_match_set ( struct berval *subj, Operation *op, int access_allowed_mask( Operation *op, - Entry *e, + Entry *e, AttributeDescription *desc, - struct berval *val, - slap_access_t access, - AccessControlState *state, - slap_mask_t *maskp ) + struct berval *val, + slap_access_t access, + AccessControlState *state, + slap_mask_t *maskp ) { int ret = 1; int count; @@ -357,7 +360,7 @@ access_allowed_mask( vd_access: control = acl_mask( a, &mask, op, - e, desc, val, matches, count, state ); + e, desc, val, MAXREMATCHES, matches, count, state ); if ( control != ACL_BREAK ) { break; @@ -629,15 +632,16 @@ acl_get( static slap_control_t acl_mask( - AccessControl *a, - slap_mask_t *mask, - Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - regmatch_t *matches, - int count, - AccessControlState *state ) + AccessControl *a, + slap_mask_t *mask, + Operation *op, + Entry *e, + AttributeDescription *desc, + struct berval *val, + int nmatch, + regmatch_t *matches, + int count, + AccessControlState *state ) { int i, odnlen, patlen; Access *b; @@ -712,10 +716,51 @@ acl_mask( } else if ( b->a_dn_style == ACL_STYLE_REGEX ) { if ( !ber_bvccmp( &b->a_dn_pat, '*' ) ) { - int ret = regex_matches( &b->a_dn_pat, - op->o_ndn.bv_val, e->e_ndn, matches ); + int tmp_nmatch; + regmatch_t tmp_matches[2], + *tmp_matchesp = tmp_matches; + + int rc = 0; - if( ret == 0 ) { + 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; + 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; + break; + + default: + /* error */ + rc = 1; + break; + } + + if ( rc ) { + continue; + } + + if ( !regex_matches( &b->a_dn_pat, + op->o_ndn.bv_val, e->e_ndn, + tmp_nmatch, tmp_matchesp ) ) + { continue; } } @@ -728,17 +773,60 @@ acl_mask( continue; if ( b->a_dn_expand ) { - struct berval bv; - char buf[ACL_BUF_SIZE]; + struct berval bv; + char buf[ACL_BUF_SIZE]; + + int tmp_nmatch; + regmatch_t tmp_matches[2], + *tmp_matchesp = tmp_matches; + + int rc = 0; bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; - if ( string_expand(&bv, &b->a_dn_pat, - e->e_ndn, matches) ) + 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; + 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; + break; + + default: + /* error */ + rc = 1; + break; + } + + if ( rc ) { + continue; + } + + if ( string_expand( &bv, &b->a_dn_pat, + e->e_nname.bv_val, + tmp_nmatch, tmp_matchesp ) ) { continue; } + if ( dnNormalize(0, NULL, NULL, &bv, &pat, op->o_tmpmemctx ) != LDAP_SUCCESS ) @@ -746,6 +834,7 @@ acl_mask( /* did not expand to a valid dn */ continue; } + } else { pat = b->a_dn_pat; } @@ -817,7 +906,7 @@ dn_match_cleanup:; 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 ) ) + e->e_ndn, nmatch, matches ) ) { continue; } @@ -829,7 +918,7 @@ dn_match_cleanup:; bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; if ( string_expand( &bv, &b->a_sockurl_pat, - e->e_ndn, matches ) ) + e->e_ndn, nmatch, matches ) ) { continue; } @@ -857,7 +946,7 @@ dn_match_cleanup:; 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 ) ) + e->e_ndn, nmatch, matches ) ) { continue; } @@ -874,7 +963,7 @@ dn_match_cleanup:; bv.bv_val = buf; if ( string_expand(&bv, &b->a_domain_pat, - e->e_ndn, matches) ) + e->e_ndn, nmatch, matches) ) { continue; } @@ -912,7 +1001,7 @@ dn_match_cleanup:; 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 ) ) + e->e_ndn, nmatch, matches ) ) { continue; } @@ -931,7 +1020,7 @@ dn_match_cleanup:; bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; if ( string_expand( &bv, &b->a_peername_pat, - e->e_ndn, matches ) ) + e->e_ndn, nmatch, matches ) ) { continue; } @@ -1020,7 +1109,7 @@ dn_match_cleanup:; 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 ) ) + e->e_ndn, nmatch, matches ) ) { continue; } @@ -1032,7 +1121,7 @@ dn_match_cleanup:; bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; if ( string_expand( &bv, &b->a_sockname_pat, - e->e_ndn, matches ) ) + e->e_ndn, nmatch, matches ) ) { continue; } @@ -1142,16 +1231,61 @@ dn_match_cleanup:; */ /* see if asker is listed in dnattr */ if ( b->a_group_style == ACL_STYLE_EXPAND ) { - char buf[ACL_BUF_SIZE]; + char buf[ACL_BUF_SIZE]; + int tmp_nmatch; + regmatch_t tmp_matches[2], + *tmp_matchesp = tmp_matches; + bv.bv_len = sizeof(buf) - 1; - bv.bv_val = buf; + bv.bv_val = buf; + + rc = 0; + + 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; + 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; + break; + default: + /* error */ + rc = 1; + break; + } + + if ( rc ) { + continue; + } + if ( string_expand( &bv, &b->a_group_pat, - e->e_ndn, matches ) ) + e->e_nname.bv_val, + tmp_nmatch, tmp_matchesp ) ) { continue; } - if ( dnNormalize( 0, NULL, NULL, &bv, &ndn, op->o_tmpmemctx ) != LDAP_SUCCESS ) { + + if ( dnNormalize( 0, NULL, NULL, &bv, &ndn, + op->o_tmpmemctx ) != LDAP_SUCCESS ) + { /* did not expand to a valid dn */ continue; } @@ -1179,7 +1313,7 @@ dn_match_cleanup:; bv.bv_len = sizeof(buf) - 1; bv.bv_val = buf; if ( string_expand( &bv, &b->a_set_pat, - e->e_ndn, matches ) ) + e->e_ndn, nmatch, matches ) ) { continue; } @@ -1270,7 +1404,8 @@ dn_match_cleanup:; if (aci_mask( op, e, desc, val, &at->a_nvals[i], - matches, &grant, &deny, &aci_bv_entry ) != 0) + nmatch, matches, + &grant, &deny, &aci_bv_entry ) != 0) { tgrant |= grant; tdeny |= deny; @@ -1304,8 +1439,10 @@ dn_match_cleanup:; * see also ACL_RECORD_VALUE_STATE above */ ACL_RECORD_VALUE_STATE; #endif - if (aci_mask(op, e, desc, val, &bvals[i], matches, - &grant, &deny, &aci_bv_children) != 0) { + if (aci_mask(op, e, desc, val, &bvals[i], + nmatch, matches, + &grant, &deny, &aci_bv_children) != 0) + { tgrant |= grant; tdeny |= deny; /* evaluation stops as soon as either a "deny" or a @@ -1852,11 +1989,12 @@ aci_list_get_rights( static int aci_group_member ( - struct berval *subj, - struct berval *defgrpoc, - struct berval *defgrpat, - Operation *op, + struct berval *subj, + struct berval *defgrpoc, + struct berval *defgrpat, + Operation *op, Entry *e, + int nmatch, regmatch_t *matches ) { @@ -1896,7 +2034,7 @@ aci_group_member ( bv.bv_len = sizeof( buf ) - 1; bv.bv_val = (char *)&buf; if ( string_expand(&bv, &subjdn, - e->e_ndn, matches) ) + e->e_ndn, nmatch, matches) ) { rc = LDAP_OTHER; goto done; @@ -1914,15 +2052,16 @@ done: static int aci_mask( - Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - struct berval *aci, + Operation *op, + Entry *e, + AttributeDescription *desc, + struct berval *val, + struct berval *aci, + int nmatch, regmatch_t *matches, - slap_access_t *grant, - slap_access_t *deny, - struct berval *scope + slap_access_t *grant, + slap_access_t *deny, + struct berval *scope ) { struct berval bv, perms, sdn; @@ -2022,11 +2161,13 @@ aci_mask( } else if (ber_bvstrcasecmp( &aci_bv_group, &bv ) == 0) { - if (aci_group_member(&sdn, &aci_bv_group_class, &aci_bv_group_attr, op, e, matches)) + if (aci_group_member(&sdn, &aci_bv_group_class, + &aci_bv_group_attr, op, e, nmatch, matches)) return(1); } else if (ber_bvstrcasecmp( &aci_bv_role, &bv ) == 0) { - if (aci_group_member(&sdn, &aci_bv_role_class, &aci_bv_role_attr, op, e, matches)) + if (aci_group_member(&sdn, &aci_bv_role_class, + &aci_bv_role_attr, op, e, nmatch, matches)) return(1); } else if (ber_bvstrcasecmp( &aci_bv_set, &bv ) == 0) { @@ -2049,6 +2190,7 @@ string_expand( struct berval *bv, struct berval *pat, char *match, + int nmatch, regmatch_t *matches) { ber_len_t size; @@ -2094,7 +2236,7 @@ string_expand( } } - if ( n >= MAXREMATCHES ) { + if ( n >= nmatch ) { /* FIXME: error */ return 1; } @@ -2136,10 +2278,11 @@ string_expand( 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 */ - regmatch_t *matches /* offsets in buffer for $N expansion variables */ + 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 */ ) { regex_t re; @@ -2147,15 +2290,18 @@ regex_matches( struct berval bv; int rc; - bv.bv_len = sizeof(newbuf) - 1; + bv.bv_len = sizeof( newbuf ) - 1; bv.bv_val = newbuf; - if(str == NULL) str = ""; + if (str == NULL) { + str = ""; + }; - string_expand(&bv, pat, buf, matches); - if (( rc = regcomp(&re, newbuf, REG_EXTENDED|REG_ICASE))) { + string_expand( &bv, pat, buf, nmatch, matches ); + rc = regcomp( &re, newbuf, REG_EXTENDED|REG_ICASE ); + if ( rc ) { char error[ACL_BUF_SIZE]; - regerror(rc, &re, error, sizeof(error)); + regerror( rc, &re, error, sizeof( error ) ); Debug( LDAP_DEBUG_TRACE, "compile( \"%s\", \"%s\") failed %s\n", @@ -2163,7 +2309,7 @@ regex_matches( return( 0 ); } - rc = regexec(&re, str, 0, NULL, 0); + rc = regexec( &re, str, 0, NULL, 0 ); regfree( &re ); Debug( LDAP_DEBUG_TRACE, diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c index c039c6e25a..03c2087773 100644 --- a/servers/slapd/aclparse.c +++ b/servers/slapd/aclparse.c @@ -103,7 +103,7 @@ regtest(const char *fname, int lineno, char *pat) { } *dp = '\0'; - if ( size >= (sizeof(buf)-1) ) { + if ( size >= (sizeof(buf) - 1) ) { fprintf( stderr, "%s: line %d: regular expression \"%s\" too large\n", fname, lineno, pat ); @@ -362,7 +362,7 @@ parse_acl( || strcmp(right, "^.*$$") == 0 ) { a->acl_dn_pat.bv_val = ch_strdup( "*" ); - a->acl_dn_pat.bv_len = sizeof("*")-1; + a->acl_dn_pat.bv_len = STRLENOF("*"); } else { acl_regex_normalized_dn( right, &a->acl_dn_pat ); @@ -474,12 +474,11 @@ parse_acl( } } - if ( a->acl_dn_pat.bv_len != 0 && - strcmp(a->acl_dn_pat.bv_val, "*") == 0 ) + if ( !BER_BVISNULL( &a->acl_dn_pat ) && + ber_bvccmp( &a->acl_dn_pat, '*' ) ) { free( a->acl_dn_pat.bv_val ); - a->acl_dn_pat.bv_val = NULL; - a->acl_dn_pat.bv_len = 0; + BER_BVZERO( &a->acl_dn_pat ); } if( a->acl_dn_pat.bv_len != 0 || @@ -634,15 +633,15 @@ parse_acl( sty = ACL_STYLE_REGEX; } else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) { - ber_str2bv("anonymous", sizeof("anonymous")-1, 1, &bv); + ber_str2bv("anonymous", STRLENOF( "anonymous" ), 1, &bv); sty = ACL_STYLE_REGEX; } else if ( strcasecmp( argv[i], "self" ) == 0 ) { - ber_str2bv("self", sizeof("self")-1, 1, &bv); + ber_str2bv("self", STRLENOF( "self" ), 1, &bv); sty = ACL_STYLE_REGEX; } else if ( strcasecmp( argv[i], "users" ) == 0 ) { - ber_str2bv("users", sizeof("users")-1, 1, &bv); + ber_str2bv("users", STRLENOF( "users" ), 1, &bv); sty = ACL_STYLE_REGEX; } else if ( strcasecmp( left, "dn" ) == 0 ) { @@ -651,18 +650,18 @@ parse_acl( if( right == NULL ) { /* no '=' */ ber_str2bv("users", - sizeof("users")-1, + STRLENOF( "users" ), 1, &bv); } else if (*right == '\0' ) { /* dn="" */ ber_str2bv("anonymous", - sizeof("anonymous")-1, + STRLENOF( "anonymous" ), 1, &bv); } else if ( strcmp( right, "*" ) == 0 ) { /* dn=* */ /* any or users? users for now */ ber_str2bv("users", - sizeof("users")-1, + STRLENOF( "users" ), 1, &bv); } else if ( strcmp( right, ".+" ) == 0 || strcmp( right, "^.+" ) == 0 @@ -672,7 +671,7 @@ parse_acl( || strcmp( right, "^.+$$" ) == 0 ) { ber_str2bv("users", - sizeof("users")-1, + STRLENOF( "users" ), 1, &bv); } else if ( strcmp( right, ".*" ) == 0 || strcmp( right, "^.*" ) == 0 @@ -682,7 +681,7 @@ parse_acl( || strcmp( right, "^.*$$" ) == 0 ) { ber_str2bv("*", - sizeof("*")-1, + STRLENOF( "*" ), 1, &bv); } else { @@ -782,7 +781,7 @@ parse_acl( continue; } - if ( strncasecmp( left, "group", sizeof("group")-1 ) == 0 ) { + if ( strncasecmp( left, "group", STRLENOF( "group" ) ) == 0 ) { char *name = NULL; char *value = NULL; @@ -1965,7 +1964,7 @@ print_access( Access *b ) fprintf( stderr, "\tby" ); if ( b->a_dn_pat.bv_len != 0 ) { - if( strcmp(b->a_dn_pat.bv_val, "*") == 0 || + if ( ber_bvccmp( &b->a_dn_pat, '*' ) || strcmp(b->a_dn_pat.bv_val, "users") == 0 || strcmp(b->a_dn_pat.bv_val, "anonymous") == 0 || strcmp(b->a_dn_pat.bv_val, "self") == 0 ) -- 2.39.5