mirror of
https://github.com/outbackdingo/sysadm.git
synced 2026-01-27 10:20:26 +00:00
Merge branch 'master' of github.com:pcbsd/sysadm
This commit is contained in:
@@ -410,7 +410,7 @@ When submitting a job to the dispatcher, keep the following points in mind:
|
||||
|
||||
* A chain of commands is useful for multi-step operations but is not considered a replacement for a good shell script on the server.
|
||||
|
||||
.. index:: query, rpc
|
||||
.. index:: query, identify, rpc
|
||||
|
||||
.. _Server Subsystems:
|
||||
|
||||
@@ -418,7 +418,7 @@ Server Subsystems
|
||||
=================
|
||||
|
||||
An RPC query can be issued to probe all the known subsystems and return which ones are currently available and what level of read and write access the user has.
|
||||
A query contains the following parameters:
|
||||
An RPC query contains the following parameters:
|
||||
|
||||
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
|
||||
| **Parameter** | **Value** | **Description** |
|
||||
@@ -487,3 +487,55 @@ A query contains the following parameters:
|
||||
"name": "response",
|
||||
"namespace": "rpc"
|
||||
}
|
||||
|
||||
To identify the type of SysAdm system, use an "identify" query. Possible identities are "server", "bridge", and "client".
|
||||
|
||||
This type of query contains the following parameters:
|
||||
|
||||
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
|
||||
| **Parameter** | **Value** | **Description** |
|
||||
| | | |
|
||||
+=================================+===============+======================================================================================================================+
|
||||
| id | | any unique value for the request; examples include a hash, checksum, or uuid |
|
||||
| | | |
|
||||
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
|
||||
| name | identify | |
|
||||
| | | |
|
||||
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
|
||||
| namespace | rpc | |
|
||||
| | | |
|
||||
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
|
||||
| args | | can be any data |
|
||||
| | | |
|
||||
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
**REST Request**
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
PUT /rpc/identify
|
||||
{}
|
||||
|
||||
**WebSocket Request**
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"args" : {},
|
||||
"namespace" : "rpc",
|
||||
"id" : "fooid",
|
||||
"name" : "identify"
|
||||
}
|
||||
|
||||
**Response**
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"args": {
|
||||
"type": "server"
|
||||
},
|
||||
"id": "fooid",
|
||||
"name": "response",
|
||||
"namespace": "rpc"
|
||||
}
|
||||
247
src/bridge/AuthorizationManager.cpp
Normal file
247
src/bridge/AuthorizationManager.cpp
Normal file
@@ -0,0 +1,247 @@
|
||||
// ===============================
|
||||
// PC-BSD REST/JSON API Server
|
||||
// Available under the 3-clause BSD License
|
||||
// Written by: Ken Moore <ken@pcbsd.org> July 2015
|
||||
// =================================
|
||||
#include "AuthorizationManager.h"
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
// Stuff for PAM to work
|
||||
#include <sys/types.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/openpam.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <login_cap.h>
|
||||
|
||||
//Stuff for OpenSSL to work
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
//Internal defines
|
||||
// -- token management
|
||||
#define TIMEOUTSECS 900 // (15 minutes) time before a token becomes invalid
|
||||
#define AUTHCHARS QString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
|
||||
#define TOKENLENGTH 40
|
||||
|
||||
AuthorizationManager::AuthorizationManager() : QObject(){
|
||||
HASH.clear();
|
||||
IPFAIL.clear();
|
||||
//initialize the random number generator (need to generate auth tokens)
|
||||
qsrand(QDateTime::currentMSecsSinceEpoch());
|
||||
}
|
||||
|
||||
AuthorizationManager::~AuthorizationManager(){
|
||||
|
||||
}
|
||||
|
||||
// == Token Interaction functions ==
|
||||
void AuthorizationManager::clearAuth(QString token){
|
||||
if(token.isEmpty() || token.length() < TOKENLENGTH){ return; } //not a valid token
|
||||
//clear an authorization token
|
||||
QString id = hashID(token);
|
||||
//qDebug() << "Clear Auth:" << id;
|
||||
if(!id.isEmpty()){ HASH.remove(id); }
|
||||
}
|
||||
|
||||
bool AuthorizationManager::checkAuth(QString token){
|
||||
//see if the given token is valid
|
||||
bool ok = false;
|
||||
QString id = hashID(token);
|
||||
if(!id.isEmpty()){
|
||||
//Also verify that the token has not timed out
|
||||
ok = (HASH[id] > QDateTime::currentDateTime());
|
||||
if(ok){ HASH.insert(id, QDateTime::currentDateTime().addSecs(TIMEOUTSECS)); } //valid - bump the timestamp
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
//SSL Certificate register/revoke/list
|
||||
bool AuthorizationManager::RegisterCertificate(QString token, QString pubkey, QString nickname, QString email){
|
||||
if(!checkAuth(token)){ return false; }
|
||||
QString user = hashID(token).section("::::",2,2); //get the user name from the currently-valid token
|
||||
//NOTE: The public key should be a base64 encoded string
|
||||
CONFIG->setValue("RegisteredCerts/"+user+"/"+pubkey, "Nickname: "+nickname+"\nEmail: "+email+"\nDate Registered: "+QDateTime::currentDateTime().toString(Qt::ISODate) );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AuthorizationManager::RevokeCertificate(QString token, QString key, QString user){
|
||||
//user will be the current user if not empty - cannot touch other user's certs without full perms on current session
|
||||
QString cuser = hashID(token).section("::::",2,2);
|
||||
|
||||
//Check that the given cert exists first
|
||||
if( !CONFIG->contains("RegisteredCerts/"+cuser+"/"+key) ){ return false; }
|
||||
CONFIG->remove("RegisteredCerts/"+cuser+"/"+key);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AuthorizationManager::ListCertificates(QString token, QJsonObject *out){
|
||||
QStringList keys; //Format: "RegisteredCerts/<user>/<key>"
|
||||
//Read all user's certs
|
||||
keys = CONFIG->allKeys().filter("RegisteredCerts/");
|
||||
//qDebug() << "Found SSL Keys to List:" << keys;
|
||||
|
||||
keys.sort();
|
||||
//Now put the known keys into the output structure arranged by username/key
|
||||
QJsonObject user; QString username;
|
||||
for(int i=0; i<keys.length(); i++){
|
||||
if(username!=keys[i].section("/",1,1)){
|
||||
if(!user.isEmpty()){ out->insert(username, user); user = QJsonObject(); } //save the current info to the output
|
||||
username = keys[i].section("/",1,1); //save the new username for later
|
||||
}
|
||||
QString info = CONFIG->value(keys[i]).toString();
|
||||
QString key = keys[i].section("/",2,-1);//just in case the key has additional "/" in it
|
||||
user.insert(key,info);
|
||||
}
|
||||
if(!user.isEmpty() && !username.isEmpty()){ out->insert(username, user); }
|
||||
}
|
||||
|
||||
//Generic functions
|
||||
int AuthorizationManager::checkAuthTimeoutSecs(QString token){
|
||||
//Return the number of seconds that a token is valid for
|
||||
if(!HASH.contains(token)){ return 0; } //invalid token
|
||||
return QDateTime::currentDateTime().secsTo( HASH[token] );
|
||||
}
|
||||
|
||||
|
||||
// == Token Generation functions
|
||||
|
||||
//Stage 1 SSL Login Check: Generation of random string for this user
|
||||
QString AuthorizationManager::GenerateEncCheckString(){
|
||||
QString key;
|
||||
for(int i=0; i<TOKENLENGTH; i++){
|
||||
key.append( AUTHCHARS.at( qrand() % AUTHCHARS.length() ) );
|
||||
}
|
||||
if(HASH.contains("SSL_CHECK_STRING/"+key)){ key = GenerateEncCheckString(); } //get a different one
|
||||
else{
|
||||
//insert this new key into the hash for later
|
||||
HASH.insert("SSL_CHECK_STRING/"+key, QDateTime::currentDateTime().addSecs(30) ); //only keep a key "alive" for 30 seconds
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
//Stage 2 SSL Login Check: Verify that the returned/encrypted string can be decoded and matches the initial random string
|
||||
QString AuthorizationManager::LoginUC(QHostAddress host, QString encstring){
|
||||
//Login w/ SSL certificate
|
||||
bool ok = false;
|
||||
//qDebug() << "SSL Auth Attempt";
|
||||
//First clean out any old strings/keys
|
||||
QStringList pubkeys = QStringList(HASH.keys()).filter("SSL_CHECK_STRING/"); //temporary, re-use variable below
|
||||
for(int i=0; i<pubkeys.length(); i++){
|
||||
//Check expiration time on each initial string
|
||||
if(QDateTime::currentDateTime() > HASH[pubkeys[i]]){
|
||||
//Note: normally only 1 request per user at a time, but it is possible for a couple different clients to try
|
||||
// and authenticate as the same user (but different keys) at nearly the same time - so keep a short valid-string time frame (<30 seconds)
|
||||
// to mitigate this possibility (need to prevent the second user-auth request from invalidating the first before the first auth handshake is finished)
|
||||
HASH.remove(pubkeys[i]); //initstring expired - go ahead and remove it to reduce calc time later
|
||||
}
|
||||
}
|
||||
//Now re-use the "pubkeys" variable for the public SSL keys
|
||||
QString user;
|
||||
pubkeys = CONFIG->allKeys().filter("RegisteredCerts/"); //Format: "RegisteredCerts/<user>/<key>"
|
||||
//qDebug() << " - Check pubkeys";// << pubkeys;
|
||||
for(int i=0; i<pubkeys.length() && !ok; i++){
|
||||
//Decrypt the string with this pubkey - and compare to the outstanding initstrings
|
||||
QString key = DecryptSSLString(encstring, pubkeys[i].section("/",2,-1));
|
||||
if(HASH.contains("SSL_CHECK_STRING/"+key)){
|
||||
//Valid reponse found
|
||||
//qDebug() << " - Found Valid Key";
|
||||
ok = true;
|
||||
//Remove the initstring from the hash (already used)
|
||||
HASH.remove("SSL_CHECK_STRING/"+key);
|
||||
user = pubkeys[i].section("/",1,1);
|
||||
}
|
||||
}
|
||||
|
||||
//qDebug() << "User Login Attempt:" << user << " Success:" << ok << " IP:" << host.toString();
|
||||
|
||||
if(!ok){
|
||||
//invalid login
|
||||
//Bump the fail count for this host
|
||||
bool overlimit = BumpFailCount(host.toString());
|
||||
if(overlimit){ emit BlockHost(host); }
|
||||
return (overlimit ? "REFUSED" : "");
|
||||
}else{
|
||||
//valid login - generate a new token for it
|
||||
ClearHostFail(host.toString());
|
||||
return generateNewToken(false, "none");
|
||||
}
|
||||
}
|
||||
|
||||
// =========================
|
||||
// PRIVATE
|
||||
// =========================
|
||||
QString AuthorizationManager::generateNewToken(bool isOp, QString user){
|
||||
QString tok;
|
||||
for(int i=0; i<TOKENLENGTH; i++){
|
||||
tok.append( AUTHCHARS.at( qrand() % AUTHCHARS.length() ) );
|
||||
}
|
||||
|
||||
if( !hashID(tok).isEmpty() ){
|
||||
//Just in case the randomizer came up with something identical - re-run it
|
||||
tok = generateNewToken(isOp, user);
|
||||
}else{
|
||||
//unique token created - add it to the hash with the current time (+timeout)
|
||||
QString id = tok + "::::"+(isOp ? "operator" : "user")+"::::"+user; //append operator status to auth key
|
||||
HASH.insert(id, QDateTime::currentDateTime().addSecs(TIMEOUTSECS) );
|
||||
//qDebug() << "Current HASH Contents:" << HASH.keys();
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
bool AuthorizationManager::BumpFailCount(QString host){
|
||||
//Returns: true if the failure count is over the limit
|
||||
//key: "<IP>::::<failnum>"
|
||||
QStringList keys = QStringList(IPFAIL.keys()).filter(host+"::::");
|
||||
int fails = 0;
|
||||
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(CONFIG->value("blacklist_settings/block_minutes",60).toInt()*60) > QDateTime::currentDateTime() ){
|
||||
fails = keys[0].section("::::",1,1).toInt();
|
||||
}
|
||||
}
|
||||
fails++;
|
||||
IPFAIL.insert(host+"::::"+QString::number(fails), QDateTime::currentDateTime() );
|
||||
return (fails>=CONFIG->value("blacklist_settings/fails_to_block",2).toInt());
|
||||
}
|
||||
|
||||
void AuthorizationManager::ClearHostFail(QString host){
|
||||
QStringList keys = QStringList(IPFAIL.keys()).filter(host+"::::");
|
||||
for(int i=0; i<keys.length(); i++){ IPFAIL.remove(keys[i]); }
|
||||
}
|
||||
|
||||
QString AuthorizationManager::DecryptSSLString(QString encstring, QString pubkey){
|
||||
//Convert from the base64 string back into byte array
|
||||
QByteArray enc;
|
||||
enc.append(encstring);
|
||||
enc = QByteArray::fromBase64(enc);
|
||||
QByteArray pkey;
|
||||
pkey.append(pubkey);
|
||||
pkey = QByteArray::fromBase64(pkey);
|
||||
//Now start the SSL routine
|
||||
/*qDebug() << "Decrypt String:" << "Length:" << enc.length() << enc;
|
||||
qDebug() << " - Base64:" << encstring << "Length:" << encstring.length();
|
||||
qDebug() << " - pubkey (base64):" << pubkey << "Length:" << pubkey.length();
|
||||
qDebug() << " - pubkey:" << pkey << "Length:" << pkey.length();*/
|
||||
unsigned char decode[4098] = {};
|
||||
RSA *rsa= NULL;
|
||||
BIO *keybio = NULL;
|
||||
//qDebug() << " - Generate keybio";
|
||||
keybio = BIO_new_mem_buf(pkey.data(), -1);
|
||||
if(keybio==NULL){ return ""; }
|
||||
//qDebug() << " - Read pubkey";
|
||||
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
|
||||
if(rsa==NULL){ qDebug() << " - Invalid RSA key!!"; return ""; }
|
||||
//qDebug() << " - Decrypt string";
|
||||
int len = RSA_public_decrypt(enc.length(), (unsigned char*)(enc.data()), decode, rsa, RSA_PKCS1_PADDING);
|
||||
if(len<0){ return ""; }
|
||||
else{ return QString( QByteArray( (char*)(decode), len) ); }
|
||||
}
|
||||
64
src/bridge/AuthorizationManager.h
Normal file
64
src/bridge/AuthorizationManager.h
Normal file
@@ -0,0 +1,64 @@
|
||||
// ===============================
|
||||
// PC-BSD REST/JSON API Server
|
||||
// Available under the 3-clause BSD License
|
||||
// Written by: Ken Moore <ken@pcbsd.org> July 2015
|
||||
// =================================
|
||||
#ifndef _PCBSD_REST_AUTHORIZATION_MANAGER_H
|
||||
#define _PCBSD_REST_AUTHORIZATION_MANAGER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
#include <QJsonObject>
|
||||
#include <QHostAddress>
|
||||
#include <QDateTime>
|
||||
#include <QByteArray>
|
||||
|
||||
class AuthorizationManager : public QObject{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AuthorizationManager();
|
||||
~AuthorizationManager();
|
||||
|
||||
// == Token Interaction functions ==
|
||||
void clearAuth(QString token); //clear an authorization token
|
||||
bool checkAuth(QString token); //see if the given token is valid
|
||||
|
||||
//SSL Certificate register/revoke/list (should only run if the current token is valid)
|
||||
bool RegisterCertificate(QString token, QString pubkey, QString nickname, QString email); //if token is valid, register the given cert for future logins
|
||||
bool RevokeCertificate(QString token, QString key, QString user=""); //user will be the current user if not empty - cannot touch other user's certs without full perms on current session
|
||||
void ListCertificates(QString token, QJsonObject *out);
|
||||
|
||||
int checkAuthTimeoutSecs(QString token); //Return the number of seconds that a token is valid for
|
||||
|
||||
//Stage 1 SSL Login Check: Generation of random string for this user
|
||||
QString GenerateEncCheckString();
|
||||
//Stage 2 SSL Login Check: Verify that the returned/encrypted string can be decoded and matches the initial random string
|
||||
QString LoginUC(QHostAddress host, QString encstring);
|
||||
|
||||
|
||||
private:
|
||||
QHash<QString, QDateTime> HASH;
|
||||
QHash <QString, QDateTime> IPFAIL;
|
||||
|
||||
QString generateNewToken(bool isOperator, QString name);
|
||||
|
||||
//Failure count management
|
||||
bool BumpFailCount(QString host);
|
||||
void ClearHostFail(QString host);
|
||||
|
||||
//token->hashID filter simplification
|
||||
QString hashID(QString token){
|
||||
QStringList tmp = QStringList(HASH.keys()).filter(token+"::::");
|
||||
if(tmp.isEmpty()){ return ""; }
|
||||
else{ return tmp.first(); }
|
||||
}
|
||||
|
||||
//SSL Decrypt function
|
||||
QString DecryptSSLString(QString encstring, QString pubkey);
|
||||
|
||||
signals:
|
||||
void BlockHost(QHostAddress); //block a host address temporarily
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -16,9 +16,9 @@ BridgeConnection::BridgeConnection(QWebSocket *sock, QString ID){
|
||||
SOCKET = sock;
|
||||
SockPeerIP = SOCKET->peerAddress().toString();
|
||||
idletimer = new QTimer(this);
|
||||
idletimer->setInterval(IDLETIMEOUTMINS*60000); //connection timout for idle sockets
|
||||
idletimer->setInterval(30000); //connection timout for idle sockets
|
||||
idletimer->setSingleShot(true);
|
||||
connect(idletimer, SIGNAL(timeout()), this, SLOT(checkgonintendoIdle()) );
|
||||
connect(idletimer, SIGNAL(timeout()), this, SLOT(checkAuth()) );
|
||||
connect(SOCKET, SIGNAL(textMessageReceived(const QString&)), this, SLOT(EvaluateMessage(const QString&)) );
|
||||
connect(SOCKET, SIGNAL(binaryMessageReceived(const QByteArray&)), this, SLOT(EvaluateMessage(const QByteArray&)) );
|
||||
connect(SOCKET, SIGNAL(aboutToClose()), this, SLOT(SocketClosing()) );
|
||||
@@ -77,7 +77,7 @@ QStringList BridgeConnection::JsonArrayToStringList(QJsonArray array){
|
||||
|
||||
void BridgeConnection::InjectMessage(QString msg){
|
||||
//See if this message is directed to the bridge itself, or a client
|
||||
if(msg.startsWith("{")){
|
||||
if(msg.startsWith("{") || !AUTHSYSTEM->checkAuth(SockAuthToken) ){
|
||||
HandleAPIMessage(msg);
|
||||
}else{
|
||||
//Need to read the destination off the message first
|
||||
@@ -119,10 +119,35 @@ void BridgeConnection::HandleAPIMessage(QString msg){
|
||||
out.insert("id", JM.value("id"));
|
||||
out.insert("namespace", namesp);
|
||||
out.insert("name","reponse");
|
||||
QJsonObject outargs;
|
||||
QJsonValue outargs;
|
||||
//There is only a short list of API calls the bridge is capable of:
|
||||
if(namesp == "rpc" && name=="identify"){
|
||||
outargs.insert("type","bridge");
|
||||
QJsonObject tmp;
|
||||
tmp.insert("type","bridge");
|
||||
outargs = tmp;
|
||||
|
||||
}else if(namesp == "rpc" && name=="auth_ssl"){
|
||||
if(!args.contains("encrypted_string")){
|
||||
//Stage 1 - send a random string to encrypt
|
||||
QString key = AUTHSYSTEM->GenerateEncCheckString();
|
||||
QJsonObject obj; obj.insert("test_string", key);
|
||||
outargs = obj;
|
||||
}else{
|
||||
//Stage 2 - verify returned encrypted string
|
||||
SockAuthToken = AUTHSYSTEM->LoginUC(SOCKET->peerAddress(),args.value("encrypted_string").toString() );
|
||||
if(AUTHSYSTEM->checkAuth(SockAuthToken)){
|
||||
QJsonArray array;
|
||||
array.append(SockAuthToken);
|
||||
array.append(AUTHSYSTEM->checkAuthTimeoutSecs(SockAuthToken));
|
||||
outargs = array;
|
||||
}else{
|
||||
out.insert("name","error");
|
||||
outargs = "unauthorized";
|
||||
}
|
||||
}
|
||||
}else if(AUTHSYSTEM->checkAuth(SockAuthToken)){
|
||||
//Valid auth - a couple more API calls available here
|
||||
|
||||
}else{
|
||||
out.insert("name","error"); //unknown API call
|
||||
}
|
||||
@@ -142,21 +167,15 @@ void BridgeConnection::checkIdle(){
|
||||
}
|
||||
|
||||
void BridgeConnection::checkAuth(){
|
||||
//if(!AUTHSYSTEM->checkAuth(SockAuthToken)){
|
||||
if(!AUTHSYSTEM->checkAuth(SockAuthToken)){
|
||||
//Still not authorized - disconnect
|
||||
//checkIdle();
|
||||
//}
|
||||
checkIdle();
|
||||
}
|
||||
}
|
||||
|
||||
void BridgeConnection::SocketClosing(){
|
||||
qDebug() << "Connection Closing: " << SockPeerIP;
|
||||
if(idletimer->isActive()){
|
||||
//This means the client deliberately closed the connection - not the idle timer
|
||||
//qDebug() << " - Client Closed Connection";
|
||||
idletimer->stop();
|
||||
}else{
|
||||
//qDebug() << "idleTimer not running";
|
||||
}
|
||||
if(idletimer->isActive()){ idletimer->stop(); }
|
||||
//Stop any current requests
|
||||
|
||||
//Reset the pointer
|
||||
@@ -167,16 +186,12 @@ void BridgeConnection::SocketClosing(){
|
||||
|
||||
void BridgeConnection::EvaluateMessage(const QByteArray &msg){
|
||||
//qDebug() << "New Binary Message:";
|
||||
if(idletimer->isActive()){ idletimer->stop(); }
|
||||
idletimer->start();
|
||||
InjectMessage( QString(msg) );
|
||||
//qDebug() << " - Done with Binary Message";
|
||||
}
|
||||
|
||||
void BridgeConnection::EvaluateMessage(const QString &msg){
|
||||
//qDebug() << "New Text Message:";
|
||||
if(idletimer->isActive()){ idletimer->stop(); }
|
||||
idletimer->start();
|
||||
InjectMessage(msg);
|
||||
//qDebug() << " - Done with Text Message";
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ private:
|
||||
|
||||
void InjectMessage(QString msg);
|
||||
void HandleAPIMessage(QString msg);
|
||||
|
||||
private slots:
|
||||
void checkIdle(); //see if the currently-connected client is idle
|
||||
void checkAuth(); //see if the currently-connected client has authed yet
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
BridgeServer::BridgeServer() : QWebSocketServer("sysadm-bridge", QWebSocketServer::SecureMode){
|
||||
//Setup all the various settings
|
||||
//AUTH = new AuthorizationManager();
|
||||
//connect(AUTH, SIGNAL(BlockHost(QHostAddress)), this, SLOT(BlackListConnection(QHostAddress)) );
|
||||
connect(AUTHSYSTEM, SIGNAL(BlockHost(QHostAddress)), this, SLOT(BlackListConnection(QHostAddress)) );
|
||||
}
|
||||
|
||||
BridgeServer::~BridgeServer(){
|
||||
@@ -92,7 +92,7 @@ bool BridgeServer::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();
|
||||
if(dt.addSecs(CONFIG->value("blacklist_settings/blockmins",60).toInt()*60) < QDateTime::currentDateTime()){
|
||||
if(dt.addSecs(CONFIG->value("blacklist_settings/block_minutes",60).toInt()*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;
|
||||
|
||||
@@ -6,12 +6,13 @@ QT = core network websockets
|
||||
|
||||
HEADERS += globals.h \
|
||||
BridgeServer.h \
|
||||
BridgeConnection.h
|
||||
BridgeConnection.h \
|
||||
AuthorizationManager.h
|
||||
|
||||
SOURCES += main.cpp \
|
||||
BridgeServer.cpp \
|
||||
BridgeConnection.cpp
|
||||
|
||||
BridgeConnection.cpp \
|
||||
AuthorizationManager.cpp
|
||||
|
||||
|
||||
TARGET=sysadm-bridge
|
||||
@@ -25,4 +26,4 @@ INSTALLS += target scripts
|
||||
|
||||
QMAKE_LIBDIR = /usr/local/lib/qt5 /usr/local/lib
|
||||
INCLUDEPATH += /usr/local/include
|
||||
LIBS += -L/usr/local/lib -lpam -lutil -lssl -lcrypto
|
||||
LIBS += -L/usr/local/lib -lutil -lssl -lcrypto
|
||||
|
||||
@@ -37,4 +37,9 @@
|
||||
|
||||
#define SETTINGSFILE "/var/db/sysadm-bridge.ini"
|
||||
|
||||
#define SYSADM_BRIDGE
|
||||
#include "AuthorizationManager.h"
|
||||
|
||||
extern QSettings* CONFIG;
|
||||
extern AuthorizationManager* AUTHSYSTEM;
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
//Create any global classes
|
||||
//Create any global classes/settings
|
||||
QSettings *CONFIG = new QSettings(SETTINGSFILE, QSettings::IniFormat);
|
||||
|
||||
AuthorizationManager *AUTHSYSTEM = new AuthorizationManager();
|
||||
|
||||
//Set the defail values for the global config variables
|
||||
/*int BlackList_BlockMinutes = 60;
|
||||
@@ -59,7 +59,9 @@ int main( int argc, char ** argv )
|
||||
if(!info.contains("=")){ continue; } //invalid format
|
||||
QString var = info.section("=",0,0); QString val = info.section("=",1,-1);
|
||||
qDebug() << "Changing bridge setting:" << info;
|
||||
if(var=="blacklist/blockmins"){ CONFIG->setValue("blacklist_settings/blockmins",val.toInt()); }
|
||||
if(var=="blacklist/block_minutes"){ CONFIG->setValue("blacklist_settings/block_minutes",val.toInt()); }
|
||||
else if(var=="blacklist/fails_to_block"){ CONFIG->setValue("blacklist_settings/fails_to_block",val.toInt()); }
|
||||
//else if(var=="blacklist_settings/block_minutes"){ CONFIG->setValue("blacklist_settings/block_minutes",val.toInt()); }
|
||||
}
|
||||
else if( (QString(argv[i])=="-port" || QString(argv[i])=="-p") && (i+1<argc)){ i++; port = QString(argv[i]).toUInt(); }
|
||||
else if( QString(argv[i])=="-set" && i+1<argc){ settingchange = true; }
|
||||
@@ -84,7 +86,7 @@ int main( int argc, char ** argv )
|
||||
//Create the two servers and connect them
|
||||
qDebug() << "Starting the PC-BSD sysadm bridge....";
|
||||
BridgeServer server;
|
||||
|
||||
|
||||
//Start the servers
|
||||
int ret = 1; //error return value
|
||||
if(!server.startServer(port)){ qDebug() << "Could not start bridge server on port:" << port; }
|
||||
|
||||
Reference in New Issue
Block a user