You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Rob Hartill <ro...@imdb.com> on 1997/03/12 03:42:01 UTC
Re: NCSA-style 'referer allow' in Apache?
On Tue, 11 Mar 1997, David Richards wrote:
> NCSA had a handy access-control feature in the latested (1.5.2.x) server
> releases where the LIMIT directive could be used to restrict access based
> on the referer variable, then the 'On-Deny' option could be used to send
> them to an appropriate page.
>
> This is very useful to provide an efficient, automated mechanism for keeping
> people from inlining your graphics their pages. I know I can do this with
> a CGI script, but that adds significant server overhead.
>
>
> Is there any good way to implement the following in Apache?
>
> <LIMIT GET>
> order deny,allow
> deny from all
>
> referer allow from http://www.mydomain.com/
>
> OnDeny http://www.mydomain.com/EVIL.gif
> </LIMIT>
there's nothing to do this automatically, but it should be possible to
create a module to do this from Apache 1.2b7's mod_browser.c. That module
sets environment variables based on the User-Agent field. Change it to
look at "Referer" and it'll then let you do something like:
ReferrerMatch http://www.parasite.com/ block_referrers
: : :
ErrorDocument 403 http://www.mydomain.com/EVIL.gif
order allow,deny
allow from all
deny from env=block_referrers
This is all theory, but I think it'll work. No hang on, the theory
just got turned into practice. A new module is attached.. Enjoy.
regards,
rob
--
Rob Hartill Internet Movie Database (Ltd)
http://us.imdb.com/Oscars/oscars_1996 - hype free Oscars (R) info.
http://us.imdb.com/usr/sweepstake - Win a 56k X2 modem. Free draw.
-=-=-=-=
Look at the docs for mod_browser.c and use "ReferrerMatch" and
"ReferrerMatchNoCase" in place of the "BrowserMatch" equivalents.
/* ====================================================================
* Copyright (c) 1997 The Apache Group. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* 4. The names "Apache Server" and "Apache Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 5. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
* IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Group and was originally based
* on public domain software written at the National Center for
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
* For more information on the Apache Group and the Apache HTTP server
* project, please see <http://www.apache.org/>.
*
*/
/*
* mod_check_referer.c
* Set environment variables based on the 'Referer' header.
*
* Rob Hartill <ro...@imdb.com>
* this is basicaly a rip-off of Alexei Kosut's mod_browser.c
*/
#include "httpd.h"
#include "http_config.h"
typedef struct {
char *name;
regex_t *preg;
table *referrer_type;
} referrer_entry;
typedef struct {
array_header *referrers;
} referrer_server_config_rec;
module referrer_module;
void *create_referrer_config (pool *p, server_rec *dummy)
{
referrer_server_config_rec *new =
(referrer_server_config_rec *) palloc (p, sizeof(referrer_server_config_rec));
new->referrers = make_array (p, 20, sizeof(referrer_entry));
return (void *)new;
}
void *merge_referrer_config (pool *p, void *basev, void *overridesv)
{
referrer_server_config_rec *a =
pcalloc(p, sizeof(referrer_server_config_rec));
referrer_server_config_rec *base = basev, *overrides = overridesv;
a->referrers = append_arrays(p, base->referrers, overrides->referrers);
return a;
}
const char *add_referrer(cmd_parms *cmd, void *dummy, char *name,
const char *feature)
{
referrer_server_config_rec *sconf =
get_module_config (cmd->server->module_config, &referrer_module);
referrer_entry *new, *entries = (referrer_entry *)sconf->referrers->elts;
char *var;
int i, cflags = (int)cmd->info;
/* First, try to merge into an existing entry */
for (i = 0; i < sconf->referrers->nelts; ++i) {
referrer_entry *b = &entries[i];
if (!strcmp(b->name, name)) {
var = getword(cmd->pool, &feature, '=');
if (*feature) table_set(b->referrer_type, var, feature);
else if (*var == '!') table_set(b->referrer_type, var + 1, "!");
else table_set(b->referrer_type, var, "1");
return NULL;
}
}
/* If none was found, create a new entry */
new = push_array(sconf->referrers);
new->name = name;
new->preg = pcalloc(cmd->pool, sizeof(regex_t));
if (regcomp(new->preg, name, REG_EXTENDED|REG_NOSUB|cflags))
return "Referrer regex could not be compiled.";
new->referrer_type = make_table(cmd->pool, 5);
var = getword(cmd->pool, &feature, '=');
if (*feature) table_set(new->referrer_type, var, feature);
else if (*var == '!') table_set(new->referrer_type, var + 1, "!");
else table_set(new->referrer_type, var, "1");
return NULL;
}
command_rec referrer_module_cmds[] = {
{ "ReferrerMatch", add_referrer, (void*)0,
RSRC_CONF, ITERATE2, "A referrer regex and a list of variables." },
{ "ReferrerMatchNoCase", add_referrer, (void*)REG_ICASE,
RSRC_CONF, ITERATE2, "a referrer regex and a list of variables." },
{ NULL },
};
int parse_headers_referrer_module(request_rec *r)
{
server_rec *s = r->server;
referrer_server_config_rec *sconf = get_module_config (s->module_config,
&referrer_module);
referrer_entry *entries = (referrer_entry *)sconf->referrers->elts;
table_entry *elts;
char *ref = table_get(r->headers_in, "Referer");
int i, j;
if (!ref) return DECLINED;
for (i = 0; i < sconf->referrers->nelts; ++i) {
referrer_entry *b = &entries[i];
if (!regexec(b->preg, ref, 0, NULL, 0)) {
elts = (table_entry *)b->referrer_type->elts;
for (j = 0; j < b->referrer_type->nelts; ++j) {
if (!strcmp(elts[j].val, "!"))
table_unset(r->subprocess_env, elts[j].key);
else
table_set(r->subprocess_env, elts[j].key, elts[j].val);
}
}
}
return OK;
}
module referrer_module = {
STANDARD_MODULE_STUFF,
NULL, /* initializer */
NULL, /* dir config creater */
NULL, /* dir merger --- default is to override */
create_referrer_config, /* server config */
merge_referrer_config, /* merge server configs */
referrer_module_cmds, /* command table */
NULL, /* handlers */
NULL, /* filename translation */
NULL, /* check_user_id */
NULL, /* check auth */
NULL, /* check access */
NULL, /* type_checker */
NULL, /* fixups */
NULL, /* logger */
parse_headers_referrer_module /* header parser */
};
Re: NCSA-style 'referer allow' in Apache?
Posted by Dean Gaudet <dg...@arctic.org>.
Didn't Alexei write mod_block for this? (see
/apache/dist/contrib/modules/mod_block.c at any mirror).
I've also seen some cool javascript that fudges with the framesets if
someone, say, tries to embed your page in their frames.
For 2.0 I want to play with a more general syntax for a lot of this config
stuff, there's a few primitives that should give a lot of this for free.
Dean
On Wed, 12 Mar 1997, Rob Hartill wrote:
> On Tue, 11 Mar 1997, David Richards wrote:
>
> > NCSA had a handy access-control feature in the latested (1.5.2.x) server
> > releases where the LIMIT directive could be used to restrict access based
> > on the referer variable, then the 'On-Deny' option could be used to send
> > them to an appropriate page.
> >
> > This is very useful to provide an efficient, automated mechanism for keeping
> > people from inlining your graphics their pages. I know I can do this with
> > a CGI script, but that adds significant server overhead.
> >
> >
> > Is there any good way to implement the following in Apache?
> >
> > <LIMIT GET>
> > order deny,allow
> > deny from all
> >
> > referer allow from http://www.mydomain.com/
> >
> > OnDeny http://www.mydomain.com/EVIL.gif
> > </LIMIT>
>
> there's nothing to do this automatically, but it should be possible to
> create a module to do this from Apache 1.2b7's mod_browser.c. That module
> sets environment variables based on the User-Agent field. Change it to
> look at "Referer" and it'll then let you do something like:
>
> ReferrerMatch http://www.parasite.com/ block_referrers
>
> : : :
>
> ErrorDocument 403 http://www.mydomain.com/EVIL.gif
> order allow,deny
> allow from all
> deny from env=block_referrers
>
> This is all theory, but I think it'll work. No hang on, the theory
> just got turned into practice. A new module is attached.. Enjoy.
>
> regards,
> rob
> --
> Rob Hartill Internet Movie Database (Ltd)
> http://us.imdb.com/Oscars/oscars_1996 - hype free Oscars (R) info.
> http://us.imdb.com/usr/sweepstake - Win a 56k X2 modem. Free draw.
>
>
> -=-=-=-=
>
> Look at the docs for mod_browser.c and use "ReferrerMatch" and
> "ReferrerMatchNoCase" in place of the "BrowserMatch" equivalents.
>
>
> /* ====================================================================
> * Copyright (c) 1997 The Apache Group. All rights reserved.
> *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> *
> * 1. Redistributions of source code must retain the above copyright
> * notice, this list of conditions and the following disclaimer.
> *
> * 2. Redistributions in binary form must reproduce the above copyright
> * notice, this list of conditions and the following disclaimer in
> * the documentation and/or other materials provided with the
> * distribution.
> *
> * 3. All advertising materials mentioning features or use of this
> * software must display the following acknowledgment:
> * "This product includes software developed by the Apache Group
> * for use in the Apache HTTP server project (http://www.apache.org/)."
> *
> * 4. The names "Apache Server" and "Apache Group" must not be used to
> * endorse or promote products derived from this software without
> * prior written permission.
> *
> * 5. Redistributions of any form whatsoever must retain the following
> * acknowledgment:
> * "This product includes software developed by the Apache Group
> * for use in the Apache HTTP server project (http://www.apache.org/)."
> *
> * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
> * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
> * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
> * OF THE POSSIBILITY OF SUCH DAMAGE.
> * ====================================================================
> *
> * This software consists of voluntary contributions made by many
> * individuals on behalf of the Apache Group and was originally based
> * on public domain software written at the National Center for
> * Supercomputing Applications, University of Illinois, Urbana-Champaign.
> * For more information on the Apache Group and the Apache HTTP server
> * project, please see <http://www.apache.org/>.
> *
> */
>
> /*
> * mod_check_referer.c
> * Set environment variables based on the 'Referer' header.
> *
> * Rob Hartill <ro...@imdb.com>
> * this is basicaly a rip-off of Alexei Kosut's mod_browser.c
> */
>
> #include "httpd.h"
> #include "http_config.h"
>
> typedef struct {
> char *name;
> regex_t *preg;
> table *referrer_type;
> } referrer_entry;
>
> typedef struct {
> array_header *referrers;
> } referrer_server_config_rec;
>
> module referrer_module;
>
> void *create_referrer_config (pool *p, server_rec *dummy)
> {
> referrer_server_config_rec *new =
> (referrer_server_config_rec *) palloc (p, sizeof(referrer_server_config_rec));
>
> new->referrers = make_array (p, 20, sizeof(referrer_entry));
> return (void *)new;
> }
>
> void *merge_referrer_config (pool *p, void *basev, void *overridesv)
> {
> referrer_server_config_rec *a =
> pcalloc(p, sizeof(referrer_server_config_rec));
> referrer_server_config_rec *base = basev, *overrides = overridesv;
>
> a->referrers = append_arrays(p, base->referrers, overrides->referrers);
> return a;
> }
>
> const char *add_referrer(cmd_parms *cmd, void *dummy, char *name,
> const char *feature)
> {
> referrer_server_config_rec *sconf =
> get_module_config (cmd->server->module_config, &referrer_module);
> referrer_entry *new, *entries = (referrer_entry *)sconf->referrers->elts;
> char *var;
> int i, cflags = (int)cmd->info;
>
> /* First, try to merge into an existing entry */
>
> for (i = 0; i < sconf->referrers->nelts; ++i) {
> referrer_entry *b = &entries[i];
> if (!strcmp(b->name, name)) {
> var = getword(cmd->pool, &feature, '=');
> if (*feature) table_set(b->referrer_type, var, feature);
> else if (*var == '!') table_set(b->referrer_type, var + 1, "!");
> else table_set(b->referrer_type, var, "1");
> return NULL;
> }
> }
>
> /* If none was found, create a new entry */
>
> new = push_array(sconf->referrers);
> new->name = name;
> new->preg = pcalloc(cmd->pool, sizeof(regex_t));
> if (regcomp(new->preg, name, REG_EXTENDED|REG_NOSUB|cflags))
> return "Referrer regex could not be compiled.";
> new->referrer_type = make_table(cmd->pool, 5);
>
> var = getword(cmd->pool, &feature, '=');
> if (*feature) table_set(new->referrer_type, var, feature);
> else if (*var == '!') table_set(new->referrer_type, var + 1, "!");
> else table_set(new->referrer_type, var, "1");
>
> return NULL;
> }
>
> command_rec referrer_module_cmds[] = {
> { "ReferrerMatch", add_referrer, (void*)0,
> RSRC_CONF, ITERATE2, "A referrer regex and a list of variables." },
> { "ReferrerMatchNoCase", add_referrer, (void*)REG_ICASE,
> RSRC_CONF, ITERATE2, "a referrer regex and a list of variables." },
> { NULL },
> };
>
> int parse_headers_referrer_module(request_rec *r)
> {
> server_rec *s = r->server;
> referrer_server_config_rec *sconf = get_module_config (s->module_config,
> &referrer_module);
> referrer_entry *entries = (referrer_entry *)sconf->referrers->elts;
> table_entry *elts;
> char *ref = table_get(r->headers_in, "Referer");
> int i, j;
>
> if (!ref) return DECLINED;
>
> for (i = 0; i < sconf->referrers->nelts; ++i) {
> referrer_entry *b = &entries[i];
>
> if (!regexec(b->preg, ref, 0, NULL, 0)) {
> elts = (table_entry *)b->referrer_type->elts;
>
> for (j = 0; j < b->referrer_type->nelts; ++j) {
> if (!strcmp(elts[j].val, "!"))
> table_unset(r->subprocess_env, elts[j].key);
> else
> table_set(r->subprocess_env, elts[j].key, elts[j].val);
> }
> }
> }
>
> return OK;
> }
>
> module referrer_module = {
> STANDARD_MODULE_STUFF,
> NULL, /* initializer */
> NULL, /* dir config creater */
> NULL, /* dir merger --- default is to override */
> create_referrer_config, /* server config */
> merge_referrer_config, /* merge server configs */
> referrer_module_cmds, /* command table */
> NULL, /* handlers */
> NULL, /* filename translation */
> NULL, /* check_user_id */
> NULL, /* check auth */
> NULL, /* check access */
> NULL, /* type_checker */
> NULL, /* fixups */
> NULL, /* logger */
> parse_headers_referrer_module /* header parser */
> };
>
>