Added new directive (SecPdfProtectMethod) to enable the user to choose between

using token redirection (falling back on forced download in some cases) and
forced download (in all cases).
This commit is contained in:
ivanr 2007-06-14 15:26:08 +00:00
parent 8b843127ba
commit 74738b29b0
4 changed files with 71 additions and 4 deletions

View File

@ -14,7 +14,7 @@
#include "modsecurity.h"
#include "msc_logging.h"
#include "pdf_protect.h"
#include "http_log.h"
/* #define DEBUG_CONF 1 */
@ -90,6 +90,7 @@ void *create_directory_config(apr_pool_t *mp, char *path) {
dcfg->pdfp_timeout = NOT_SET;
dcfg->pdfp_token_name = NOT_SET_P;
dcfg->pdfp_only_get = NOT_SET;
dcfg->pdfp_method = NOT_SET;
/* Geo Lookups */
dcfg->geo = NOT_SET_P;
@ -384,6 +385,8 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child) {
? parent->pdfp_token_name : child->pdfp_token_name);
merged->pdfp_only_get = (child->pdfp_only_get == NOT_SET
? parent->pdfp_only_get : child->pdfp_only_get);
merged->pdfp_method = (child->pdfp_method == NOT_SET
? parent->pdfp_method : child->pdfp_method);
/* Geo Lookup */
merged->geo = (child->geo == NOT_SET_P
@ -457,6 +460,7 @@ void init_directory_config(directory_config *dcfg) {
if (dcfg->pdfp_timeout == NOT_SET) dcfg->pdfp_timeout = 10;
if (dcfg->pdfp_token_name == NOT_SET_P) dcfg->pdfp_token_name = "PDFPTOKEN";
if (dcfg->pdfp_only_get == NOT_SET) dcfg->pdfp_only_get = 1;
if (dcfg->pdfp_method == NOT_SET) dcfg->pdfp_method = PDF_PROTECT_METHOD_TOKEN_REDIRECTION;
/* Geo Lookup */
if (dcfg->geo == NOT_SET_P) dcfg->geo = NULL;
@ -1195,6 +1199,25 @@ static const char *cmd_pdf_protect_intercept_get_only(cmd_parms *cmd, void *_dcf
return NULL;
}
static const char *cmd_pdf_protect_method(cmd_parms *cmd, void *_dcfg,
const char *p1)
{
directory_config *dcfg = (directory_config *)_dcfg;
if (dcfg == NULL) return NULL;
if (strcasecmp(p1, "TokenRedirection") == 0) {
dcfg->pdfp_method = PDF_PROTECT_METHOD_TOKEN_REDIRECTION;
} else
if (strcasecmp(p1, "ForcedDownload") == 0) {
dcfg->pdfp_method = PDF_PROTECT_METHOD_FORCED_DOWNLOAD;
} else {
return (const char *)apr_psprintf(cmd->pool,
"ModSecurity: Unrecognised parameter value for SecPdfProtectMethod: %s", p1);
}
return NULL;
}
/* -- Geo Lookup configuration -- */
static const char *cmd_geo_lookups_db(cmd_parms *cmd, void *_dcfg,
@ -1550,6 +1573,14 @@ const command_rec module_directives[] = {
"whether or not to intercept only GET and HEAD requess. Defaults to true."
),
AP_INIT_TAKE1 (
"SecPdfProtectMethod",
cmd_pdf_protect_method,
NULL,
RSRC_CONF,
"protection method to use. Can be 'TokenRedirection' (default) or 'ForcedDownload'"
),
AP_INIT_TAKE1 (
"SecGeoLookupsDb",
cmd_geo_lookups_db,

View File

@ -412,6 +412,7 @@ struct directory_config {
int pdfp_timeout;
const char *pdfp_token_name;
int pdfp_only_get;
int pdfp_method;
/* Geo Lookup */
geo_db *geo;

View File

@ -225,11 +225,14 @@ apr_status_t pdfp_output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
if (msr == NULL) {
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, f->r->server,
"ModSecurity: Internal Error: Unable to retrieve context in PDF output filter.");
ap_remove_output_filter(f);
return send_error_bucket(f, HTTP_INTERNAL_SERVER_ERROR);
}
if (msr->txcfg->pdfp_enabled == 1) {
// TODO Should we look at err_headers_out too?
const char *h_content_type = apr_table_get(f->r->headers_out, "Content-Type");
if (msr->txcfg->debuglog_level >= 9) {
@ -258,7 +261,7 @@ apr_status_t pdfp_output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
// TODO application/x-pdf, application/vnd.fdf, application/vnd.adobe.xfdf,
// application/vnd.adobe.xdp+xml, application/vnd.adobe.xfd+xml, application/vnd.pdf
// application/acrobat, text/pdf, text/x-pdf
// application/acrobat, text/pdf, text/x-pdf ???
if (((f->r->content_type != NULL)&&(strcasecmp(f->r->content_type, "application/pdf") == 0))
|| ((h_content_type != NULL)&&(strcasecmp(h_content_type, "application/pdf") == 0)))
{
@ -270,13 +273,32 @@ apr_status_t pdfp_output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
log_escape_nq(msr->mp, r->uri));
}
/* If we are configured with ForcedDownload protection method then we
* can do our thing here and finish early.
*/
if (msr->txcfg->pdfp_method == PDF_PROTECT_METHOD_FORCED_DOWNLOAD) {
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "PdfProtect: Forcing download of a dynamically "
"generated PDF file.");
}
apr_table_set(f->r->headers_out, "Content-Disposition", DISPOSITION_VALUE);
f->r->content_type = ATTACHMENT_MIME_TYPE;
ap_remove_output_filter(f);
return ap_pass_brigade(f->next, bb_in);
}
/* If we are here that means TokenRedirection is the desired protection method. */
/* Is this a non-GET request? */
if ((f->r->method_number != M_GET)&&
((msr->txcfg->pdfp_only_get == 1)||(msr->txcfg->pdfp_only_get == -1))
) {
/* This is a non-GET request and we have been configured
* not to intercept it. We are not going to do that but
* we are going to tweak the headers to force download.
* not to intercept it. So we are going to tweak the headers
* to force download.
*/
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "PdfProtect: Forcing download of a dynamically "
@ -287,6 +309,7 @@ apr_status_t pdfp_output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
f->r->content_type = ATTACHMENT_MIME_TYPE;
ap_remove_output_filter(f);
return ap_pass_brigade(f->next, bb_in);
}
@ -362,6 +385,15 @@ int pdfp_check(modsec_rec *msr) {
return 0;
}
if (msr->txcfg->pdfp_method != PDF_PROTECT_METHOD_TOKEN_REDIRECTION) {
if (msr->txcfg->debuglog_level >= 4) {
msr_log(msr, 4, "PdfProtect: Configured with ForcedDownload as protection method, "
"skipping detection on the inbound.");
}
return 0;
}
/* Then determine whether we need to act at
* all. If the request is not for a PDF file
* return straight away.

View File

@ -14,6 +14,9 @@
#ifndef _PDF_PROTECT_H_
#define _PDF_PROTECT_H_
#define PDF_PROTECT_METHOD_TOKEN_REDIRECTION 1
#define PDF_PROTECT_METHOD_FORCED_DOWNLOAD 2
apr_status_t DSOLOCAL pdfp_output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in);
int DSOLOCAL pdfp_check(modsec_rec *msr);