diff --git a/src/conf/sysadm.conf b/src/conf/sysadm.conf new file mode 100644 index 0000000..dc85633 --- /dev/null +++ b/src/conf/sysadm.conf @@ -0,0 +1,16 @@ +#Sample Configuration file for the sysadm server + +### Server Port Number ### +# - Websocket Server (standard) +PORT=12150 +# - REST Server (started with the "-rest" CLI flag) +PORT_REST=12151 + +### Blacklist options ### +# - Number of minutes that an IP remains on the blacklist +BLACKLIST_BLOCK_MINUTES=60 +# - Number of authorization failures before an IP is placed on the blacklist +BLACKLIST_AUTH_FAIL_LIMIT=5 +# - Number of minutes of no activity from an IP before resetting the failure counter +# (Note: A successful authorization will always reset the fail counter) +BLACKLIST_AUTH_FAIL_RESET_MINUTES=10 diff --git a/src/server/AuthorizationManager.cpp b/src/server/AuthorizationManager.cpp index 5e8d2eb..da1016d 100644 --- a/src/server/AuthorizationManager.cpp +++ b/src/server/AuthorizationManager.cpp @@ -30,9 +30,10 @@ #define TIMEOUTSECS 900 // (15 minutes) time before a token becomes invalid #define AUTHCHARS QString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") #define TOKENLENGTH 20 + // -- Connection failure limitations -#define AUTHFAILLIMIT 5 //number of sequential failures before IP is blocked for a time -#define FAILOVERMINS 10 //after this many minutes without a new login attempt the failure count will reset +//#define AUTHFAILLIMIT 5 //number of sequential failures before IP is blocked for a time +//#define FAILOVERMINS 10 //after this many minutes without a new login attempt the failure count will reset AuthorizationManager::AuthorizationManager() : QObject(){ HASH.clear(); @@ -315,13 +316,13 @@ bool AuthorizationManager::BumpFailCount(QString host){ if(!keys.isEmpty()){ //Take the existing key/value and put a new one in (this limits the filter to 1 value maximum) QDateTime last = IPFAIL.take(keys[0]); - if(last.addSecs(FAILOVERMINS*60) > QDateTime::currentDateTime() ){ + if(last.addSecs(BlackList_AuthFailResetMinutes*60) > QDateTime::currentDateTime() ){ fails = keys[0].section("::::",1,1).toInt(); } } fails++; IPFAIL.insert(host+"::::"+QString::number(fails), QDateTime::currentDateTime() ); - return (fails>=AUTHFAILLIMIT); + return (fails>=BlackList_AuthFailsToBlock); } void AuthorizationManager::ClearHostFail(QString host){ diff --git a/src/server/WebServer.cpp b/src/server/WebServer.cpp index e04fb80..9f76c1a 100644 --- a/src/server/WebServer.cpp +++ b/src/server/WebServer.cpp @@ -4,6 +4,7 @@ // Written by: Ken Moore July 2015 // ================================= #include "WebServer.h" +#include "globals.h" #define DEBUG 0 @@ -105,8 +106,7 @@ bool WebServer::allowConnection(QHostAddress addr){ if(!CONFIG->contains(key) ){ return true; } //not in the list //Address on the list - see if the timeout has expired QDateTime dt = CONFIG->value(key,QDateTime()).toDateTime(); - int minblock = CONFIG->value("blacklist/RefuseMinutes",60).toInt(); - if(dt.addSecs(minblock*60) < QDateTime::currentDateTime()){ + if(dt.addSecs(BlackList_BlockMinutes*60) < QDateTime::currentDateTime()){ //This entry has timed out - go ahead and allow it CONFIG->remove(key); //make the next connection check for this IP faster again return true; diff --git a/src/server/globals-qt.h b/src/server/globals-qt.h index 2f8333d..2e53258 100644 --- a/src/server/globals-qt.h +++ b/src/server/globals-qt.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include diff --git a/src/server/globals.h b/src/server/globals.h index 43fccb3..57ab16e 100644 --- a/src/server/globals.h +++ b/src/server/globals.h @@ -23,4 +23,9 @@ extern Dispatcher *DISPATCHER; #define WSPORTNUMBER 12150 // WebSocket server default port #define PORTNUMBER 12151 // TCP server default port +//Config file settings for this instance of the server +extern int BlackList_BlockMinutes; +extern int BlackList_AuthFailsToBlock; +extern int BlackList_AuthFailResetMinutes; + #endif diff --git a/src/server/main.cpp b/src/server/main.cpp index 44c1550..0b36aeb 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -10,14 +10,22 @@ #include "WebServer.h" +#define CONFFILE "/usr/local/etc/sysadm.conf" +#define SETTINGSFILE "/usr/local/etc/.sysadm-internal.ini" + #define DEBUG 0 //Create any global classes -QSettings *CONFIG = new QSettings("/usr/local/etc/sysadm.conf", QSettings::IniFormat); +QSettings *CONFIG = new QSettings(SETTINGSFILE, QSettings::IniFormat); EventWatcher *EVENTS = new EventWatcher(); Dispatcher *DISPATCHER = new Dispatcher(); bool WS_MODE = false; +//Set the defail values for the global config variables +int BlackList_BlockMinutes = 60; +int BlackList_AuthFailsToBlock = 5; +int BlackList_AuthFailResetMinutes = 10; + //Create the default logfile QFile logfile; void MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg){ @@ -45,6 +53,15 @@ void MessageOutput(QtMsgType type, const QMessageLogContext &context, const QStr if(!txt.endsWith("\n")){ out << "\n"; } } +inline QString ReadFile(QString path){ + QFile file(path); + if( !file.open(QIODevice::ReadOnly) ){ return ""; } + QTextStream in(&file); + QString str = in.readAll(); + file.close(); + return str; +} + int main( int argc, char ** argv ) { QCoreApplication a(argc, argv); @@ -54,18 +71,59 @@ int main( int argc, char ** argv ) return 1; } - //Evaluate input arguments - bool websocket = false; + bool websocket = true; quint16 port = 0; for(int i=1; isync(); //re-sync settings structure + conf.clear(); //No config yet } + //Load the settings from the config file + // - port number + if(port==0){ + if(websocket){ + int index = conf.indexOf(QRegExp("PORT=*",Qt::CaseSensitive,QRegExp::Wildcard)); + bool ok = false; + if(index>=0){ port = conf[index].section("=",1,1).toInt(&ok); } + if(port<=0 || !ok){ port = WSPORTNUMBER; } + }else{ + int index = conf.indexOf(QRegExp("PORT_REST=*",Qt::CaseSensitive,QRegExp::Wildcard)); + bool ok = false; + if(index>=0){ port = conf[index].section("=",1,1).toInt(&ok); } + if(port<=0 || !ok){ port = PORTNUMBER; } + } + } + // - Blacklist options + QRegExp rg = QRegExp("BLACKLIST_BLOCK_MINUTES=*",Qt::CaseSensitive,QRegExp::Wildcard); + if(!conf.filter(rg).isEmpty()){ + bool ok = false; + int tmp = conf.filter(rg).first().section("=",1,1).simplified().toInt(&ok); + if(ok){ BlackList_BlockMinutes = tmp; } + } + rg = QRegExp("BLACKLIST_AUTH_FAIL_LIMIT=*",Qt::CaseSensitive,QRegExp::Wildcard); + if(!conf.filter(rg).isEmpty()){ + bool ok = false; + int tmp = conf.filter(rg).first().section("=",1,1).simplified().toInt(&ok); + if(ok){ BlackList_AuthFailsToBlock = tmp; } + } + rg = QRegExp("BLACKLIST_AUTH_FAIL_RESET_MINUTES=*",Qt::CaseSensitive,QRegExp::Wildcard); + if(!conf.filter(rg).isEmpty()){ + bool ok = false; + int tmp = conf.filter(rg).first().section("=",1,1).simplified().toInt(&ok); + if(ok){ BlackList_AuthFailResetMinutes = tmp; } + } + //Setup the log file LogManager::checkLogDir(); //ensure the logging directory exists if(!websocket){ logfile.setFileName("/var/log/sysadm-server-tcp.log"); }