Feat: Close connection if ext clients when def pw is set

This commit is contained in:
brindosch 2019-08-30 18:49:38 +02:00
parent 1e4c29dacb
commit 5553199cc4
8 changed files with 61 additions and 12 deletions

View File

@ -37,6 +37,11 @@ public:
///
void handleMessage(const QString & message, const QString& httpAuthHeader = "");
///
/// @brief Initialization steps
///
void initialize(void);
public slots:
///
/// @brief Is called whenever the current Hyperion instance pushes new led raw values (if enabled)
@ -117,6 +122,9 @@ private:
/// Log instance
Logger* _log;
/// Is this a local connection
bool _localConnection;
/// Hyperion instance manager
HyperionIManager* _instanceManager;

View File

@ -48,6 +48,7 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, const bool& localConnection,
, _noListener(noListener)
, _peerAddress(peerAddress)
, _log(log)
, _localConnection(localConnection)
, _instanceManager(HyperionIManager::getInstance())
, _hyperion(nullptr)
, _jsonCB(new JsonCB(this))
@ -56,20 +57,22 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, const bool& localConnection,
, _ledStreamTimer(new QTimer(this))
{
Q_INIT_RESOURCE(JSONRPC_schemas);
}
void JsonAPI::initialize(void)
{
// For security we block external connections if default PW is set
if(!localConnection && _authManager->hasHyperionDefaultPw())
if(!_localConnection && _authManager->hasHyperionDefaultPw())
{
emit forceClose();
}
// if this is localConnection and network allows unauth locals, set authorized flag
if(_apiAuthRequired && localConnection)
if(_apiAuthRequired && _localConnection)
_authorized = !_authManager->isLocalAuthRequired();
// admin access is allowed, when the connection is local and the option for local admin isn't set. Con: All local connections get full access
// authorization is also granted for api based on admin result. Pro: Admin should have full access.
if(localConnection)
if(_localConnection)
{
_userAuthorized = !_authManager->isLocalAdminAuthRequired();
_authorized = _userAuthorized;
@ -1646,6 +1649,9 @@ void JsonAPI::handleInstanceStateChange(const instanceState& state, const quint8
void JsonAPI::stopDataConnections(void)
{
LoggerManager::getInstance()->disconnect();
_streaming_logging_activated = false;
_jsonCB->resetSubscriptions();
_imageStreamTimer->stop();
_ledStreamTimer->stop();
}

View File

@ -17,7 +17,10 @@ JsonClientConnection::JsonClientConnection(QTcpSocket *socket, const bool& local
// create a new instance of JsonAPI
_jsonAPI = new JsonAPI(socket->peerAddress().toString(), _log, localConnection, this);
// get the callback messages from JsonAPI and send it to the client
connect(_jsonAPI,SIGNAL(callbackMessage(QJsonObject)),this,SLOT(sendMessage(QJsonObject)));
connect(_jsonAPI, &JsonAPI::callbackMessage, this , &JsonClientConnection::sendMessage);
connect(_jsonAPI, &JsonAPI::forceClose, this , [&](){ _socket->close(); } );
_jsonAPI->initialize();
}
void JsonClientConnection::readRequest()

View File

@ -300,8 +300,8 @@ void QtHttpClientWrapper::onReplySendDataRequested (void)
void QtHttpClientWrapper::sendToClientWithReply(QtHttpReply * reply)
{
connect (reply, &QtHttpReply::requestSendHeaders, this, &QtHttpClientWrapper::onReplySendHeadersRequested);
connect (reply, &QtHttpReply::requestSendData, this, &QtHttpClientWrapper::onReplySendDataRequested);
connect (reply, &QtHttpReply::requestSendHeaders, this, &QtHttpClientWrapper::onReplySendHeadersRequested, Qt::UniqueConnection);
connect (reply, &QtHttpReply::requestSendData, this, &QtHttpClientWrapper::onReplySendDataRequested, Qt::UniqueConnection);
m_parsingStatus = sendReplyToClient (reply);
}
@ -340,3 +340,19 @@ QtHttpClientWrapper::ParsingStatus QtHttpClientWrapper::sendReplyToClient (QtHtt
return AwaitingRequest;
}
void QtHttpClientWrapper::closeConnection()
{
// probably filter for request to follow http spec
if(m_currentRequest != Q_NULLPTR)
{
QtHttpReply reply(m_serverHandle);
reply.setStatusCode(QtHttpReply::StatusCode::Forbidden);
connect (&reply, &QtHttpReply::requestSendHeaders, this, &QtHttpClientWrapper::onReplySendHeadersRequested, Qt::UniqueConnection);
connect (&reply, &QtHttpReply::requestSendData, this, &QtHttpClientWrapper::onReplySendDataRequested, Qt::UniqueConnection);
m_parsingStatus = sendReplyToClient(&reply);
}
m_sockClient->close ();
}

View File

@ -34,6 +34,11 @@ public:
/// @brief Wrapper for sendReplyToClient(), handles m_parsingStatus and signal connect
void sendToClientWithReply (QtHttpReply * reply);
///
/// @brief close a connection with FORBIDDEN header (used from JsonAPI over HTTP)
///
void closeConnection();
private slots:
void onClientDataReceived (void);

View File

@ -15,14 +15,20 @@ WebJsonRpc::WebJsonRpc(QtHttpRequest* request, QtHttpServer* server, const bool&
const QString client = request->getClientInfo().clientAddress.toString();
_jsonAPI = new JsonAPI(client, _log, localConnection, this, true);
connect(_jsonAPI, &JsonAPI::callbackMessage, this, &WebJsonRpc::handleCallback);
connect(_jsonAPI, &JsonAPI::forceClose, [&]() { _wrapper->closeConnection(); _stopHandle = true; });
_jsonAPI->initialize();
}
void WebJsonRpc::handleMessage(QtHttpRequest* request)
{
QByteArray header = request->getHeader("Authorization");
QByteArray data = request->getRawData();
_unlocked = true;
_jsonAPI->handleMessage(data,header);
// TODO better solution. If jsonAPI emits forceClose the request is deleted and the following call to this method results in segfault
if(!_stopHandle)
{
QByteArray header = request->getHeader("Authorization");
QByteArray data = request->getRawData();
_unlocked = true;
_jsonAPI->handleMessage(data,header);
}
}
void WebJsonRpc::handleCallback(QJsonObject obj)

View File

@ -22,6 +22,7 @@ private:
Logger* _log;
JsonAPI* _jsonAPI;
bool _stopHandle = false;
bool _unlocked = false;
private slots:

View File

@ -25,6 +25,7 @@ WebSocketClient::WebSocketClient(QtHttpRequest* request, QTcpSocket* sock, const
// Json processor
_jsonAPI = new JsonAPI(client, _log, localConnection, this);
connect(_jsonAPI, &JsonAPI::callbackMessage, this, &WebSocketClient::sendMessage);
connect(_jsonAPI, &JsonAPI::forceClose, this,[this]() { this->sendClose(CLOSECODE::NORMAL); });
Debug(_log, "New connection from %s", QSTRING_CSTR(client));
@ -40,6 +41,9 @@ WebSocketClient::WebSocketClient(QtHttpRequest* request, QTcpSocket* sock, const
_socket->write(QSTRING_CSTR(data), data.size());
_socket->flush();
// Init JsonAPI
_jsonAPI->initialize();
}
void WebSocketClient::handleWebSocketFrame(void)
@ -123,7 +127,7 @@ void WebSocketClient::handleWebSocketFrame(void)
handleBinaryMessage(_wsReceiveBuffer);
}
_wsReceiveBuffer.clear();
}
}
break;