Change the location of the sysadm server internal settings file (QSettings file), and add support for an optional sysadm.conf file which is loaded on server startup.

This commit is contained in:
Ken Moore
2016-02-22 12:25:52 -05:00
parent 9ebf28134e
commit 7e230c5f5f
6 changed files with 94 additions and 13 deletions

16
src/conf/sysadm.conf Normal file
View File

@@ -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

View File

@@ -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){

View File

@@ -4,6 +4,7 @@
// Written by: Ken Moore <ken@pcbsd.org> 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;

View File

@@ -39,6 +39,7 @@
#include <QThread>
#include <QFileSystemWatcher>
#include <QQueue>
#include <QRegExp>
#include <QList>
#include <QHash>

View File

@@ -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

View File

@@ -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; i<argc; i++){
if( QString(argv[i])=="-ws" ){ websocket = true; WS_MODE = true;}
if( QString(argv[i])=="-rest" ){ websocket = false;}
else if( QString(argv[i])=="-p" && (i+1<argc) ){ i++; port = QString(argv[i]).toUInt(); }
}
if(port==0){
if(websocket){ port = WSPORTNUMBER; }
else{ port = PORTNUMBER; }
WS_MODE = websocket; //set the global variable too
//Now load the config file
QStringList conf = ReadFile(CONFFILE).split("\n");
if(!conf.filter("[internal]").isEmpty()){
//Older QSettings file - move it to the new location
if(QFile::exists(SETTINGSFILE)){ QFile::remove(SETTINGSFILE); } //remove the new/empty settings file
QFile::rename(CONFFILE, SETTINGSFILE);
CONFIG->sync(); //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"); }