httpd-40323

Version:

2.0.55

Bug link:

https://issues.apache.org/bugzilla/show_bug.cgi?id=40323

Symptom(Failure):

Refuse valid input. Apache would reject user-defined filter: SetOutputFilter with the following msg:

[error] [client 192.168.56.15] couldn't find definition of filter 'myfilterz'

Configuration:

ExtFilterDefine myfilterZ cmd="/scriptpath/scriptname.pl"
<Location /home>
 SetOutputFilter myfilterZ
</Location>

How it is diagnosed:

We cannot reproduce the failure so only analyzed the code.

Root Cause:

Apache core server normalized the user-defined filter name by converting it to lower case. But later the look-up code didn't convert to lowercase, resulting that the ‘find_filter_def’ function cannot find the filter.

mod_ext_filter.c:

static apr_status_t init_filter_instance(ap_filter_t *f) {

   … …

   f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(ef_ctx_t));

   dc = ap_get_module_config(f->r->per_dir_config,

                             &ext_filter_module);

   ctx->dc = dc;

   /* look for the user-defined filter */

   ctx->filter = find_filter_def(f->r->server, f->frec->name);

  /* find_filter_def essentially calls apr_hash_get to perform the look-up.

       If we cannot find a filter, print an error message. */

   if (!ctx->filter) {

       ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,

                     "couldn't find definition of filter '%s'",

                     f->frec->name);

       return APR_EINVAL;

   }

}

   

/* find_filter_def essentially uses ‘apr_hash_get’ to perform the hash lookup.  */

static ef_filter_t *find_filter_def(const server_rec *s, const char *fname) {

   ef_server_t *sc;

   ef_filter_t *f;

   sc = ap_get_module_config(s->module_config, &ext_filter_module);

   f = apr_hash_get(sc->h, fname, APR_HASH_KEY_STRING);

   if (!f && s != main_server) {

       s = main_server;

       sc = ap_get_module_config(s->module_config, &ext_filter_module);

       f = apr_hash_get(sc->h, fname, APR_HASH_KEY_STRING);

   }

   return f;

}

/* The fix below is simply to use lower-cases when storing into

  the hash table. */

char* define_filter(cmd_parms *cmd, void *dummy, const char *args) {
+    char *normalized_name;

-    if (apr_hash_get(conf->h, name, APR_HASH_KEY_STRING)) {
+    /* During request processing, we find information about the filter
+     * by looking up the filter name provided by core server in our
+     * hash table.  But the core server has normalized the filter
+     * name by converting it to lower case.  Thus, when adding the
+     * filter to our hash table we have to use lower case as well.
+     */
+    normalized_name = apr_pstrdup(cmd->pool, name);
+    ap_str_tolower(normalized_name);
+
+    if (apr_hash_get(conf->h, normalized_name, APR_HASH_KEY_STRING)) {
        return apr_psprintf(cmd->pool, "ExtFilter %s is already defined",
                            name);
    }

-    apr_hash_set(conf->h, name, APR_HASH_KEY_STRING, filter);
+    apr_hash_set(conf->h, normalized_name, APR_HASH_KEY_STRING, filter);

    while (*args) {
        while (apr_isspace(*args)) {

}

Is there any log message?:

Yes.

What is the error message pattern:

Input check. Checks whether Apache can find the user-defined filter input.