From d8a0faea790d45e638508f7488fb4ddbadc97bf6 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Fri, 20 May 2016 12:40:32 -0400 Subject: [PATCH] Clean up the server and bridge systems so that connections are now successful as needed. --- src/bridge/BridgeConnection.cpp | 17 +++++++++++++++-- src/bridge/BridgeConnection.h | 1 + src/bridge/BridgeServer.cpp | 10 +++++++--- src/bridge/main.cpp | 15 ++++++++++++--- src/server/WebSocket.cpp | 26 ++++++++++++++++++++++++-- src/server/main.cpp | 29 +++++++++++++++++++++++++---- 6 files changed, 84 insertions(+), 14 deletions(-) diff --git a/src/bridge/BridgeConnection.cpp b/src/bridge/BridgeConnection.cpp index 1addddd..9518db0 100644 --- a/src/bridge/BridgeConnection.cpp +++ b/src/bridge/BridgeConnection.cpp @@ -24,6 +24,7 @@ BridgeConnection::BridgeConnection(QWebSocket *sock, QString ID){ connect(SOCKET, SIGNAL(binaryMessageReceived(const QByteArray&)), this, SLOT(EvaluateMessage(const QByteArray&)) ); connect(SOCKET, SIGNAL(aboutToClose()), this, SLOT(SocketClosing()) ); idletimer->start(); + requestIdentify(); QTimer::singleShot(30000, this, SLOT(checkAuth())); } @@ -116,6 +117,7 @@ void BridgeConnection::HandleAPIMessage(QString msg){ // - Return messages first (check ID) QString id = JM.value("id").toString(); if(id=="sysadm_bridge_request_ident"){ + qDebug() << "Got ident reply:" << JM; serverconn = (JM.value("args").toObject().value("type").toString() == "server"); }else if("bridge_request_list_keys"){ QStringList keys = JsonArrayToStringList(JM.value("args").toObject().value("md5_keys").toArray()); @@ -134,7 +136,7 @@ void BridgeConnection::HandleAPIMessage(QString msg){ namesp = JM.value("namespace").toString(); out.insert("id", JM.value("id")); out.insert("namespace", namesp); - out.insert("name","reponse"); + out.insert("name","response"); QJsonValue outargs; //There is only a short list of API calls the bridge is capable of: if(namesp == "rpc" && name=="identify"){ @@ -145,6 +147,7 @@ void BridgeConnection::HandleAPIMessage(QString msg){ }else if(namesp == "rpc" && name=="auth_ssl"){ if(!args.contains("encrypted_string")){ //Stage 1 - send a random string to encrypt + qDebug() << "Connection Auth Init:" << SockPeerIP; QString key = AUTHSYSTEM->GenerateEncCheckString(); QJsonObject obj; obj.insert("test_string", key); outargs = obj; @@ -156,7 +159,7 @@ void BridgeConnection::HandleAPIMessage(QString msg){ array.append(SockAuthToken); array.append(AUTHSYSTEM->checkAuthTimeoutSecs(SockAuthToken)); outargs = array; - qDebug() << "Connection Authorized:" << SockPeerIP; + qDebug() << "Connection Authorized:" << SockPeerIP << "Type:" << (serverconn ? "server" : "client"); QTimer::singleShot(10 ,this, SLOT(requestKeyList()) ); }else{ out.insert("name","error"); @@ -232,6 +235,16 @@ void BridgeConnection::SslError(const QList &err){ //sslErrors() sign // ====================== // PUBLIC SLOTS // ====================== +void BridgeConnection::requestIdentify(){ + QJsonObject obj; + obj.insert("id","sysadm_bridge_request_ident"); + obj.insert("namespace","rpc"); + obj.insert("name","identify"); + obj.insert("args",""); + + SOCKET->sendTextMessage( QJsonDocument(obj).toJson(QJsonDocument::Compact) ); +} + void BridgeConnection::requestKeyList(){ if(!AUTHSYSTEM->checkAuth(SockAuthToken)){ return; } //not authorized yet QJsonObject obj; diff --git a/src/bridge/BridgeConnection.h b/src/bridge/BridgeConnection.h index 490e7e1..d5bbec3 100644 --- a/src/bridge/BridgeConnection.h +++ b/src/bridge/BridgeConnection.h @@ -50,6 +50,7 @@ private slots: void SslError(const QList&); //sslErrors() signal public slots: + void requestIdentify(); void requestKeyList(); void announceIDAvailability(QStringList IDs); diff --git a/src/bridge/BridgeServer.cpp b/src/bridge/BridgeServer.cpp index 6ffc37a..cae44e3 100644 --- a/src/bridge/BridgeServer.cpp +++ b/src/bridge/BridgeServer.cpp @@ -113,11 +113,13 @@ QString BridgeServer::generateID(QString name){ // New Connection Signals void BridgeServer::NewSocketConnection(){ BridgeConnection *sock = 0; - qDebug() << "New incoming connection.."; if(this->hasPendingConnections()){ + qDebug() << "New incoming connection.."; QWebSocket *ws = this->nextPendingConnection(); if(allowConnection(ws->peerAddress()) ){ - sock = new BridgeConnection( ws, generateID(ws->peerName()) ); + QString name = ws->peerName(); + if(name.isEmpty()){ name = ws->peerAddress().toString(); } + sock = new BridgeConnection( ws, generateID(name) ); }else{ ws->abort(); } @@ -125,7 +127,7 @@ void BridgeServer::NewSocketConnection(){ if(sock==0){ return; } //no new connection //qDebug() << "New Socket Connection"; connect(sock, SIGNAL(SocketClosed(QString)), this, SLOT(SocketClosed(QString)) ); - connect(sock, SIGNAL(SocketMessage(QString, QString)), this, SLOT(SendMessage(QString, QString)) ); + connect(sock, SIGNAL(SocketMessage(QString, QString)), this, SLOT(sendMessage(QString, QString)) ); connect(sock, SIGNAL(keysChanged(QString, bool, QStringList)), this, SLOT(announceKeyChange(QString, bool, QStringList)) ); OpenSockets << sock; } @@ -188,6 +190,7 @@ void BridgeServer::SocketClosed(QString ID){ // Connection Keys Changed void BridgeServer::announceKeyChange(QString ID, bool isServer, QStringList keys){ + qDebug() << "Key Change:" << ID << isServer << keys; for(int c = 0; cisServer(); QStringList keys = OpenSockets[c]->validKeySums(); @@ -199,6 +202,7 @@ void BridgeServer::announceKeyChange(QString ID, bool isServer, QStringList keys //compare keys to look for matches QStringList chkkeys = OpenSockets[i ]->validKeySums(); chkkeys.removeDuplicates(); + qDebug() << "Known Keys for ID:" << OpenSockets[i]->ID() << chkkeys; chkkeys << keys; if(chkkeys.removeDuplicates() > 0){ IDs << OpenSockets[i]->ID(); } } diff --git a/src/bridge/main.cpp b/src/bridge/main.cpp index 74aa754..488a576 100644 --- a/src/bridge/main.cpp +++ b/src/bridge/main.cpp @@ -62,8 +62,17 @@ qDebug() << " \"blacklist/fails_to_block\" (integer): Number of times a syste int main( int argc, char ** argv ) { - if(getuid() != 0){ CONFIG = new QSettings("sysadm","bridge"); SSLFILEDIR=CONFIG->fileName().section("/",0,-2); } - else{ CONFIG = new QSettings("/var/db/sysadm-bridge.ini", QSettings::IniFormat); SSLFILEDIR="/usr/local/etc/sysadm"; } + QString logdir; + if(getuid() != 0){ + CONFIG = new QSettings("sysadm","bridge"); + SSLFILEDIR=CONFIG->fileName().section("/",0,-2); + logdir = SSLFILEDIR; + } + else{ + CONFIG = new QSettings("/var/db/sysadm-bridge.ini", QSettings::IniFormat); + SSLFILEDIR="/usr/local/etc/sysadm"; + logdir="/var/log"; + } qDebug() << "Using Config file:" << CONFIG->fileName(); qDebug() << "SSL FILE DIR:" << SSLFILEDIR; //Evaluate input arguments @@ -147,7 +156,7 @@ int main( int argc, char ** argv ) //Setup the log file if(USELOG){ - logfile.setFileName(SSLFILEDIR+"/sysadm-bridge.log"); + logfile.setFileName(logdir+"/sysadm-bridge.log"); qDebug() << "Log File:" << logfile.fileName(); if(QFile::exists(logfile.fileName()+".old")){ QFile::remove(logfile.fileName()+".old"); } if(logfile.exists()){ QFile::rename(logfile.fileName(), logfile.fileName()+".old"); } diff --git a/src/server/WebSocket.cpp b/src/server/WebSocket.cpp index c6c56f8..41ba936 100644 --- a/src/server/WebSocket.cpp +++ b/src/server/WebSocket.cpp @@ -79,6 +79,8 @@ WebSocket::WebSocket(QString url, QString ID, AuthorizationManager *auth){ connect(EVENTS, SIGNAL(NewEvent(EventWatcher::EVENT_TYPE, QJsonValue)), this, SLOT(EventUpdate(EventWatcher::EVENT_TYPE, QJsonValue)) ); connect(this, SIGNAL(SendMessage(QString)), this, SLOT(sendReply(QString)) ); connect(SOCKET, SIGNAL(connected()), this, SLOT(startBridgeAuth()) ); + //connect(SOCKET, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)) ); + connect(SOCKET, SIGNAL(sslErrors(const QList&)), this, SLOT(SslError(const QList&)) ); //idletimer->start(); //do not idle out on a bridge connection /*QTimer::singleShot(30000, this, SLOT(checkAuth()));*/ //Assemble the URL as needed @@ -86,7 +88,10 @@ WebSocket::WebSocket(QString url, QString ID, AuthorizationManager *auth){ bool hasport = false; url.section(":",-1).toInt(&hasport); //check if the last piece of the url is a valid number if(!hasport){ url.append(":"+QString::number(BRIDGEPORTNUMBER)); } + //Now setup/init the connection qDebug() << "Connecting to bridge:" << url; + SOCKET->setSslConfiguration(QSslConfiguration::defaultConfiguration()); + //QTimer::singleShot(0,SOCKET, SLOT(ignoreSslErrors()) ); SOCKET->open(QUrl(url)); } @@ -164,6 +169,7 @@ void WebSocket::EvaluateREST(QString msg){ out.Header << "Content-Type: text/json; charset=utf-8"; this->sendReply(out.assembleMessage()); }else{ + qDebug() << "Got Message:" << IN.namesp << IN.name << IN.args << isBridge; if(IN.name.startsWith("auth") || (IN.namesp.toLower()=="rpc" && IN.name.toLower()=="identify") ){ //Keep auth/pre-auth system requests in order EvaluateRequest(IN); @@ -362,6 +368,7 @@ if(out.in_struct.namesp.toLower() == "rpc"){ } void WebSocket::EvaluateResponse(const RestInputStruct& IN){ + qDebug() << "Evaluate Response:" << IN.id << IN.name << IN.args; if(!isBridge){ return; } //this is only valid for bridge connections if(IN.namesp=="events" && IN.name=="bridge"){ QStringList bids = JsonArrayToStringList(IN.args.toObject().value("available_connections").toArray()); @@ -538,14 +545,29 @@ void WebSocket::nowEncrypted(){ } void WebSocket::peerError(const QSslError&){ //peerVerifyError() signal - //qDebug() << "Socket Peer Error:"; + qDebug() << "Socket Peer Error:"; } void WebSocket::SslError(const QList &err){ //sslErrors() signal - LogManager::log(LogManager::HOST,"Connection SSL Errors ["+SockPeerIP+"]: "+err.length()); + QList ignored; + for(int i=0; i< err.length(); i++){ + if(err[i].error()==QSslError::SelfSignedCertificate || err[i].error()==QSslError::HostNameMismatch ){ + //qDebug() << " - (IGNORED) " << err[i].errorString(); + ignored << err[i]; + }else{ + qWarning() << " - " << err[i].errorString(); + } + } + if(ignored.length() != err.length()){ + LogManager::log(LogManager::HOST,"Connection SSL Errors ["+SockPeerIP+"]: "+err.length()); + SOCKET->close(); //SSL errors - close the connection + }else{ + SOCKET->ignoreSslErrors(); + } } void WebSocket::startBridgeAuth(){ + qDebug() << "Init Bridge Auth..."; QJsonObject obj; obj.insert("id", "server_to_bridge_auth"); obj.insert("namespace","rpc"); diff --git a/src/server/main.cpp b/src/server/main.cpp index 28bcd54..e6ac3dd 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -101,8 +101,24 @@ int main( int argc, char ** argv ) i=i+1; }else if(opt=="export_key"){ //Export the public SSL cert used for establishing a connection with a bridge - QString crt = ReadFile("/usr/local/etc/sysadm/ws_bridge.crt"); - qDebug() << crt.toLocal8Bit(); + QFile cfile("/usr/local/etc/sysadm/ws_bridge.crt"); + if( cfile.open(QIODevice::ReadOnly) ){ + QSslCertificate cert(&cfile); + cfile.close(); + if(!cert.isNull()){ + if(i+1