This commit is contained in:
+102
-93
@@ -23,7 +23,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
@@ -55,16 +54,18 @@ extern struct siproxd_config configuration;
|
||||
static struct plugin_config {
|
||||
char *dbpath; /* path to sqlite DB file (/var/lib/siproxd/bl.db */
|
||||
int block_mode; /* 0: no, 1: IP based, 2: IP & SIP-user */
|
||||
int block_duration; /* in seconds, 0: forever, dont' expire */
|
||||
int block_hitcount; /* required attempts until blocked */
|
||||
int simulate; /* 0: no, 1: don't block, just log */
|
||||
int duration; /* in seconds, 0: forever, dont' expire */
|
||||
int hitcount; /* required attempts until blocked */
|
||||
} plugin_cfg;
|
||||
|
||||
/* Instructions for config parser */
|
||||
static cfgopts_t plugin_cfg_opts[] = {
|
||||
{ "plugin_blacklist_dbpath", TYP_STRING, &plugin_cfg.dbpath, {0, "/var/lib/siproxd/blacklist.sqlite"} },
|
||||
{ "plugin_blacklist_mode", TYP_INT4, &plugin_cfg.block_mode, {0, NULL} },
|
||||
{ "plugin_blacklist_duration", TYP_INT4, &plugin_cfg.block_duration, {3600, NULL} },
|
||||
{ "plugin_blacklist_hitcount", TYP_INT4, &plugin_cfg.block_hitcount, {10, NULL} },
|
||||
{ "plugin_blacklist_dbpath", TYP_STRING, &plugin_cfg.dbpath, {0, "/var/lib/siproxd/blacklist.sqlite"} },
|
||||
{ "plugin_blacklist_mode", TYP_INT4, &plugin_cfg.block_mode, {0, NULL} },
|
||||
{ "plugin_blacklist_simulate", TYP_INT4, &plugin_cfg.simulate, {0, NULL} },
|
||||
{ "plugin_blacklist_duration", TYP_INT4, &plugin_cfg.duration, {3600, NULL} },
|
||||
{ "plugin_blacklist_hitcount", TYP_INT4, &plugin_cfg.hitcount, {10, NULL} },
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -83,9 +84,18 @@ static sql_statement_t sql_statement[] = {
|
||||
{ 0, NULL, "SELECT count(id) from blacklist WHERE ip=?001 and sipuri=?002 AND failcount>?003;" },
|
||||
{ 1, NULL, "UPDATE OR IGNORE blacklist SET lastseen=?003 WHERE ip=?001 and sipuri=?002;" },
|
||||
/* blacklist_update_fail() */
|
||||
{ 2, NULL, "INSERT OR IGNORE INTO blacklist (ip, sipuri, failcount, lastseen, lastfail) VALUES (?001, ?002, 0, ?003, ?003);" },
|
||||
{ 2, NULL, "INSERT OR IGNORE INTO blacklist (ip, sipuri) VALUES (?001, ?002);" },
|
||||
{ 3, NULL, "UPDATE OR IGNORE blacklist SET failcount=failcount+1, lastseen=?003, lastfail=?003 WHERE ip=?001 and sipuri=?002;" },
|
||||
{ 4, NULL, "UPDATE OR IGNORE blacklist SET lastseen=?003 WHERE ip=?001 and sipuri=?002;" },
|
||||
{ 5, NULL, "UPDATE OR IGNORE blacklist SET failcount=0, lastseen=?003 WHERE ip=?001 and sipuri=?002;" },
|
||||
};
|
||||
#define SQL_CHECK_1 0
|
||||
#define SQL_CHECK_2 1
|
||||
|
||||
#define SQL_UPDATE_FAIL_1 2 /* insert new record to DB */
|
||||
#define SQL_UPDATE_FAIL_2 3 /* increment failcount */
|
||||
#define SQL_UPDATE_FAIL_3 4 /* just update lastseen */
|
||||
#define SQL_UPDATE_FAIL_4 5 /* reset failcount upon successful registration */
|
||||
|
||||
/* string magic in C preprocessor */
|
||||
#define xstr(s) str(s)
|
||||
@@ -128,10 +138,10 @@ blacklist
|
||||
static int blacklist_check(sip_ticket_t *ticket);
|
||||
static int blacklist_update_fail(sip_ticket_t *ticket);
|
||||
static int blacklist_expire(sip_ticket_t *ticket);
|
||||
|
||||
static int blacklist_sqlite_begin(void);
|
||||
static int blacklist_sqlite_end(void);
|
||||
static int blacklict_exec_prep_query_int(sqlite3_stmt *stmt1, int *retval);
|
||||
/* helpers */
|
||||
static int sqlite_begin(void);
|
||||
static int sqlite_end(void);
|
||||
static int sqlite_exec_stmt_int(sql_statement_t *sql_statement, int *retval);
|
||||
|
||||
/*
|
||||
* Initialization.
|
||||
@@ -159,12 +169,10 @@ int PLUGIN_INIT(plugin_def_t *plugin_def) {
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
if (blacklist_sqlite_begin() != STS_SUCCESS) {
|
||||
if (sqlite_begin() != STS_SUCCESS) {
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
blacklist_check(NULL);
|
||||
INFO("plugin_blacklist is initialized (sqlite version %s)", sqlite3_libversion());
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
@@ -177,6 +185,11 @@ int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){
|
||||
int sts;
|
||||
/* stage contains the PLUGIN_* value - the stage of SIP processing. */
|
||||
DEBUGC(DBCLASS_BABBLE, "plugin_blacklist: processing - stage %i",stage);
|
||||
DEBUGC(DBCLASS_BABBLE, "plugin_blacklist: MSG_IS_REQUEST %i",MSG_IS_REQUEST(ticket->sipmsg));
|
||||
DEBUGC(DBCLASS_BABBLE, "plugin_blacklist: MSG_IS_RESPONSE %i",MSG_IS_RESPONSE(ticket->sipmsg));
|
||||
DEBUGC(DBCLASS_BABBLE, "plugin_blacklist: MSG_IS_REGISTER %i",MSG_IS_REGISTER(ticket->sipmsg));
|
||||
DEBUGC(DBCLASS_BABBLE, "plugin_blacklist: MSG_IS_RESPONSE_FOR(REGISTER) %i",MSG_IS_RESPONSE_FOR(ticket->sipmsg,"REGISTER"));
|
||||
DEBUGC(DBCLASS_BABBLE, "plugin_blacklist: MSG_IS_STATUS_4XX %i",MSG_IS_STATUS_4XX(ticket->sipmsg));
|
||||
|
||||
if ((stage == PLUGIN_VALIDATE)
|
||||
&& MSG_IS_REQUEST(ticket->sipmsg)) {
|
||||
@@ -186,7 +199,7 @@ int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){
|
||||
}
|
||||
} else if ((stage == PLUGIN_POST_PROXY)
|
||||
&& MSG_IS_RESPONSE(ticket->sipmsg)
|
||||
&& MSG_IS_REGISTER(ticket->sipmsg)) {
|
||||
&& MSG_IS_RESPONSE_FOR(ticket->sipmsg, "REGISTER")) {
|
||||
sts = blacklist_update_fail(ticket);
|
||||
}
|
||||
|
||||
@@ -202,7 +215,7 @@ int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){
|
||||
int PLUGIN_END(plugin_def_t *plugin_def){
|
||||
int sts;
|
||||
|
||||
sts = blacklist_sqlite_end();
|
||||
sts = sqlite_end();
|
||||
|
||||
INFO("plugin_blacklist ends here");
|
||||
return STS_SUCCESS;
|
||||
@@ -212,48 +225,27 @@ int PLUGIN_END(plugin_def_t *plugin_def){
|
||||
/* private plugin code */
|
||||
static int blacklist_check(sip_ticket_t *ticket) {
|
||||
int sts;
|
||||
sqlite3_stmt *stmt1 = sql_statement[0].stmt;
|
||||
sqlite3_stmt *stmt2 = sql_statement[1].stmt;
|
||||
int retval=0;
|
||||
sql_statement_t *sql_stmt = NULL;
|
||||
|
||||
DEBUGC(DBCLASS_BABBLE, "entering blacklist_check");
|
||||
|
||||
/* bind */
|
||||
sts = sqlite3_bind_text(stmt1, 001, "1.2.3.4", -1, SQLITE_STATIC);
|
||||
sts = sqlite3_bind_text(stmt1, 002, "foo@bar.org", -1, SQLITE_STATIC);
|
||||
sts = sqlite3_bind_int(stmt1, 003, plugin_cfg.block_hitcount);
|
||||
sql_stmt = &sql_statement[SQL_CHECK_1];
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 001, "1.2.3.4", -1, SQLITE_TRANSIENT);
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 002, "foo@bar.org", -1, SQLITE_TRANSIENT);
|
||||
sts = sqlite3_bind_int(sql_stmt->stmt, 003, plugin_cfg.hitcount);
|
||||
/* execute & eval result */
|
||||
do {
|
||||
sts = sqlite3_step(stmt1);
|
||||
if (sts == SQLITE_ROW) {
|
||||
INFO("Blacklist Lookup returned %i matches", sqlite3_column_int(stmt1, 0));
|
||||
}
|
||||
} while (sts == SQLITE_ROW);
|
||||
if ( sts == SQLITE_ERROR) {
|
||||
sts = sqlite3_reset(stmt1);
|
||||
ERROR("SQL step error [%i]: %s\n", sts, sqlite3_errmsg(db));
|
||||
} else if ( sts != SQLITE_DONE ) {
|
||||
ERROR("SQL step error [%i]: %s\n", sts, sqlite3_errmsg(db));
|
||||
}
|
||||
/* cleanup */
|
||||
sts = sqlite3_reset(stmt1);
|
||||
|
||||
sts = sqlite_exec_stmt_int(sql_stmt, &retval);
|
||||
sql_stmt = NULL;
|
||||
|
||||
/* bind */
|
||||
sts = sqlite3_bind_text(stmt2, 001, "1.2.3.4", -1, SQLITE_STATIC);
|
||||
sts = sqlite3_bind_text(stmt2, 002, "foo@bar.org", -1, SQLITE_STATIC);
|
||||
sts = sqlite3_bind_int(stmt2, 003, time(NULL));
|
||||
/* execute & eval result */
|
||||
do {
|
||||
sts = sqlite3_step(stmt2);
|
||||
} while (sts == SQLITE_ROW);
|
||||
if ( sts == SQLITE_ERROR) {
|
||||
sts = sqlite3_reset(stmt2);
|
||||
ERROR("SQL step error [%i]: %s\n", sts, sqlite3_errmsg(db));
|
||||
} else if ( sts != SQLITE_DONE ) {
|
||||
ERROR("SQL step error [%i]: %s\n", sts, sqlite3_errmsg(db));
|
||||
}
|
||||
/* cleanup */
|
||||
sts = sqlite3_reset(stmt2);
|
||||
sql_stmt = &sql_statement[SQL_CHECK_2];
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 001, "1.2.3.4", -1, SQLITE_TRANSIENT);
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 002, "foo@bar.org", -1, SQLITE_TRANSIENT);
|
||||
sts = sqlite3_bind_int(sql_stmt->stmt, 003, ticket->timestamp);
|
||||
sts = sqlite_exec_stmt_int(sql_stmt, &retval);
|
||||
sql_stmt = NULL;
|
||||
|
||||
// not present in 3.3.6 sts = sqlite3_clear_bindings(stmt1);
|
||||
|
||||
@@ -283,51 +275,45 @@ static int blacklist_check(sip_ticket_t *ticket) {
|
||||
|
||||
static int blacklist_update_fail(sip_ticket_t *ticket) {
|
||||
int sts;
|
||||
sqlite3_stmt *stmt11 = sql_statement[2].stmt;
|
||||
sqlite3_stmt *stmt12 = sql_statement[3].stmt;
|
||||
int retval=0;
|
||||
sql_statement_t *sql_stmt = NULL;
|
||||
|
||||
DEBUGC(DBCLASS_BABBLE, "entering blacklist_update_fail");
|
||||
|
||||
|
||||
/* bind */
|
||||
//&&& fetch UAC IP from telegram
|
||||
//&&& fetch SIP URI (contact?) from telegram
|
||||
sts = sqlite3_bind_text(stmt11, 001, "1.2.3.4", -1, SQLITE_STATIC);
|
||||
sts = sqlite3_bind_text(stmt11, 002, "foo@bar.org", -1, SQLITE_STATIC);
|
||||
sts = sqlite3_bind_int(stmt11, 003, time(NULL));
|
||||
/* execute & eval result */
|
||||
do {
|
||||
sts = sqlite3_step(stmt11);
|
||||
} while (sts == SQLITE_ROW);
|
||||
if ( sts == SQLITE_ERROR) {
|
||||
sts = sqlite3_reset(stmt11);
|
||||
ERROR("SQL step error [%i]: %s\n", sts, sqlite3_errmsg(db));
|
||||
} else if ( sts != SQLITE_DONE ) {
|
||||
ERROR("SQL step error [%i]: %s\n", sts, sqlite3_errmsg(db));
|
||||
if (MSG_IS_STATUS_4XX(ticket->sipmsg)) {
|
||||
/* bind */
|
||||
sql_stmt = &sql_statement[SQL_UPDATE_FAIL_1];
|
||||
//&&& fetch UAC IP from telegram
|
||||
//&&& fetch SIP URI (contact?) from telegram
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 001, "1.2.3.41", -1, SQLITE_TRANSIENT);
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 002, "foo@bar.org", -1, SQLITE_TRANSIENT);
|
||||
sts = sqlite_exec_stmt_int(sql_stmt, &retval);
|
||||
sql_stmt = NULL;
|
||||
}
|
||||
/* cleanup */
|
||||
sts = sqlite3_reset(stmt11);
|
||||
|
||||
|
||||
/* bind */
|
||||
//&&& fetch UAC IP from telegram
|
||||
//&&& fetch SIP URI (contact?) from telegram
|
||||
sts = sqlite3_bind_text(stmt12, 001, "1.2.3.4", -1, SQLITE_STATIC);
|
||||
sts = sqlite3_bind_text(stmt12, 002, "foo@bar.org", -1, SQLITE_STATIC);
|
||||
sts = sqlite3_bind_int(stmt12, 003, time(NULL));
|
||||
/* execute & eval result */
|
||||
do {
|
||||
sts = sqlite3_step(stmt12);
|
||||
} while (sts == SQLITE_ROW);
|
||||
if ( sts == SQLITE_ERROR) {
|
||||
sts = sqlite3_reset(stmt12);
|
||||
ERROR("SQL step error [%i]: %s\n", sts, sqlite3_errmsg(db));
|
||||
} else if ( sts != SQLITE_DONE ) {
|
||||
ERROR("SQL step error [%i]: %s\n", sts, sqlite3_errmsg(db));
|
||||
sql_stmt = NULL;
|
||||
if (MSG_IS_STATUS_4XX(ticket->sipmsg)) {
|
||||
/* REGISTER 4xx failure: increment error counter */
|
||||
sql_stmt = &sql_statement[SQL_UPDATE_FAIL_2];
|
||||
} else if (MSG_IS_STATUS_2XX(ticket->sipmsg)) {
|
||||
/* REGISTER 2xx success: set error counter to 0 */
|
||||
sql_stmt = &sql_statement[SQL_UPDATE_FAIL_4];
|
||||
} else {
|
||||
/* update last-seen */
|
||||
sql_stmt = &sql_statement[SQL_UPDATE_FAIL_3];
|
||||
}
|
||||
if (sql_stmt) {
|
||||
/* bind */
|
||||
//&&& fetch UAC IP from telegram
|
||||
//&&& fetch SIP URI (contact?) from telegram
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 001, "1.2.3.41", -1, SQLITE_TRANSIENT);
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 002, "foo@bar.org", -1, SQLITE_TRANSIENT);
|
||||
sts = sqlite3_bind_int(sql_stmt->stmt, 003, ticket->timestamp);
|
||||
/* execute query */
|
||||
sts = sqlite_exec_stmt_int(sql_stmt, &retval);
|
||||
sql_stmt = NULL;
|
||||
}
|
||||
/* cleanup */
|
||||
sts = sqlite3_reset(stmt12);
|
||||
|
||||
|
||||
/* INSERT OR IGNORE records to DB: IP, sipuri */
|
||||
/* UPDATE records failcount=failcount+1, lastseen=now, lastfail=now */
|
||||
@@ -351,7 +337,7 @@ static int blacklist_expire(sip_ticket_t *ticket) {
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/* helper functions */
|
||||
static int blacklist_sqlite_begin(void){
|
||||
static int sqlite_begin(void){
|
||||
int sts;
|
||||
int i;
|
||||
char *zErrMsg = NULL;
|
||||
@@ -409,7 +395,7 @@ static int blacklist_sqlite_begin(void){
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
static int blacklist_sqlite_end(void){
|
||||
static int sqlite_end(void){
|
||||
int sts;
|
||||
int i;
|
||||
char *zErrMsg = NULL;
|
||||
@@ -436,7 +422,30 @@ static int blacklist_sqlite_end(void){
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
static int blacklict_exec_prep_query_int(sqlite3_stmt *stmt1, int *retval){
|
||||
static int sqlite_exec_stmt_int(sql_statement_t *sql_statement, int *retval){
|
||||
int sts;
|
||||
|
||||
/* execute & eval result */
|
||||
DEBUGC(DBCLASS_BABBLE, "executing query [%s]", sql_statement->sql_query);
|
||||
do {
|
||||
sts = sqlite3_step(sql_statement->stmt);
|
||||
if (sts == SQLITE_ROW) {
|
||||
if (retval != NULL) {
|
||||
*retval = sqlite3_column_int(sql_statement->stmt, 0);
|
||||
DEBUGC(DBCLASS_BABBLE, "sqlite_exec_stmt_int: query returned INT %i", *retval);
|
||||
}
|
||||
}
|
||||
} while (sts == SQLITE_ROW);
|
||||
if ( sts == SQLITE_ERROR) {
|
||||
sts = sqlite3_reset(sql_statement->stmt);
|
||||
ERROR("SQL step error [%i]: %s\n", sts, sqlite3_errmsg(db));
|
||||
} else if ( sts != SQLITE_DONE ) {
|
||||
ERROR("SQL step error [%i]: %s\n", sts, sqlite3_errmsg(db));
|
||||
}
|
||||
/* cleanup */
|
||||
sts = sqlite3_reset(sql_statement->stmt);
|
||||
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
//&&& implement cache of open REGISTER requests, only honor failed REGISTERS responses where a
|
||||
|
||||
Reference in New Issue
Block a user