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

View File

@ -48,6 +48,7 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, const bool& localConnection,
, _noListener(noListener) , _noListener(noListener)
, _peerAddress(peerAddress) , _peerAddress(peerAddress)
, _log(log) , _log(log)
, _localConnection(localConnection)
, _instanceManager(HyperionIManager::getInstance()) , _instanceManager(HyperionIManager::getInstance())
, _hyperion(nullptr) , _hyperion(nullptr)
, _jsonCB(new JsonCB(this)) , _jsonCB(new JsonCB(this))
@ -56,20 +57,22 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, const bool& localConnection,
, _ledStreamTimer(new QTimer(this)) , _ledStreamTimer(new QTimer(this))
{ {
Q_INIT_RESOURCE(JSONRPC_schemas); Q_INIT_RESOURCE(JSONRPC_schemas);
}
void JsonAPI::initialize(void)
{
// For security we block external connections if default PW is set // For security we block external connections if default PW is set
if(!localConnection && _authManager->hasHyperionDefaultPw()) if(!_localConnection && _authManager->hasHyperionDefaultPw())
{ {
emit forceClose(); emit forceClose();
} }
// if this is localConnection and network allows unauth locals, set authorized flag // if this is localConnection and network allows unauth locals, set authorized flag
if(_apiAuthRequired && localConnection) if(_apiAuthRequired && _localConnection)
_authorized = !_authManager->isLocalAuthRequired(); _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 // 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. // authorization is also granted for api based on admin result. Pro: Admin should have full access.
if(localConnection) if(_localConnection)
{ {
_userAuthorized = !_authManager->isLocalAdminAuthRequired(); _userAuthorized = !_authManager->isLocalAdminAuthRequired();
_authorized = _userAuthorized; _authorized = _userAuthorized;
@ -1646,6 +1649,9 @@ void JsonAPI::handleInstanceStateChange(const instanceState& state, const quint8
void JsonAPI::stopDataConnections(void) void JsonAPI::stopDataConnections(void)
{ {
LoggerManager::getInstance()->disconnect(); LoggerManager::getInstance()->disconnect();
_streaming_logging_activated = false;
_jsonCB->resetSubscriptions(); _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 // create a new instance of JsonAPI
_jsonAPI = new JsonAPI(socket->peerAddress().toString(), _log, localConnection, this); _jsonAPI = new JsonAPI(socket->peerAddress().toString(), _log, localConnection, this);
// get the callback messages from JsonAPI and send it to the client // 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() void JsonClientConnection::readRequest()

View File

@ -300,8 +300,8 @@ void QtHttpClientWrapper::onReplySendDataRequested (void)
void QtHttpClientWrapper::sendToClientWithReply(QtHttpReply * reply) void QtHttpClientWrapper::sendToClientWithReply(QtHttpReply * reply)
{ {
connect (reply, &QtHttpReply::requestSendHeaders, this, &QtHttpClientWrapper::onReplySendHeadersRequested); connect (reply, &QtHttpReply::requestSendHeaders, this, &QtHttpClientWrapper::onReplySendHeadersRequested, Qt::UniqueConnection);
connect (reply, &QtHttpReply::requestSendData, this, &QtHttpClientWrapper::onReplySendDataRequested); connect (reply, &QtHttpReply::requestSendData, this, &QtHttpClientWrapper::onReplySendDataRequested, Qt::UniqueConnection);
m_parsingStatus = sendReplyToClient (reply); m_parsingStatus = sendReplyToClient (reply);
} }
@ -340,3 +340,19 @@ QtHttpClientWrapper::ParsingStatus QtHttpClientWrapper::sendReplyToClient (QtHtt
return AwaitingRequest; 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 /// @brief Wrapper for sendReplyToClient(), handles m_parsingStatus and signal connect
void sendToClientWithReply (QtHttpReply * reply); void sendToClientWithReply (QtHttpReply * reply);
///
/// @brief close a connection with FORBIDDEN header (used from JsonAPI over HTTP)
///
void closeConnection();
private slots: private slots:
void onClientDataReceived (void); void onClientDataReceived (void);

View File

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

View File

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

View File

@ -25,6 +25,7 @@ WebSocketClient::WebSocketClient(QtHttpRequest* request, QTcpSocket* sock, const
// Json processor // Json processor
_jsonAPI = new JsonAPI(client, _log, localConnection, this); _jsonAPI = new JsonAPI(client, _log, localConnection, this);
connect(_jsonAPI, &JsonAPI::callbackMessage, this, &WebSocketClient::sendMessage); 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)); 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->write(QSTRING_CSTR(data), data.size());
_socket->flush(); _socket->flush();
// Init JsonAPI
_jsonAPI->initialize();
} }
void WebSocketClient::handleWebSocketFrame(void) void WebSocketClient::handleWebSocketFrame(void)
@ -123,7 +127,7 @@ void WebSocketClient::handleWebSocketFrame(void)
handleBinaryMessage(_wsReceiveBuffer); handleBinaryMessage(_wsReceiveBuffer);
} }
_wsReceiveBuffer.clear(); _wsReceiveBuffer.clear();
} }
} }
break; break;