From 8728c7e6d1318fc630858955c421452210959307 Mon Sep 17 00:00:00 2001 From: Thomas Ries Date: Sat, 12 Aug 2017 09:50:11 +0000 Subject: [PATCH] --- src/plugin_blacklist.c | 123 ++++++++++++++++++++++++++++++++--------- 1 file changed, 97 insertions(+), 26 deletions(-) diff --git a/src/plugin_blacklist.c b/src/plugin_blacklist.c index b9d41cf..e747b2f 100644 --- a/src/plugin_blacklist.c +++ b/src/plugin_blacklist.c @@ -31,6 +31,9 @@ #include #include +#include +#include + #include #include "siproxd.h" @@ -95,7 +98,9 @@ static sql_statement_t sql_statement[] = { { 7, NULL, "UPDATE OR IGNORE blacklist SET failcount=failcount+1, lastseen=?003, lastfail=?003 WHERE type=0 and ip=?001 and sipuri=?002;" }, { 8, NULL, "UPDATE OR IGNORE blacklist SET lastseen=?003 WHERE ip=?001 and sipuri=?002;" }, { 9, NULL, "UPDATE OR IGNORE blacklist SET failcount=0, lastseen=?003 WHERE type=0 and ip=?001 and sipuri=?002;" }, - { 10, NULL, "UPDATE OR IGNORE blacklist SET failcount=0 WHERE type=0 and failcount?001 and lastseenexe_mask=PLUGIN_VALIDATE | PLUGIN_POST_PROXY; + plugin_def->exe_mask=PLUGIN_VALIDATE | PLUGIN_POST_PROXY | PLUGIN_TIMER; /* read the config file */ if (read_config(configuration.configfile, @@ -213,22 +218,33 @@ 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); + if (ticket) { 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) + && ticket && MSG_IS_REQUEST(ticket->sipmsg)) { sts = blacklist_check(ticket); if (sts != STS_SUCCESS) { return STS_FAILURE; } } else if ((stage == PLUGIN_POST_PROXY) + && ticket && MSG_IS_RESPONSE(ticket->sipmsg) && MSG_IS_RESPONSE_FOR(ticket->sipmsg, "REGISTER")) { sts = blacklist_update(ticket); + } else if ((stage == PLUGIN_TIMER)) { + static int count=0; + /*&&&TODO: hmmm, still hardcoded... will be executed once per minute */ + if (++count >= 12) { + count=0; + sts = blacklist_expire(ticket); + } } return STS_SUCCESS; @@ -245,7 +261,7 @@ int PLUGIN_END(plugin_def_t *plugin_def){ sts = sqlite_end(); - INFO("plugin_blacklist ends here"); + INFO("plugin_blacklist ends here, sts=%i", sts); return STS_SUCCESS; } @@ -282,20 +298,29 @@ static int blacklist_check(sip_ticket_t *ticket) { /* bind */ sql_stmt = &sql_statement[SQL_CHECK_1]; sts = sqlite3_bind_text(sql_stmt->stmt, 001, srcip, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 002, from, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_int(sql_stmt->stmt, 003, plugin_cfg.hitcount); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_int failed with %i", sts); } /* execute & eval result */ sts = sqlite_exec_stmt_int(sql_stmt, &retval); /* retval: nunber of records found that */ /* the blocked query */ + if( sts != STS_SUCCESS ){ WARN("sqlite_exec_stmt_int failed with %i", sts); } sql_stmt = NULL; /* Query 2: UPDATE (last seen TS) */ /* bind */ sql_stmt = &sql_statement[SQL_CHECK_2]; sts = sqlite3_bind_text(sql_stmt->stmt, 001, srcip, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 002, from, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_int(sql_stmt->stmt, 003, ticket->timestamp); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_int failed with %i", sts); } + /* execute & eval result */ sts = sqlite_exec_stmt_none(sql_stmt); + if( sts != STS_SUCCESS ){ WARN("sqlite_exec_stmt_none failed with %i", sts); } sql_stmt = NULL; if (MSG_IS_REGISTER(ticket->sipmsg)) { @@ -310,19 +335,32 @@ static int blacklist_check(sip_ticket_t *ticket) { /* bind */ sql_stmt = &sql_statement[SQL_CHECK_3]; sts = sqlite3_bind_int(sql_stmt->stmt, 001, ticket->timestamp); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_int failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 002, srcip, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 003, from, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 004, call_id,-1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } + /* execute & eval result */ sts = sqlite_exec_stmt_none(sql_stmt); + if( sts != STS_SUCCESS ){ WARN("sqlite_exec_stmt_none failed with %i", sts); } sql_stmt = NULL; - /* Query 3: INSERT OR IGNORE REGISTER request into requests DB */ + + /* Query 4: INSERT OR IGNORE REGISTER request into requests DB */ /* bind */ sql_stmt = &sql_statement[SQL_CHECK_4]; sts = sqlite3_bind_int(sql_stmt->stmt, 001, ticket->timestamp); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_int failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 002, srcip, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 003, from, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 004, call_id,-1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } + /* execute & eval result */ sts = sqlite_exec_stmt_none(sql_stmt); + if( sts != STS_SUCCESS ){ WARN("sqlite_exec_stmt_none failed with %i", sts); } sql_stmt = NULL; } @@ -361,7 +399,10 @@ static int blacklist_update(sip_ticket_t *ticket) { /* bind */ sql_stmt = &sql_statement[SQL_UPDATE_1]; sts = sqlite3_bind_int(sql_stmt->stmt, 001, ticket->timestamp - plugin_cfg.register_window); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_int failed with %i", sts); } + /* execute & eval result */ sts = sqlite_exec_stmt_none(sql_stmt); + if( sts != STS_SUCCESS ){ WARN("sqlite_exec_stmt_none failed with %i", sts); } sql_stmt = NULL; /* get target IP address as string */ @@ -383,9 +424,14 @@ static int blacklist_update(sip_ticket_t *ticket) { /* bind */ sql_stmt = &sql_statement[SQL_UPDATE_2]; sts = sqlite3_bind_text(sql_stmt->stmt, 001, dstip, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 002, from, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 003, call_id, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } + /* execute & eval result */ sts = sqlite_exec_stmt_int(sql_stmt, &retval); + if( sts != STS_SUCCESS ){ WARN("sqlite_exec_stmt_int failed with %i", sts); } sql_stmt = NULL; if (retval > 0) { @@ -398,8 +444,12 @@ static int blacklist_update(sip_ticket_t *ticket) { /* bind */ sql_stmt = &sql_statement[SQL_UPDATE_3]; sts = sqlite3_bind_text(sql_stmt->stmt, 001, dstip, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 002, from, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } + /* execute & eval result */ sts = sqlite_exec_stmt_int(sql_stmt, &retval); + if( sts != STS_SUCCESS ){ WARN("sqlite_exec_stmt_int failed with %i", sts); } sql_stmt = NULL; } @@ -421,47 +471,71 @@ static int blacklist_update(sip_ticket_t *ticket) { /* Query 4/5/6 */ /* bind */ sts = sqlite3_bind_text(sql_stmt->stmt, 001, dstip, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_text(sql_stmt->stmt, 002, from, -1, SQLITE_TRANSIENT); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_text failed with %i", sts); } sts = sqlite3_bind_int(sql_stmt->stmt, 003, ticket->timestamp); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_int failed with %i", sts); } /* execute query */ sts = sqlite_exec_stmt_none(sql_stmt); + if( sts != STS_SUCCESS ){ WARN("sqlite_exec_stmt_int failed with %i", sts); } sql_stmt = NULL; } } /* if Q2 true */ - /* expire old blacklist records */ - /* Query7 */ - /* bind */ - sql_stmt = &sql_statement[SQL_UPDATE_7]; - sts = sqlite3_bind_int(sql_stmt->stmt, 001, plugin_cfg.hitcount); - sts = sqlite3_bind_int(sql_stmt->stmt, 002, ticket->timestamp-plugin_cfg.duration); - /* execute query */ - sts = sqlite_exec_stmt_none(sql_stmt); - sql_stmt = NULL; - /* free resources */ osip_free(from); - DEBUGC(DBCLASS_BABBLE, "leaving blacklist_update"); return STS_SUCCESS; } -#if 0 static int blacklist_expire(sip_ticket_t *ticket) { -// int sts; -// char *zErrMsg = NULL; + int sts; + sql_statement_t *sql_stmt = NULL; + time_t now; DEBUGC(DBCLASS_BABBLE, "entering blacklist_expire"); + + time(&now); + /* set failcount=0 for all records where last_seen is older than block_period */ /* or remove records */ + /* expire old blacklist records (if config.duration > 0)*/ + if (plugin_cfg.duration > 0) { + /* Query7 */ + /* bind */ + sql_stmt = &sql_statement[SQL_EXPIRE_1]; + sts = sqlite3_bind_int(sql_stmt->stmt, 001, plugin_cfg.hitcount); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_int failed with %i", sts); } + sts = sqlite3_bind_int(sql_stmt->stmt, 002, now-plugin_cfg.duration); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_int failed with %i", sts); } + /* execute query */ + sts = sqlite_exec_stmt_none(sql_stmt); + if( sts != STS_SUCCESS ){ WARN("sqlite_exec_stmt_int failed with %i", sts); } + sql_stmt = NULL; + } + + /* delete old records (failcount=0, lastseen older than one day) */ +/*&&&TODO: I should do this once a day/hour/whatever */ + /* Query8 */ + /* bind */ + sql_stmt = &sql_statement[SQL_EXPIRE_2]; + sts = sqlite3_bind_int(sql_stmt->stmt, 001, now-86400); + if( sts != SQLITE_OK ){ WARN("sqlite3_bind_int failed with %i", sts); } + /* execute query */ + sts = sqlite_exec_stmt_none(sql_stmt); + if( sts != STS_SUCCESS ){ WARN("sqlite_exec_stmt_int failed with %i", sts); } + sql_stmt = NULL; + + DEBUGC(DBCLASS_BABBLE, "leaving blacklist_expire"); return STS_SUCCESS; } -#endif + /*--------------------------------------------------------------------*/ /* helper functions */ @@ -500,7 +574,7 @@ static int sqlite_begin(void){ } /* create prepared statements */ - DEBUGC(DBCLASS_BABBLE, "PLUGIN_INIT: preparing %i statements", + DEBUGC(DBCLASS_BABBLE, "PLUGIN_INIT: preparing %li statements", sizeof(sql_statement) / sizeof(sql_statement[0])); for (i=0; i < sizeof(sql_statement) / sizeof(sql_statement[0]); i++) { if (sql_statement[i].sql_query == NULL) { @@ -595,6 +669,3 @@ static int sqlite_exec_stmt_int(sql_statement_t *sql_statement, int *retval){ return STS_SUCCESS; } - -//&&& implement cache of open REGISTER requests, only honor failed REGISTERS responses where a -//&&& REQUEST has been sent before from one of our clients.