summaryrefslogtreecommitdiffstats
path: root/signet
diff options
context:
space:
mode:
authorBen Boeckel <MathStuf@gmail.com>2008-11-01 01:08:10 +0000
committerBen Boeckel <MathStuf@gmail.com>2008-11-01 01:08:10 +0000
commiteda2022859e7cfde9197a34d9318a9ccec50d841 (patch)
treebe51b862c06475932086c81cf43397008d773211 /signet
parentff3295a0ede441caef7a133d2f4f4a472b5b7cde (diff)
downloadsigen-eda2022859e7cfde9197a34d9318a9ccec50d841.tar.gz
sigen-eda2022859e7cfde9197a34d9318a9ccec50d841.tar.xz
sigen-eda2022859e7cfde9197a34d9318a9ccec50d841.zip
[FIX] Code for challenge-based login complete
[FIX] Protocol is getting started [FIX] Removed the kdegames dependency until it's actually here [FIX] Using QCA2 for hashing git-svn-id: https://pokegen.svn.sourceforge.net/svnroot/pokegen/trunk@289 6ecfd1a5-f3ed-3746-8530-beee90d26b22
Diffstat (limited to 'signet')
-rw-r--r--signet/CMakeLists.txt13
-rw-r--r--signet/ConnectionHandler.cpp91
-rw-r--r--signet/ConnectionHandler.h22
-rw-r--r--signet/Server.cpp10
-rw-r--r--signet/Server.h2
-rw-r--r--signet/protocol/ChallengeMediator.cpp135
-rw-r--r--signet/protocol/ChallengeMediator.h74
-rw-r--r--signet/protocol/Packet.cpp52
-rw-r--r--signet/protocol/Packet.h62
-rw-r--r--signet/protocol/PacketMaker.cpp35
-rw-r--r--signet/protocol/PacketMaker.h57
11 files changed, 549 insertions, 4 deletions
diff --git a/signet/CMakeLists.txt b/signet/CMakeLists.txt
index b9eba0b5..acdf5dc8 100644
--- a/signet/CMakeLists.txt
+++ b/signet/CMakeLists.txt
@@ -4,7 +4,13 @@ IF (NOT SIGEN_VERSION)
MESSAGE(FATAL_ERROR "Sigen version is not defined")
ENDIF (NOT SIGEN_VERSION)
+SET(signet_PROTOCOL_HEADERS
+ protocol/ChallengeMediator.h
+ protocol/Packet.h
+ protocol/PacketMaker.h
+)
SET(signet_HEADERS
+ ${signet_PROTOCOL_HEADERS}
Client.h
ConnectionHandler.h
Global.h
@@ -12,7 +18,13 @@ SET(signet_HEADERS
Server.h
Table.h
)
+SET(signet_PROTOCOL_SRCS
+ protocol/ChallengeMediator.cpp
+ protocol/Packet.cpp
+ protocol/PacketMaker.cpp
+)
SET(signet_SRCS
+ ${signet_PROTOCOL_SRCS}
Client.cpp
ConnectionHandler.cpp
Room.cpp
@@ -34,6 +46,7 @@ TARGET_LINK_LIBRARIES(signet
${QT_QTCORE_LIBRARY}
${QT_QTNETWORK_LIBRARY}
${KDE4_KDECORE_LIBRARY}
+ ${QCA2_LIBRARIES}
)
INSTALL(
diff --git a/signet/ConnectionHandler.cpp b/signet/ConnectionHandler.cpp
index e72950cd..98c2420b 100644
--- a/signet/ConnectionHandler.cpp
+++ b/signet/ConnectionHandler.cpp
@@ -20,12 +20,103 @@
// Signet includes
#include "Client.h"
+#include "protocol/ChallengeMediator.h"
+
+// QCA includes
+#include <QtCrypto/QtCrypto>
+
+// Qt includes
+#include <QtCore/QUuid>
+#include <QtNetwork/QHostAddress>
+#include <QtNetwork/QTcpSocket>
Signet::ConnectionHandler::ConnectionHandler(QObject* parent) :
QObject(parent)
{
}
+QByteArray Signet::ConnectionHandler::generateChallengeKey()
+{
+ return QUuid::createUuid().toString().toUtf8();
+}
+
+QByteArray Signet::ConnectionHandler::generateResponse(const QByteArray& key1, const QByteArray& key2, const QByteArray& secret)
+{
+ if (QCA::isSupported("sha256"))
+ {
+ QByteArray total;
+ total.append(key1);
+ total.append(key2);
+ total.append(secret);
+ QCA::Hash sha256("sha256");
+ return sha256.hash(total).toByteArray();
+ }
+ qFatal("SHA-256 is not supported");
+ return QByteArray();
+}
+
+Signet::ConnectionHandler::ChallengeError Signet::ConnectionHandler::challenge(QTcpSocket* socket, const QByteArray& secret)
+{
+ QByteArray clientKey;
+ QByteArray serverKey;
+ QByteArray clientResponse;
+ QByteArray serverResponse;
+ QByteArray expectedServerResponse;
+ Protocol::ChallengeMediator mediator(socket, Protocol::ChallengeMediator::Client);
+ mediator.init();
+ if (!mediator.getServerKey(&serverKey))
+ return SocketError;
+ clientKey = generateChallengeKey();
+ clientResponse = generateResponse(clientKey, serverKey, secret);
+ expectedServerResponse = generateResponse(serverKey, clientKey, secret);
+ mediator.clientResponse(clientKey, clientResponse);
+ if (!mediator.getServerResponse(&serverResponse))
+ return SocketError;
+ if (mediator.state() != Protocol::ChallengeMediator::Accepted)
+ return ClientFailed;
+ if (serverResponse != expectedServerResponse)
+ {
+ mediator.notifyServerFail();
+ return ServerFailed;
+ }
+ mediator.notifyServerAccept();
+ return NoError;
+}
+
+Signet::ConnectionHandler::ChallengeError Signet::ConnectionHandler::challenged(QTcpSocket* socket)
+{
+ QByteArray clientKey;
+ QByteArray serverKey;
+ QByteArray clientResponse;
+ QByteArray serverResponse;
+ QByteArray expectedClientResponse;
+ QByteArray secret = secretForHost(socket->peerAddress());
+ Protocol::ChallengeMediator mediator(socket, Protocol::ChallengeMediator::Server);
+ serverKey = generateChallengeKey();
+ mediator.serverKey(serverKey);
+ if (!mediator.getClientResponse(&clientKey, &clientResponse))
+ return SocketError;
+ expectedClientResponse = generateResponse(clientKey, serverKey, secret);
+ if (clientResponse != expectedClientResponse)
+ {
+ mediator.notifyClientFail();
+ return ClientFailed;
+ }
+ serverResponse = generateResponse(serverKey, clientKey, secret);
+ mediator.serverResponse(serverResponse);
+ if (!mediator.getClientAnswer())
+ return SocketError;
+ if (mediator.state() != Protocol::ChallengeMediator::Accepted)
+ return ServerFailed;
+ return NoError;
+}
+
+QByteArray Signet::ConnectionHandler::secretForHost(const QHostAddress& address) const
+{
+ Q_UNUSED(address)
+ return QByteArray();
+}
+
bool Signet::ConnectionHandler::addClient(Client* socket)
{
// TODO: Add the client
diff --git a/signet/ConnectionHandler.h b/signet/ConnectionHandler.h
index c845e6b5..9108a9a9 100644
--- a/signet/ConnectionHandler.h
+++ b/signet/ConnectionHandler.h
@@ -25,9 +25,12 @@
#include <QtCore/QMap>
#include <QtCore/QObject>
+// Forward declarations
+class QHostAddress;
+class QTcpSocket;
+
namespace Signet
{
-// Forward declarations
class Client;
class SIGNET_EXPORT ConnectionHandler : public QObject
@@ -35,8 +38,23 @@ class SIGNET_EXPORT ConnectionHandler : public QObject
Q_OBJECT
public:
+ enum ChallengeError
+ {
+ NoError,
+ ClientFailed,
+ ServerFailed,
+ SocketError
+ };
+
ConnectionHandler(QObject* parent);
+ static QByteArray generateChallengeKey();
+ static QByteArray generateResponse(const QByteArray& key1, const QByteArray& key2, const QByteArray& secret);
+ static ChallengeError challenge(QTcpSocket* socket, const QByteArray& secret);
+ ChallengeError challenged(QTcpSocket* socket);
+
+ virtual QByteArray secretForHost(const QHostAddress& address) const;
+
virtual QString type() const = 0;
virtual QString name() const = 0;
public slots:
@@ -48,7 +66,7 @@ class SIGNET_EXPORT ConnectionHandler : public QObject
protected slots:
void sendData(Client* client, const QByteArray& data);
private:
- QList<Client*> m_sockets;
+ QList<Client*> m_clients;
};
}
diff --git a/signet/Server.cpp b/signet/Server.cpp
index bd23faf5..422f2d45 100644
--- a/signet/Server.cpp
+++ b/signet/Server.cpp
@@ -62,6 +62,14 @@ void Signet::Server::hostFound()
void Signet::Server::hostConnected()
{
qDebug("Master server connected");
+ ChallengeError error = challenge(m_master, m_key);
+ if (error == NoError)
+ qDebug("Master server connected");
+ else if (error != SocketError)
+ {
+ qCritical("Challenge negotiation failed: %s", (error == ClientFailed) ? "Client" : "Server");
+ m_master->disconnectFromHost();
+ }
}
void Signet::Server::hostDisconnected()
@@ -96,7 +104,7 @@ void Signet::Server::loadConfiguration()
m_masterPort = group.readEntry("Port", -1);
if (m_masterPort < 0)
qFatal("Invalid port for the master server: %d", m_masterPort);
- m_key = group.readEntry("Key", "");
+ m_key = group.readEntry("Key", QByteArray());
}
else
qFatal("Configuration does not contain a \"Master Server\" group");
diff --git a/signet/Server.h b/signet/Server.h
index a8cb31ff..ee90455a 100644
--- a/signet/Server.h
+++ b/signet/Server.h
@@ -66,7 +66,7 @@ class SIGNET_EXPORT Server : public ConnectionHandler
QHostAddress m_masterHost;
int m_masterPort;
- QUuid m_key;
+ QByteArray m_key;
QMap<QString, Room*> m_rooms;
};
diff --git a/signet/protocol/ChallengeMediator.cpp b/signet/protocol/ChallengeMediator.cpp
new file mode 100644
index 00000000..c26b6ea4
--- /dev/null
+++ b/signet/protocol/ChallengeMediator.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header include
+#include "ChallengeMediator.h"
+
+// Protocol includes
+#include "PacketMaker.h"
+
+// Qt includes
+#include <QtCore/QBuffer>
+#include <QtNetwork/QTcpSocket>
+
+Signet::Protocol::ChallengeMediator::ChallengeMediator(QTcpSocket* socket, Side side) :
+ m_side(side),
+ m_state(Negotiating),
+ m_socket(socket)
+{
+}
+
+void Signet::Protocol::ChallengeMediator::init()
+{
+ Q_ASSERT(m_side == Client);
+ PacketMaker::challengePacket(m_socket);
+}
+
+void Signet::Protocol::ChallengeMediator::serverKey(const QByteArray& serverKey)
+{
+ Q_ASSERT(m_side == Server);
+ PacketMaker::wrap(m_socket, serverKey);
+}
+
+bool Signet::Protocol::ChallengeMediator::getServerKey(QByteArray* serverKey)
+{
+ Q_ASSERT(m_side == Client);
+ QBuffer buffer(serverKey);
+ Packet packet = PacketMaker::unwrap(m_socket);
+ if (!packet.isValid())
+ return false;
+ packet.dump(&buffer);
+ return true;
+}
+
+void Signet::Protocol::ChallengeMediator::clientResponse(const QByteArray& clientKey, const QByteArray& clientResponse)
+{
+ Q_ASSERT(m_side == Client);
+ PacketMaker::wrap(m_socket, clientKey);
+ PacketMaker::wrap(m_socket, clientResponse);
+}
+
+bool Signet::Protocol::ChallengeMediator::getClientResponse(QByteArray* clientKey, QByteArray* clientResponse)
+{
+ Q_ASSERT(m_side == Server);
+ QBuffer buffer(clientKey);
+ Packet packet = PacketMaker::unwrap(m_socket);
+ if (!packet.isValid())
+ return false;
+ packet.dump(&buffer);
+ buffer.setBuffer(clientResponse);
+ packet = PacketMaker::unwrap(m_socket);
+ if (!packet.isValid())
+ return false;
+ packet.dump(&buffer);
+ return true;
+}
+
+void Signet::Protocol::ChallengeMediator::serverResponse(const QByteArray& serverResponse)
+{
+ Q_ASSERT(m_side == Server);
+ PacketMaker::wrap(m_socket, serverResponse);
+}
+
+bool Signet::Protocol::ChallengeMediator::getServerResponse(QByteArray* serverResponse)
+{
+ Q_ASSERT(m_side == Client);
+ QBuffer buffer(serverResponse);
+ Packet packet = PacketMaker::unwrap(m_socket);
+ if (!packet.isValid())
+ return false;
+ if (packet.type() == Packet::Denial)
+ m_state = Rejected;
+ else
+ packet.dump(&buffer);
+ return true;
+}
+
+bool Signet::Protocol::ChallengeMediator::getClientAnswer()
+{
+ Q_ASSERT(m_side == Server);
+ Packet packet = PacketMaker::unwrap(m_socket);
+ if (!packet.isValid())
+ return false;
+ if (packet.type() == Packet::Acceptance)
+ m_state = Accepted;
+ else
+ m_state = Rejected;
+ return true;
+}
+
+Signet::Protocol::ChallengeMediator::State Signet::Protocol::ChallengeMediator::state() const
+{
+ return m_state;
+}
+
+void Signet::Protocol::ChallengeMediator::notifyServerFail()
+{
+ Q_ASSERT(m_side == Client);
+ PacketMaker::deny(m_socket);
+}
+
+void Signet::Protocol::ChallengeMediator::notifyServerAccept()
+{
+ Q_ASSERT(m_side == Client);
+ PacketMaker::accept(m_socket);
+}
+
+void Signet::Protocol::ChallengeMediator::notifyClientFail()
+{
+ Q_ASSERT(m_side == Server);
+ PacketMaker::deny(m_socket);
+}
diff --git a/signet/protocol/ChallengeMediator.h b/signet/protocol/ChallengeMediator.h
new file mode 100644
index 00000000..bc02245d
--- /dev/null
+++ b/signet/protocol/ChallengeMediator.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SIGNET_PROTOCOL_CHALLENGEMEDIATOR
+#define SIGNET_PROTOCOL_CHALLENGEMEDIATOR
+
+// Signet includes
+#include "../Global.h"
+
+// Forward declarations
+class QTcpSocket;
+
+namespace Signet
+{
+namespace Protocol
+{
+class SIGNET_EXPORT ChallengeMediator
+{
+ public:
+ enum Side
+ {
+ Client = 0,
+ Server = 1
+ };
+ enum State
+ {
+ Negotiating = 0,
+ Accepted = 1,
+ Rejected = 2
+ };
+
+ ChallengeMediator(QTcpSocket* socket, Side side);
+
+ void init();
+
+ void serverKey(const QByteArray& serverKey);
+ bool getServerKey(QByteArray* serverKey);
+
+ void clientResponse(const QByteArray& clientKey, const QByteArray& clientResponse);
+ bool getClientResponse(QByteArray* clientKey, QByteArray* clientResponse);
+
+ void serverResponse(const QByteArray& serverResponse);
+ bool getServerResponse(QByteArray* serverResponse);
+
+ bool getClientAnswer();
+
+ State state() const;
+
+ void notifyServerFail();
+ void notifyServerAccept();
+ void notifyClientFail();
+ private:
+ const Side m_side;
+ State m_state;
+ QTcpSocket* m_socket;
+};
+}
+}
+
+#endif
diff --git a/signet/protocol/Packet.cpp b/signet/protocol/Packet.cpp
new file mode 100644
index 00000000..34e6d125
--- /dev/null
+++ b/signet/protocol/Packet.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header include
+#include "Packet.h"
+
+// Qt include
+#include <QtCore/QIODevice>
+
+Signet::Protocol::Packet::Packet(const Type type) :
+ m_type(type)
+{
+}
+
+void Signet::Protocol::Packet::determineType()
+{
+}
+
+Signet::Protocol::Packet::Type Signet::Protocol::Packet::type() const
+{
+ return m_type;
+}
+
+bool Signet::Protocol::Packet::isValid() const
+{
+ return m_type == Invalid;
+}
+
+void Signet::Protocol::Packet::write(const QByteArray& data)
+{
+ if ((m_type == RawData) || (m_type == Invalid))
+ m_rawData.append(data);
+}
+
+void Signet::Protocol::Packet::dump(QIODevice* device) const
+{
+ device->write(m_rawData);
+}
diff --git a/signet/protocol/Packet.h b/signet/protocol/Packet.h
new file mode 100644
index 00000000..764ae26a
--- /dev/null
+++ b/signet/protocol/Packet.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SIGNET_PROTOCOL_PACKET
+#define SIGNET_PROTOCOL_PACKET
+
+// Signet includes
+#include "../Global.h"
+
+// Qt includes
+#include <QtCore/QByteArray>
+
+// Forward declarations
+class QIODevice;
+
+namespace Signet
+{
+namespace Protocol
+{
+class SIGNET_EXPORT Packet
+{
+ public:
+ enum Type
+ {
+ Invalid = -1,
+ RawData = 0,
+ Acceptance = 1,
+ Denial = 2,
+ Challenge = 3
+ };
+
+ Packet(const Type type = Invalid);
+
+ void determineType();
+
+ Type type() const;
+ bool isValid() const;
+
+ void write(const QByteArray& data);
+ void dump(QIODevice* device) const;
+ private:
+ Type m_type;
+ QByteArray m_rawData;
+};
+}
+}
+
+#endif
diff --git a/signet/protocol/PacketMaker.cpp b/signet/protocol/PacketMaker.cpp
new file mode 100644
index 00000000..f2a05d2b
--- /dev/null
+++ b/signet/protocol/PacketMaker.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header include
+#include "PacketMaker.h"
+
+void Signet::Protocol::PacketMaker::deny(QIODevice* device)
+{
+}
+
+void Signet::Protocol::PacketMaker::accept(QIODevice* device)
+{
+}
+
+void Signet::Protocol::PacketMaker::challengePacket(QIODevice* device)
+{
+}
+
+Signet::Protocol::Packet Signet::Protocol::PacketMaker::unwrap(QIODevice* device)
+{
+}
diff --git a/signet/protocol/PacketMaker.h b/signet/protocol/PacketMaker.h
new file mode 100644
index 00000000..877eef9b
--- /dev/null
+++ b/signet/protocol/PacketMaker.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SIGNET_PROTOCOL_PACKETMAKER
+#define SIGNET_PROTOCOL_PACKETMAKER
+
+// Protocol includes
+#include "Packet.h"
+
+// Signet includes
+#include "../Global.h"
+
+// Forward declarations
+#include <QtCore/QIODevice>
+
+namespace Signet
+{
+namespace Protocol
+{
+class SIGNET_EXPORT PacketMaker
+{
+ public:
+ static void deny(QIODevice* device);
+ static void accept(QIODevice* device);
+
+ static void challengePacket(QIODevice* device);
+
+ template<typename T> static void wrap(QIODevice* device, const T& data);
+
+ static Packet unwrap(QIODevice* device);
+};
+
+template<> inline void PacketMaker::wrap<QByteArray>(QIODevice* device, const QByteArray& data)
+{
+ Packet packet(Packet::RawData);
+ packet.write(data);
+ packet.dump(device);
+}
+
+}
+}
+
+#endif