diff --git a/src/server/AuthorizationManager.cpp b/src/server/AuthorizationManager.cpp index b463278..45b2b0c 100644 --- a/src/server/AuthorizationManager.cpp +++ b/src/server/AuthorizationManager.cpp @@ -231,6 +231,35 @@ QString AuthorizationManager::GenerateEncCheckString(){ return key; } +QString AuthorizationManager::GenerateEncString_bridge(QString str){ + //Get the private key + return str; //NOT IMPLEMENTED YET + QByteArray privkey = "";//SSL_cfg.privateKey().toPem(); + + //Now use this private key to encode the given string + unsigned char encode[4098] = {}; + RSA *rsa= NULL; + BIO *keybio = NULL; + keybio = BIO_new_mem_buf(privkey.data(), -1); + if(keybio==NULL){ return ""; } + rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL); + if(rsa==NULL){ return ""; } + int len = RSA_private_encrypt(str.length(), (unsigned char*)(str.toLatin1().data()), encode, rsa, RSA_PKCS1_PADDING); + if(len <0){ return ""; } + else{ + //Now return this as a base64 encoded string + QByteArray str_encode( (char*)(encode), len); + /*qDebug() << "Encoded String Info"; + qDebug() << " - Raw string:" << str << "Length:" << str.length(); + qDebug() << " - Encoded string:" << str_encode << "Length:" << str_encode.length();*/ + str_encode = str_encode.toBase64(); + /*qDebug() << " - Enc string (base64):" << str_encode << "Length:" << str_encode.length(); + qDebug() << " - Enc string (QString):" << QString(str_encode);*/ + return QString( str_encode ); + } + +} + //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 @@ -294,11 +323,12 @@ QString AuthorizationManager::LoginUC(QHostAddress host, QString encstring){ } QString AuthorizationManager::encryptString(QString msg, QString key){ - + //do nothing yet + return msg; } QString AuthorizationManager::decryptString(QString msg, QString key){ - + return msg; //do nothing yet } // ========================= diff --git a/src/server/AuthorizationManager.h b/src/server/AuthorizationManager.h index e74342e..bcbcca2 100644 --- a/src/server/AuthorizationManager.h +++ b/src/server/AuthorizationManager.h @@ -32,7 +32,9 @@ public: QString LoginService(QHostAddress host, QString service); //Login a particular automated service //Stage 1 SSL Login Check: Generation of random string for this user - QString GenerateEncCheckString(); + QString GenerateEncCheckString(); //generate random string (server is receiver w/ pub key) + QString GenerateEncString_bridge(QString str); //encrypt random string (server is initiator w/ private key) + //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); diff --git a/src/server/WebServer.cpp b/src/server/WebServer.cpp index 709a600..28ce2de 100644 --- a/src/server/WebServer.cpp +++ b/src/server/WebServer.cpp @@ -15,6 +15,9 @@ WebServer::WebServer(){ //Setup all the various settings WSServer = 0; TCPServer = 0; + bridgeTimer = new QTimer(this); + bridgeTimer->setInterval(5*60*1000); //5 minutes + connect(bridgeTimer, SIGNAL(timeout()), this, SLOT(checkBridges()) ); AUTH = new AuthorizationManager(); connect(AUTH, SIGNAL(BlockHost(QHostAddress)), this, SLOT(BlackListConnection(QHostAddress)) ); } @@ -30,7 +33,7 @@ bool WebServer::startServer(quint16 port, bool websocket){ qDebug() << " - Version:" << QSslSocket::sslLibraryVersionString(); } bool ok = false; - if(websocket){ ok = setupWebSocket(port); } + if(websocket){ ok = setupWebSocket(port); } else{ ok = setupTcp(port); } if(ok){ @@ -41,11 +44,15 @@ bool WebServer::startServer(quint16 port, bool websocket){ }else{ qCritical() << "Could not start server - exiting..."; } - + if(ok && websocket){ + bridgeTimer->start(); + QTimer::singleShot(5, this, SLOT(checkBridges())); + } return ok; } void WebServer::stopServer(){ + if(bridgeTimer->isActive()){ bridgeTimer->stop(); } if(WSServer!=0){ WSServer->close(); } //note - this will throw the "closed()" signal when done else if(TCPServer!=0){ TCPServer->close(); QCoreApplication::exit(0);} //no corresponding signal } @@ -206,3 +213,8 @@ void WebServer::SocketClosed(QString ID){ } QTimer::singleShot(0,this, SLOT(NewSocketConnection()) ); //check for a new connection } + +// BRIDGE Connection checks +void WebServer::checkBridges(){ + +} diff --git a/src/server/WebServer.h b/src/server/WebServer.h index a3fa0c5..6041c0c 100644 --- a/src/server/WebServer.h +++ b/src/server/WebServer.h @@ -28,7 +28,8 @@ private: SslServer *TCPServer; QList OpenSockets; AuthorizationManager *AUTH; - + QTimer *bridgeTimer; + //Server Setup functions bool setupWebSocket(quint16 port); bool setupTcp(quint16 port); @@ -56,9 +57,12 @@ private slots: void SslErrors(const QList&); //sslErrors() signal void SocketClosed(QString ID); + // BRIDGE Connection checks + void checkBridges(); + signals: //void DispatchStatusUpdate(QString); }; -#endif \ No newline at end of file +#endif diff --git a/src/server/WebSocket.cpp b/src/server/WebSocket.cpp index a8c4c7b..a5f68f1 100644 --- a/src/server/WebSocket.cpp +++ b/src/server/WebSocket.cpp @@ -59,6 +59,31 @@ WebSocket::WebSocket(QSslSocket *sock, QString ID, AuthorizationManager *auth){ QTimer::singleShot(30000, this, SLOT(checkAuth())); } +WebSocket::WebSocket(QUrl url, QString ID, AuthorizationManager *auth){ + //sets up a bridge connection (websocket only) + SockID = ID; + isBridge = true; + SockAuthToken.clear(); //nothing set initially + SOCKET = new QWebSocket("sysadm-server", QWebSocketProtocol::VersionLatest, this); + TSOCKET = 0; + AUTHSYSTEM = auth; + SockPeerIP = SOCKET->peerAddress().toString(); + LogManager::log(LogManager::HOST,"New Connection: "+SockPeerIP); + idletimer = new QTimer(this); + idletimer->setInterval(IDLETIMEOUTMINS*60000); //connection timout for idle sockets + idletimer->setSingleShot(true); + connect(idletimer, SIGNAL(timeout()), this, SLOT(checkIdle()) ); + 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()) ); + 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()) ); + //idletimer->start(); //do not idle out on a bridge connection + /*QTimer::singleShot(30000, this, SLOT(checkAuth()));*/ + SOCKET->open(url); +} + WebSocket::~WebSocket(){ //qDebug() << "SOCKET Destroyed"; if(SOCKET!=0 && SOCKET->isValid()){ @@ -143,7 +168,7 @@ void WebSocket::EvaluateRequest(const RestInputStruct &REQ){ if(SOCKET!=0 && SOCKET->isValid()){ host = SOCKET->peerAddress(); } else if(TSOCKET!=0 && TSOCKET->isValid()){ host = TSOCKET->peerAddress(); } QString cur_auth_tok = SockAuthToken; - if(!REQ.bridgeID.isEmpty()){ + if(!REQ.bridgeID.isEmpty() || isBridge){ //never clear/check the SockAuthToken itself on a bridge - this was assigned by the bridge and not created here cur_auth_tok.clear(); if(BRIDGE.contains(REQ.bridgeID)){ cur_auth_tok = BRIDGE[REQ.bridgeID].auth_tok; } } @@ -317,6 +342,7 @@ if(out.in_struct.namesp.toLower() == "rpc"){ } void WebSocket::EvaluateResponse(const RestInputStruct& IN){ + 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()); QStringList keys = BRIDGE.keys(); @@ -328,6 +354,28 @@ void WebSocket::EvaluateResponse(const RestInputStruct& IN){ for(int i=0; iGenerateEncString_bridge(test); + //Now send the string back + QJsonObject obj, args; + obj.insert("id","server_to_bridge_auth"); + obj.insert("namespace","rpc"); + obj.insert("name","auth_ssl"); + args.insert("encrypted_string", enc_test); + obj.insert("args", args); + this->sendReply( QJsonDocument(obj).toJson(QJsonDocument::Compact) ); + } } } // === GENERAL PURPOSE UTILITY FUNCTIONS === @@ -477,6 +525,16 @@ void WebSocket::SslError(const QList &err){ //sslErrors() signal LogManager::log(LogManager::HOST,"Connection SSL Errors ["+SockPeerIP+"]: "+err.length()); } +void WebSocket::startBridgeAuth(){ + QJsonObject obj; + obj.insert("id", "server_to_bridge_auth"); + obj.insert("namespace","rpc"); + obj.insert("name","auth_ssl"); + obj.insert("args",""); + + this->sendReply( QJsonDocument(obj).toJson(QJsonDocument::Compact) ); +} + // ====================== // PUBLIC SLOTS // ====================== diff --git a/src/server/WebSocket.h b/src/server/WebSocket.h index c77560e..694a8c9 100644 --- a/src/server/WebSocket.h +++ b/src/server/WebSocket.h @@ -20,6 +20,7 @@ class WebSocket : public QObject{ public: WebSocket(QWebSocket*, QString ID, AuthorizationManager *auth); WebSocket(QSslSocket*, QString ID, AuthorizationManager *auth); + WebSocket(QUrl, QString ID, AuthorizationManager *auth); //sets up a bridge connection (websocket only) ~WebSocket(); QString ID(); @@ -105,6 +106,9 @@ private slots: void slotIohyveFetchDone(QString, int, QString); void slotIohyveFetchProcessOutput(QString); + //Bridge Connection Handling + void startBridgeAuth(); + public slots: void EventUpdate(EventWatcher::EVENT_TYPE, QJsonValue = QJsonValue() );