Clean up the server and bridge systems so that connections are now successful as needed.

This commit is contained in:
Ken Moore
2016-05-20 12:40:32 -04:00
parent 6e07eb7c49
commit d8a0faea79
6 changed files with 84 additions and 14 deletions

View File

@@ -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<QSslError> &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;

View File

@@ -50,6 +50,7 @@ private slots:
void SslError(const QList<QSslError>&); //sslErrors() signal
public slots:
void requestIdentify();
void requestKeyList();
void announceIDAvailability(QStringList IDs);

View File

@@ -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; c<OpenSockets.length(); c++){
bool server = OpenSockets[c]->isServer();
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(); }
}

View File

@@ -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"); }

View File

@@ -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<QSslError>&)), this, SLOT(SslError(const QList<QSslError>&)) );
//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<QSslError> &err){ //sslErrors() signal
LogManager::log(LogManager::HOST,"Connection SSL Errors ["+SockPeerIP+"]: "+err.length());
QList<QSslError> 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");

View File

@@ -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<argc){
i++; QString filepath = argv[i];
QFile outfile(filepath);
outfile.open(QIODevice::WriteOnly | QIODevice::Truncate);
outfile.write(cert.publicKey().toPem());
outfile.close();
qDebug() << "Public Key Saved to file:" << filepath;
}else{
//Output to std out instead
qDebug() << cert.publicKey().toPem();
}
}
}
}else{
qDebug() << "Unknown option:" << argv[i];
return 1;
@@ -118,8 +134,13 @@ int main( int argc, char ** argv )
bool ok = true;
if(QFile::exists(key)){
QFile file(key);
if(file.open(QIODevice::ReadOnly)){ key = file.readAll(); file.close(); }
else{ qDebug() << "Could not open file:" << file.fileName(); ok = false; }
QByteArray pubkey;
if(file.open(QIODevice::ReadOnly)){
QSslKey sslkey( &file, QSsl::Rsa, QSsl::Pem, QSsl::PublicKey);
if(!key.isNull()){ pubkey = sslkey.toPem(); }
else{ qDebug() << "Invalid Key file:" << file.fileName(); ok = false; }
file.close();
}else{ qDebug() << "Could not open file:" << file.fileName(); ok = false; }
}
if(ok){ ok = AuthorizationManager::RegisterCertificateInternal(user, key, nickname, email); }
if(ok){ qDebug() << "Key Added" << user << nickname; }