-const char filters_rcs[] = "$Id: filters.c,v 1.70 2006/12/09 13:33:15 fabiankeil Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.76 2007/01/01 19:36:37 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/filters.c,v $
*
* Revisions :
* $Log: filters.c,v $
+ * Revision 1.76 2007/01/01 19:36:37 fabiankeil
+ * Integrate a modified version of Wil Mahan's
+ * zlib patch (PR #895531).
+ *
+ * Revision 1.75 2006/12/29 18:30:46 fabiankeil
+ * Fixed gcc43 conversion warnings,
+ * changed sprintf calls to snprintf.
+ *
+ * Revision 1.74 2006/12/24 17:37:38 fabiankeil
+ * Adjust comment in pcrs_filter_response()
+ * to recent pcrs changes. Hohoho.
+ *
+ * Revision 1.73 2006/12/23 16:01:02 fabiankeil
+ * Don't crash if pcre returns an error code
+ * that pcrs didn't expect. Fixes BR 1621173.
+ *
+ * Revision 1.72 2006/12/22 18:52:53 fabiankeil
+ * Modified is_untrusted_url to complain in case of
+ * write errors and to give a reason when adding new
+ * entries to the trustfile. Closes FR 1097611.
+ *
+ * Revision 1.71 2006/12/22 14:24:52 fabiankeil
+ * Skip empty filter files in pcrs_filter_response,
+ * but don't ignore the ones that come afterwards.
+ * Fixes parts of BR 1619208.
+ *
* Revision 1.70 2006/12/09 13:33:15 fabiankeil
* Added some sanity checks for get_last_url().
* Fixed possible segfault caused by my last commit.
return cgi_error_memory();
}
}
-
}
else
#endif /* def FEATURE_IMAGE_BLOCKING */
p = strdup("");
for (tl = csp->config->trust_list; (t = *tl) != NULL ; tl++)
{
- sprintf(buf, "<li>%s</li>\n", t->spec);
+ snprintf(buf, sizeof(buf), "<li>%s</li>\n", t->spec);
string_append(&p, buf);
}
err = map(exports, "trusted-referrers", 1, p, 0);
p = strdup("");
for (l = csp->config->trust_info->first; l ; l = l->next)
{
- sprintf(buf, "<li> <a href=\"%s\">%s</a><br>\n",l->str, l->str);
+ snprintf(buf, sizeof(buf), "<li> <a href=\"%s\">%s</a><br>\n", l->str, l->str);
string_append(&p, buf);
}
err = map(exports, "trust-info", 1, p, 0);
* If it exists, use the previously rewritten URL as input
* otherwise just use the old path.
*/
- old_url = new_url ? new_url : strdup(csp->http->path);
+ old_url = (new_url != NULL) ? new_url : strdup(csp->http->path);
new_url = get_last_url(old_url, redirect_mode);
freez(old_url);
}
* otherwise
*
*********************************************************************/
-int is_imageurl(struct client_state *csp)
+int is_imageurl(const struct client_state *csp)
{
#ifdef FEATURE_IMAGE_DETECT_MSIE
char *tmp;
* Returns : 0 => trusted, 1 => untrusted
*
*********************************************************************/
-int is_untrusted_url(struct client_state *csp)
+int is_untrusted_url(const struct client_state *csp)
{
struct file_list *fl;
struct block_spec *b;
{
/* if the URL's referrer is from a trusted referrer, then
* add the target spec to the trustfile as an unblocked
- * domain and return NULL (which means it's OK).
+ * domain and return 0 (which means it's OK).
*/
FILE *fp;
string_join(&new_entry, path);
}
+ /*
+ * Give a reason for generating this entry.
+ */
+ string_append(&new_entry, " # Trusted referrer was: ");
+ string_append(&new_entry, referer);
+
if (new_entry != NULL)
{
- fprintf(fp, "%s\n", new_entry);
+ if (-1 == fprintf(fp, "%s\n", new_entry))
+ {
+ log_error(LOG_LEVEL_ERROR, "Failed to append \'%s\' to trustfile \'%s\': %E",
+ new_entry, csp->config->trustfile);
+ }
free(new_entry);
}
else
fclose(fp);
}
+ else
+ {
+ log_error(LOG_LEVEL_ERROR, "Failed to append new entry for \'%s\' to trustfile \'%s\': %E",
+ csp->http->hostport, csp->config->trustfile);
+ }
return 0;
}
}
* csp->content_length to the modified size and raise the
* CSP_FLAG_MODIFIED flag.
*
+ * XXX: Currently pcrs_filter_response is also responsible
+ * for dechunking and decompressing. Both should be
+ * done in separate functions so other content modifiers
+ * profit as well, even if pcrs filtering is disabled.
+ *
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
*
{
return(NULL);
}
- size = csp->iob->eod - csp->iob->cur;
+ size = (size_t)(csp->iob->eod - csp->iob->cur);
/*
* Need to check the set of re_filterfiles...
if (0 == found_filters)
{
log_error(LOG_LEVEL_ERROR, "Unable to get current state of regexp filtering.");
- return(NULL);
+ return(NULL);
}
/*
csp->flags |= CSP_FLAG_MODIFIED;
}
+#ifdef FEATURE_ZLIB
+ /*
+ * If the body has a compressed transfer-encoding,
+ * uncompress it first, adjusting size and iob->eod.
+ * Note that decompression occurs after de-chunking.
+ */
+ if (csp->content_type & CT_GZIP || csp->content_type & CT_DEFLATE)
+ {
+ /* Notice that we at least tried to decompress. */
+ if (JB_ERR_OK != decompress_iob(csp))
+ {
+ /*
+ * We failed to decompress the data; there's no point
+ * in continuing since we can't filter. This is
+ * slightly tricky because we need to remember not to
+ * modify the Content-Encoding header later; using
+ * CT_TABOO flag is a kludge for this purpose.
+ */
+ csp->content_type |= CT_TABOO;
+ return(NULL);
+ }
+ log_error(LOG_LEVEL_RE_FILTER, "Decompressing successful");
+
+ /*
+ * Decompression gives us a completely new iob,
+ * so we need to update.
+ */
+ size = (size_t)(csp->iob->eod - csp->iob->cur);
+ old = csp->iob->cur;
+
+ csp->flags |= CSP_FLAG_MODIFIED;
+ csp->content_type &= ~CT_TABOO;
+ }
+#endif
+
for (i = 0; i < MAX_AF_FILES; i++)
{
fl = csp->rlist[i];
{
if (strcmp(b->name, filtername->str) == 0)
{
- int current_hits = 0;
+ int current_hits = 0; /* Number of hits caused by this filter */
+ int job_number = 0; /* Which job we're currently executing */
+ int job_hits = 0; /* How many hits the current job caused */
if ( NULL == b->joblist )
{
/* Apply all jobs from the joblist */
for (job = b->joblist; NULL != job; job = job->next)
{
- current_hits += pcrs_execute(job, old, size, &new, &size);
- if (old != csp->iob->cur) free(old);
- old=new;
+ job_number++;
+ job_hits = pcrs_execute(job, old, size, &new, &size);
+
+ if (job_hits >= 0)
+ {
+ /*
+ * That went well. Continue filtering
+ * and use the result of this job as
+ * input for the next one.
+ */
+ current_hits += job_hits;
+ if (old != csp->iob->cur)
+ {
+ free(old);
+ }
+ old = new;
+ }
+ else
+ {
+ /*
+ * This job caused an unexpected error. Inform the user
+ * and skip the rest of the jobs in this filter. We could
+ * continue with the next job, but usually the jobs
+ * depend on each other or are similar enough to
+ * fail for the same reason.
+ *
+ * At the moment our pcrs expects the error codes of pcre 3.4,
+ * but newer pcre versions can return additional error codes.
+ * As a result pcrs_strerror()'s error message might be
+ * "Unknown error ...", therefore we print the numerical value
+ * as well.
+ *
+ * XXX: Is this important enough for LOG_LEVEL_ERROR or
+ * should we use LOG_LEVEL_RE_FILTER instead?
+ */
+ log_error(LOG_LEVEL_ERROR, "Skipped filter \'%s\' after job number %u: %s (%d)",
+ b->name, job_number, pcrs_strerror(job_hits), job_hits);
+ break;
+ }
}
- log_error(LOG_LEVEL_RE_FILTER, "re_filtering %s%s (size %d) with filter %s produced %d hits (new size %d).",
- csp->http->hostport, csp->http->path, prev_size, b->name, current_hits, size);
+ log_error(LOG_LEVEL_RE_FILTER,
+ "re_filtering %s%s (size %d) with filter %s produced %d hits (new size %d).",
+ csp->http->hostport, csp->http->path, prev_size, b->name, current_hits, size);
hits += current_hits;
}
{
struct binbuffer *in, *out;
char *p;
- size_t size = csp->iob->eod - csp->iob->cur;
+ size_t size;
+
+ size = (size_t)(csp->iob->eod - csp->iob->cur);
/*
* If the body has a "chunked" transfer-encoding,
*********************************************************************/
char *jpeg_inspect_response(struct client_state *csp)
{
- struct binbuffer *in = NULL, *out = NULL;
+ struct binbuffer *in = NULL;
+ struct binbuffer *out = NULL;
char *p = NULL;
- size_t size = csp->iob->eod - csp->iob->cur;
+ size_t size;
+
+ size = (size_t)(csp->iob->eod - csp->iob->cur);
/*
* If the body has a "chunked" transfer-encoding,
* went wrong
*
*********************************************************************/
-int remove_chunked_transfer_coding(char *buffer, const size_t size)
+size_t remove_chunked_transfer_coding(char *buffer, const size_t size)
{
size_t newsize = 0;
unsigned int chunksize = 0;