make auth config work
This commit is contained in:
parent
a4658332ff
commit
63ffc163ba
@ -238,16 +238,17 @@ QHash<QString, JsonHandler *> JsonRPCServer::handlers() const
|
||||
}
|
||||
|
||||
/*! Register a new \l{TransportInterface} to the JSON server. The \a enabled flag indivates if the given \a interface sould be enebeld on startup. */
|
||||
void JsonRPCServer::registerTransportInterface(TransportInterface *interface, const bool &enabled)
|
||||
void JsonRPCServer::registerTransportInterface(TransportInterface *interface, bool enabled, bool authenticationRequired)
|
||||
{
|
||||
connect(interface, &TransportInterface::clientConnected, this, &JsonRPCServer::clientConnected);
|
||||
connect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServer::clientDisconnected);
|
||||
connect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServer::processData);
|
||||
|
||||
if (enabled)
|
||||
QMetaObject::invokeMethod(interface, "startServer", Qt::QueuedConnection);
|
||||
m_interfaces.insert(interface, authenticationRequired);
|
||||
|
||||
m_interfaces.append(interface);
|
||||
if (enabled) {
|
||||
QMetaObject::invokeMethod(interface, "startServer", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
/*! Send a JSON success response to the client with the given \a clientId,
|
||||
@ -330,18 +331,21 @@ void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &data)
|
||||
QString targetNamespace = commandList.first();
|
||||
QString method = commandList.last();
|
||||
|
||||
// if there is no user in the system yet, let's fail unless this is a CreateUser or Introspect call
|
||||
if (GuhCore::instance()->userManager()->users().isEmpty()) {
|
||||
if (!(targetNamespace == "JSONRPC" && (method == "CreateUser" || method == "Introspect"))) {
|
||||
sendUnauthorizedResponse(interface, clientId, commandId, "Initial setup required. Call CreateUser first.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// ok, we have a user. if there isn't a valid token, let's fail unless this is a Authenticate or Introspect call
|
||||
QByteArray token = message.value("token").toByteArray();
|
||||
if (!(targetNamespace == "JSONRPC" && (method == "Authenticate" || method == "Introspect")) && !GuhCore::instance()->userManager()->verifyToken(token)) {
|
||||
sendUnauthorizedResponse(interface, clientId, commandId, "Forbidden: Invalid token.");
|
||||
return;
|
||||
// check if authentication is required for this transport
|
||||
if (m_interfaces.value(interface)) {
|
||||
// if there is no user in the system yet, let's fail unless this is a CreateUser or Introspect call
|
||||
if (GuhCore::instance()->userManager()->users().isEmpty()) {
|
||||
if (!(targetNamespace == "JSONRPC" && (method == "CreateUser" || method == "Introspect"))) {
|
||||
sendUnauthorizedResponse(interface, clientId, commandId, "Initial setup required. Call CreateUser first.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// ok, we have a user. if there isn't a valid token, let's fail unless this is a Authenticate or Introspect call
|
||||
QByteArray token = message.value("token").toByteArray();
|
||||
if (!(targetNamespace == "JSONRPC" && (method == "Authenticate" || method == "Introspect")) && !GuhCore::instance()->userManager()->verifyToken(token)) {
|
||||
sendUnauthorizedResponse(interface, clientId, commandId, "Forbidden: Invalid token.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// At this point we can assume all the calls are authorized
|
||||
@ -404,7 +408,7 @@ void JsonRPCServer::sendNotification(const QVariantMap ¶ms)
|
||||
notification.insert("notification", handler->name() + "." + method.name());
|
||||
notification.insert("params", params);
|
||||
|
||||
foreach (TransportInterface *interface, m_interfaces) {
|
||||
foreach (TransportInterface *interface, m_interfaces.keys()) {
|
||||
interface->sendData(m_clients.keys(true), QJsonDocument::fromVariant(notification).toJson());
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ public:
|
||||
|
||||
QHash<QString, JsonHandler *> handlers() const;
|
||||
|
||||
void registerTransportInterface(TransportInterface *interface, const bool &enabled = true);
|
||||
void registerTransportInterface(TransportInterface *interface, bool enabled, bool authenticationRequired);
|
||||
|
||||
private:
|
||||
void sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap ¶ms = QVariantMap());
|
||||
@ -78,7 +78,7 @@ private slots:
|
||||
void asyncReplyFinished();
|
||||
|
||||
private:
|
||||
QList<TransportInterface *> m_interfaces;
|
||||
QMap<TransportInterface*, bool> m_interfaces;
|
||||
QHash<QString, JsonHandler *> m_handlers;
|
||||
QHash<JsonReply *, TransportInterface *> m_asyncReplies;
|
||||
|
||||
|
||||
@ -94,22 +94,22 @@ ServerManager::ServerManager(GuhConfiguration* configuration, QObject *parent) :
|
||||
// Transports
|
||||
#ifdef TESTING_ENABLED
|
||||
MockTcpServer *tcpServer = new MockTcpServer(this);
|
||||
m_jsonServer->registerTransportInterface(tcpServer);
|
||||
m_jsonServer->registerTransportInterface(tcpServer, true, true);
|
||||
#else
|
||||
foreach (const ServerConfiguration &config, configuration->tcpServerConfigurations()) {
|
||||
TcpServer *tcpServer = new TcpServer(config.address, config.port, config.sslEnabled, m_sslConfiguration, this);
|
||||
m_jsonServer->registerTransportInterface(tcpServer);
|
||||
m_jsonServer->registerTransportInterface(tcpServer, true, config.authenticationEnabled);
|
||||
}
|
||||
#endif
|
||||
|
||||
foreach (const ServerConfiguration &config, configuration->webSocketServerConfigurations()) {
|
||||
qWarning() << "Have websockeserver config" << config.id;
|
||||
WebSocketServer *webSocketServer = new WebSocketServer(config.address, config.port, config.sslEnabled, m_sslConfiguration, this);
|
||||
m_jsonServer->registerTransportInterface(webSocketServer);
|
||||
m_jsonServer->registerTransportInterface(webSocketServer, true, config.authenticationEnabled);
|
||||
}
|
||||
|
||||
m_bluetoothServer = new BluetoothServer(this);
|
||||
m_jsonServer->registerTransportInterface(m_bluetoothServer, configuration->bluetoothServerEnabled());
|
||||
m_jsonServer->registerTransportInterface(m_bluetoothServer, configuration->bluetoothServerEnabled(), true);
|
||||
|
||||
foreach (const WebServerConfiguration &config, configuration->webServerConfigurations()) {
|
||||
WebServer *webServer = new WebServer(config.address, config.port, config.publicFolder, config.sslEnabled, m_sslConfiguration, this);
|
||||
|
||||
@ -80,53 +80,25 @@ void TcpServer::sendData(const QUuid &clientId, const QByteArray &data)
|
||||
QTcpSocket *client = 0;
|
||||
client = m_clientList.value(clientId);
|
||||
if (client) {
|
||||
qWarning() << "send data:" << data;
|
||||
client->write(data);
|
||||
}
|
||||
}
|
||||
|
||||
void TcpServer::onClientConnected(QSslSocket *socket)
|
||||
{
|
||||
// got a new client connected
|
||||
qCDebug(dcConnection) << "Tcp server: new client connected:" << socket->peerAddress().toString();
|
||||
|
||||
QUuid clientId = QUuid::createUuid();
|
||||
|
||||
// append the new client to the client list
|
||||
m_clientList.insert(clientId, socket);
|
||||
|
||||
emit clientConnected(clientId);
|
||||
}
|
||||
|
||||
void TcpServer::readPackage()
|
||||
void TcpServer::onClientDisconnected(QSslSocket *socket)
|
||||
{
|
||||
QTcpSocket *client = qobject_cast<QTcpSocket*>(sender());
|
||||
qCDebug(dcTcpServer) << "Data coming from" << client->peerAddress().toString();
|
||||
QByteArray message;
|
||||
while (client->canReadLine()) {
|
||||
QByteArray dataLine = client->readLine();
|
||||
qCDebug(dcTcpServer) << "Line in:" << dataLine;
|
||||
message.append(dataLine);
|
||||
if (dataLine.endsWith('\n')) {
|
||||
emit dataAvailable(m_clientList.key(client), message);
|
||||
message.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TcpServer::onSslErrors(const QList<QSslError> &errors)
|
||||
{
|
||||
qCWarning(dcTcpServer) << "SSL errors:" << errors;
|
||||
}
|
||||
|
||||
void TcpServer::onClientDisconnected()
|
||||
{
|
||||
QPointer<QTcpSocket> client = qobject_cast<QTcpSocket *>(sender());
|
||||
if (client.isNull())
|
||||
return;
|
||||
|
||||
qCDebug(dcConnection) << "Tcp server: client disconnected:" << client->peerAddress().toString();
|
||||
QUuid clientId = m_clientList.key(client);
|
||||
m_clientList.take(clientId)->deleteLater();
|
||||
qCDebug(dcConnection) << "Tcp server: client disconnected:" << socket->peerAddress().toString();
|
||||
QUuid clientId = m_clientList.key(socket);
|
||||
m_clientList.take(clientId);
|
||||
emit clientDisconnected(clientId);
|
||||
}
|
||||
|
||||
void TcpServer::onError(QAbstractSocket::SocketError error)
|
||||
@ -141,6 +113,12 @@ void TcpServer::onEncrypted()
|
||||
qCDebug(dcTcpServer) << "TCP Server connection encrypted";
|
||||
}
|
||||
|
||||
void TcpServer::onDataAvailable(QSslSocket * socket, const QByteArray &data)
|
||||
{
|
||||
QUuid clientId = m_clientList.key(socket);
|
||||
emit dataAvailable(clientId, data);
|
||||
}
|
||||
|
||||
void TcpServer::onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state)
|
||||
{
|
||||
if (state == QtAvahiService::QtAvahiServiceStateEstablished) {
|
||||
@ -204,6 +182,8 @@ bool TcpServer::startServer()
|
||||
|
||||
qCDebug(dcConnection) << "Started Tcp server on" << m_server->serverAddress().toString() << m_server->serverPort();
|
||||
connect(m_server, SIGNAL(clientConnected(QSslSocket *)), SLOT(onClientConnected(QSslSocket *)));
|
||||
connect(m_server, SIGNAL(clientDisconnected(QSslSocket *)), SLOT(onClientDisconnected(QSslSocket *)));
|
||||
connect(m_server, &SslServer::dataAvailable, this, &TcpServer::onDataAvailable);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -231,23 +211,17 @@ void SslServer::incomingConnection(qintptr socketDescriptor)
|
||||
{
|
||||
qWarning() << "incoming";
|
||||
QSslSocket *sslSocket = new QSslSocket(this);
|
||||
connect(sslSocket, &QSslSocket::encrypted, [this, sslSocket](){
|
||||
qWarning() << "encrypted";
|
||||
emit clientConnected(sslSocket);
|
||||
});
|
||||
|
||||
connect(sslSocket, &QSslSocket::readyRead, [this, sslSocket]() {
|
||||
qWarning() << "readyRead:" << sslSocket->readAll();
|
||||
// sslSocket->startServerEncryption();
|
||||
});
|
||||
connect(sslSocket, &QSslSocket::encrypted, [this, sslSocket](){ emit clientConnected(sslSocket); });
|
||||
connect(sslSocket, &QSslSocket::readyRead, this, &SslServer::onSocketReadyRead);
|
||||
connect(sslSocket, &QSslSocket::disconnected, this, &SslServer::onClientDisconnected);
|
||||
|
||||
if (!sslSocket->setSocketDescriptor(socketDescriptor)) {
|
||||
qCWarning(dcConnection) << "Failed to set SSL socket";
|
||||
qCWarning(dcConnection) << "Failed to set SSL socket descriptor.";
|
||||
delete sslSocket;
|
||||
return;
|
||||
}
|
||||
if (m_sslEnabled) {
|
||||
qWarning() << "starting encryption";
|
||||
sslSocket->setSslConfiguration(m_config);
|
||||
sslSocket->startServerEncryption();
|
||||
} else {
|
||||
@ -255,4 +229,18 @@ void SslServer::incomingConnection(qintptr socketDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
void SslServer::onClientDisconnected()
|
||||
{
|
||||
QSslSocket *socket = static_cast<QSslSocket*>(sender());
|
||||
emit clientDisconnected(socket);
|
||||
socket->deleteLater();
|
||||
}
|
||||
|
||||
void SslServer::onSocketReadyRead()
|
||||
{
|
||||
QSslSocket *socket = static_cast<QSslSocket*>(sender());
|
||||
QByteArray data = socket->readAll();
|
||||
emit dataAvailable(socket, data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -52,10 +52,16 @@ public:
|
||||
|
||||
signals:
|
||||
void clientConnected(QSslSocket *socket);
|
||||
void clientDisconnected(QSslSocket *socket);
|
||||
void dataAvailable(QSslSocket *socket, const QByteArray &data);
|
||||
|
||||
protected:
|
||||
void incomingConnection(qintptr socketDescriptor) override;
|
||||
|
||||
private slots:
|
||||
void onClientDisconnected();
|
||||
void onSocketReadyRead();
|
||||
|
||||
private:
|
||||
bool m_sslEnabled = false;
|
||||
QSslConfiguration m_config;
|
||||
@ -87,9 +93,8 @@ private:
|
||||
|
||||
private slots:
|
||||
void onClientConnected(QSslSocket *socket);
|
||||
void onClientDisconnected();
|
||||
void readPackage();
|
||||
void onSslErrors(const QList<QSslError> &errors);
|
||||
void onClientDisconnected(QSslSocket *socket);
|
||||
void onDataAvailable(QSslSocket *socket, const QByteArray &data);
|
||||
void onError(QAbstractSocket::SocketError error);
|
||||
void onEncrypted();
|
||||
|
||||
|
||||
@ -143,27 +143,6 @@ void WebServer::sendHttpReply(HttpReply *reply)
|
||||
socket->write(reply->data());
|
||||
}
|
||||
|
||||
/*! Returns the port on which the webserver is listening. */
|
||||
int WebServer::port() const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
/*! Returns the list of addresses on which the webserver is listening. */
|
||||
QList<QHostAddress> WebServer::serverAddressList()
|
||||
{
|
||||
QList<QHostAddress> addresses;
|
||||
foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) {
|
||||
// listen only on IPv4
|
||||
foreach (QNetworkAddressEntry entry, interface.addressEntries()) {
|
||||
if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
addresses.append(entry.ip());
|
||||
}
|
||||
}
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
|
||||
bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName)
|
||||
{
|
||||
QFileInfo file(fileName);
|
||||
@ -235,17 +214,6 @@ HttpReply *WebServer::processIconRequest(const QString &fileName)
|
||||
return RestResource::createErrorReply(HttpReply::NotFound);
|
||||
}
|
||||
|
||||
QHostAddress WebServer::getServerAddress(QHostAddress clientAddress)
|
||||
{
|
||||
foreach (QHostAddress address, serverAddressList()) {
|
||||
if (clientAddress.isInSubnet(QHostAddress::parseSubnet(address.toString() + "/24"))) {
|
||||
qCDebug(dcWebServer) << "server for" << clientAddress.toString() << " ->" << address.toString();
|
||||
return address;
|
||||
}
|
||||
}
|
||||
return QHostAddress();
|
||||
}
|
||||
|
||||
void WebServer::incomingConnection(qintptr socketDescriptor)
|
||||
{
|
||||
if (!m_enabled)
|
||||
@ -397,8 +365,7 @@ void WebServer::readClient()
|
||||
qCDebug(dcWebServer) << "server XML request call";
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/xml");
|
||||
QHostAddress serverAddress = getServerAddress(socket->peerAddress());
|
||||
reply->setPayload(createServerXmlDocument(serverAddress));
|
||||
reply->setPayload(createServerXmlDocument(m_host));
|
||||
reply->setClientId(clientId);
|
||||
sendHttpReply(reply);
|
||||
reply->deleteLater();
|
||||
@ -553,12 +520,10 @@ bool WebServer::startServer()
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (QHostAddress address, serverAddressList()) {
|
||||
if (m_useSsl) {
|
||||
qCDebug(dcConnection) << "Started webserver on" << QString("https://%1:%2").arg(address.toString()).arg(m_port);
|
||||
} else {
|
||||
qCDebug(dcConnection) << "Started webserver on" << QString("http://%1:%2").arg(address.toString()).arg(m_port);
|
||||
}
|
||||
if (m_useSsl) {
|
||||
qCDebug(dcConnection) << "Started webserver on" << QString("https://%1:%2").arg(m_host.toString()).arg(m_port);
|
||||
} else {
|
||||
qCDebug(dcConnection) << "Started webserver on" << QString("http://%1:%2").arg(m_host.toString()).arg(m_port);
|
||||
}
|
||||
|
||||
#ifndef TESTING_ENABLED
|
||||
|
||||
@ -76,9 +76,6 @@ public:
|
||||
~WebServer();
|
||||
|
||||
void sendHttpReply(HttpReply *reply);
|
||||
int port() const;
|
||||
QList<QHostAddress> serverAddressList();
|
||||
|
||||
|
||||
private:
|
||||
QHash<QUuid, QSslSocket *> m_clientList;
|
||||
@ -101,7 +98,6 @@ private:
|
||||
|
||||
QByteArray createServerXmlDocument(QHostAddress address);
|
||||
HttpReply *processIconRequest(const QString &fileName);
|
||||
QHostAddress getServerAddress(QHostAddress clientAddress);
|
||||
|
||||
protected:
|
||||
void incomingConnection(qintptr socketDescriptor) override;
|
||||
|
||||
Reference in New Issue
Block a user