2012-05-21 19:08:04 +01:00
/*
* mod_blockinator for Apache v2 .2
*
* Author : Scott Wallace < scott @ suborbit . com >
* Date : March 2012
*
* Written for European Directories to integrate traffic
* blocking based upon recommendations from a Sentor
* device .
*
* The SQLite DB is populated with a Python script that
* can be found at ,
* http : //svn.eurodir.eu/svn/common/trunk/scripts/blockinator/trunk/
*
*/
# include "httpd.h"
# include "http_config.h"
# include "http_log.h"
# include <sqlite3.h>
module AP_MODULE_DECLARE_DATA blockinator_module ;
/*
* Global variables for use everywhere
*/
sqlite3 * db ;
typedef struct {
const char * db ;
} blockinator_cfg_t ;
/*
* Function to build the configuration for the module
*/
static void * create_blockinator_config ( apr_pool_t * p , server_rec * s )
{
/* Allocate some memory using the proper Apache function */
blockinator_cfg_t * mod_config = apr_pcalloc ( p , sizeof ( blockinator_cfg_t ) ) ;
return mod_config ;
}
/*
* Function to set the configuration item , ' db '
*/
static const char * blockinator_set_config_db ( cmd_parms * parms , void * mconfig , const char * arg )
{
blockinator_cfg_t * cfg = ap_get_module_config ( parms - > server - > module_config , & blockinator_module ) ;
cfg - > db = ( char * ) arg ;
return NULL ;
}
/*
* Main HTTP request handler
*/
static int mod_blockinator_method_handler ( request_rec * r )
{
2012-11-08 14:03:38 +00:00
const char * remote_ip , * forwarded_ip , * useragent ;
2012-05-21 19:08:04 +01:00
char * statement ;
sqlite3_stmt * sqlite3_statement ;
2012-11-08 14:03:38 +00:00
int sqlite3_rc ;
2012-05-21 19:08:04 +01:00
/* Capture the relevant information from the inbound request */
remote_ip = r - > connection - > remote_ip ;
forwarded_ip = apr_table_get ( r - > headers_in , " X-Forwarded-For " ) ;
useragent = apr_table_get ( r - > headers_in , " User-Agent " ) ;
2012-11-08 14:03:38 +00:00
if ( forwarded_ip = = NULL ) {
forwarded_ip = " (null) " ;
}
if ( useragent = = NULL ) {
useragent = " (null) " ;
}
2012-05-21 19:08:04 +01:00
/* Build the SQL statement */
2012-11-08 14:03:38 +00:00
statement = sqlite3_mprintf ( " SELECT * FROM blocklist WHERE remote_ip = '%q' AND (forwarded_ip = 'ANY' OR forwarded_ip = '%q') AND (useragent = 'ANY' OR useragent = '%q') " , remote_ip , forwarded_ip , useragent ) ;
2012-05-21 19:08:04 +01:00
/* Prepare the statement */
2012-12-19 15:27:41 +00:00
sqlite3_rc = sqlite3_prepare_v2 ( db , statement , - 1 , & sqlite3_statement , NULL ) ;
2012-11-08 14:03:38 +00:00
if ( sqlite3_rc ! = SQLITE_OK ) {
2012-05-21 19:08:04 +01:00
/* SQLite error. Allow. */
2012-11-08 14:03:38 +00:00
ap_log_rerror ( APLOG_MARK , APLOG_ERR , 0 , r , " SQLite error (%s). Allow traffic from %s by default. " , sqlite3_errmsg ( db ) , remote_ip ) ;
2012-05-21 19:08:04 +01:00
return DECLINED ;
}
/* Check for any results. */
if ( sqlite3_step ( sqlite3_statement ) = = SQLITE_ROW ) {
/* SQLite results. Time to block. */
2012-11-08 14:03:38 +00:00
ap_log_rerror ( APLOG_MARK , APLOG_WARNING , 0 , r , " Blocklist match. (Forwarded_IP: %s, User-Agent: %s) " , forwarded_ip , useragent ) ;
2012-05-21 19:08:04 +01:00
apr_table_set ( r - > headers_in , " X-Block " , " 1 " ) ;
}
/* Tidy-up the SQLite way. */
if ( sqlite3_finalize ( sqlite3_statement ) ! = SQLITE_OK ) {
2012-11-20 14:53:18 +00:00
ap_log_rerror ( APLOG_MARK , APLOG_WARNING , 0 , r , " SQLite error freeing the SQLite compile statement (%s). Possible memory leak. " , sqlite3_errmsg ( db ) ) ;
2012-05-21 19:08:04 +01:00
}
2012-11-20 14:53:18 +00:00
sqlite3_free ( statement ) ;
2012-05-21 19:08:04 +01:00
return DECLINED ;
}
/*
* Module initialiser
*/
static void mod_blockinator_init_handler ( apr_pool_t * p , server_rec * s )
{
/* Read config from module */
blockinator_cfg_t * cfg = ap_get_module_config ( s - > module_config , & blockinator_module ) ;
/* Open the SQLite DB */
2012-11-08 14:03:38 +00:00
ap_log_error ( APLOG_MARK , APLOG_INFO , 0 , s , " Opening mod_blockinator blocklist DB: %s. " , cfg - > db ) ;
2012-08-29 10:50:08 +01:00
if ( sqlite3_open_v2 ( cfg - > db , & db , SQLITE_OPEN_READONLY , " unix-none " ) ) {
2012-05-21 19:08:04 +01:00
/* Error. */
ap_log_error ( APLOG_MARK , APLOG_ERR , 0 , s , " mod_blockinator: SQLite error (%s). Could not open database. " , sqlite3_errmsg ( db ) ) ;
}
}
/*
* Register hooks
*/
static void register_hooks ( apr_pool_t * p )
{
/* Register the module initialiser */
ap_hook_child_init ( mod_blockinator_init_handler , NULL , NULL , APR_HOOK_LAST ) ;
/* Register the module header parser in the post_read_request phase of Apache */
ap_hook_post_read_request ( mod_blockinator_method_handler , NULL , NULL , APR_HOOK_FIRST ) ;
}
/*
* Apache configuration directives
*/
static const command_rec mod_blockinator_directives [ ] = {
AP_INIT_TAKE1 (
" BlockinatorBlocklistDB " ,
blockinator_set_config_db ,
NULL ,
RSRC_CONF ,
" BlockinatorBlocklistDB (filepath). The absolute path of Blockinator blocklist SQLite DB. "
) ,
{ NULL }
} ;
/*
* Main module code
*/
module AP_MODULE_DECLARE_DATA blockinator_module = {
STANDARD20_MODULE_STUFF ,
NULL , /* create per-directory config structures */
NULL , /* merge per-directory config structures */
create_blockinator_config , /* create per-server config structures */
NULL , /* merge per-server config structures */
mod_blockinator_directives , /* command handlers */
register_hooks /* register hooks */
} ;