From d85b13bbe064c7783ec4d85d29f07abd59723f50 Mon Sep 17 00:00:00 2001 From: Ludwig Krispenz Date: Tue, 12 May 2015 10:07:24 +0200 Subject: [PATCH 350/363] Ticket 48175 - Avoid using regex in ACL if possible Bug Description: aci code uses regex to do substring matching for targets but this is a huge overhead for a simple sequence of string matching Fix Description: directly do the str match for the initial, any, final parts of the filter https://fedorahosted.org/389/ticket/48175 Reviewed by: Noriko, thanks (cherry picked from commit 6024a7731c1888668f1efc163fb55e118a373366) --- ldap/servers/plugins/acl/acl.c | 121 ++++++++++------------------------------- 1 file changed, 30 insertions(+), 91 deletions(-) diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c index 6edc367..3b0a7ce 100644 --- a/ldap/servers/plugins/acl/acl.c +++ b/ldap/servers/plugins/acl/acl.c @@ -3209,119 +3209,58 @@ acl__TestRights(Acl_PBlock *aclpb,int access, char **right, char ** map_generic, int acl_match_substring ( Slapi_Filter *f, char *str, int exact_match) { - int i, rc, len; - char *p = NULL; - char *end, *realval, *tmp; - char pat[BUFSIZ]; - char buf[BUFSIZ]; + int i, len, tlen; + char *p = str; char *type, *initial, *final; char **any; - Slapi_Regex *re = NULL; - const char *re_result = NULL; if ( 0 != slapi_filter_get_subfilt ( f, &type, &initial, &any, &final ) ) { return (ACL_FALSE); } - /* convert the input to lower. */ - for (p = str; *p; p++) - *p = TOLOWER ( *p ); - - /* construct a regular expression corresponding to the filter: */ - pat[0] = '\0'; - p = pat; - end = pat + sizeof(pat) - 2; /* leave room for null */ - - + /* this assumes that str and the filter components are already + * normalized. If not, it shoul be done + */ if ( initial != NULL) { - strcpy (p, "^"); - p = strchr (p, '\0'); - - /* 2 * in case every char is special */ - if (p + 2 * strlen ( initial ) > end) { - slapi_log_error (SLAPI_LOG_ACL, plugin_name, - "not enough pattern space\n"); - - return (ACL_ERR); - } - - if (!exact_match) { - strcpy (p, ".*"); - p = strchr (p, '\0'); + len = strlen(initial); + if (exact_match) { + int rc = strncmp(p, initial, len); + if (rc) { + return ACL_FALSE; + } else { + p += len; + } + } else { + p = strstr(p, initial); + if (p) { + p += len; + } else { + return ACL_FALSE; + } } - acl_strcpy_special (p, initial); - p = strchr (p, '\0'); } if ( any != NULL) { for (i = 0; any && any[i] != NULL; i++) { - /* ".*" + value */ - if (p + 2 * strlen ( any[i]) + 2 > end) { - slapi_log_error (SLAPI_LOG_ACL, plugin_name, - "not enough pattern space\n"); - return (ACL_ERR); + p = strstr(p, any[i]); + if (p) { + p += strlen(any[i]); + } else { + return ACL_FALSE; } - - strcpy (p, ".*"); - p = strchr (p, '\0'); - acl_strcpy_special (p, any[i]); - p = strchr (p, '\0'); } } if ( final != NULL) { - /* ".*" + value */ - if (p + 2 * strlen ( final ) + 2 > end) { - slapi_log_error (SLAPI_LOG_ACL, plugin_name, - "not enough pattern space\n"); - return (ACL_ERR); - } - - strcpy (p, ".*"); - p = strchr (p, '\0'); - acl_strcpy_special (p, final); - p = strchr (p, '\0'); - strcpy (p, "$"); + len = strlen(final); + tlen = strlen(p); + if (len > tlen) return ACL_FALSE; + if (strcmp(p+tlen-len, final)) return ACL_FALSE; } - /* see if regex matches with the input string */ - tmp = NULL; - len = strlen(str); - - if (len < sizeof(buf)) { - strcpy (buf, str); - realval = buf; - } else { - tmp = (char*) slapi_ch_malloc (len + 1); - strcpy (tmp, str); - realval = tmp; - } + return ACL_TRUE; - /* What we have built is a regular pattaren expression. - ** Now we will compile the pattern and compare wth the string to - ** see if the input string matches with the patteren or not. - */ - re = slapi_re_comp( pat, &re_result ); - if (NULL == re) { - slapi_log_error (SLAPI_LOG_ACL, plugin_name, - "acl_match_substring:re_comp failed (%s)\n", re_result?re_result:"unknown"); - return (ACL_ERR); - } - - /* slapi_re_exec() returns 1 if the string p1 matches the last compiled - ** regular expression, 0 if the string p1 failed to match - */ - rc = slapi_re_exec( re, realval, -1 /* no timelimit */ ); - - slapi_re_free(re); - slapi_ch_free ( (void **) &tmp ); - - if (rc == 1) { - return ACL_TRUE; - } else { - return ACL_FALSE; - } } /*************************************************************************** * -- 2.4.3