Copy authentication from the old frontend
authorunC0Rr
Thu, 30 May 2019 18:31:02 +0200
changeset 15099 fb7a9b0119d3
parent 15098 a2d09a597fbb
child 15100 424e3b132dd3
Copy authentication from the old frontend
qmlfrontend/net_session.cpp
qmlfrontend/net_session.h
--- a/qmlfrontend/net_session.cpp	Wed May 29 01:05:20 2019 +0200
+++ b/qmlfrontend/net_session.cpp	Thu May 30 18:31:02 2019 +0200
@@ -1,12 +1,15 @@
 #include "net_session.h"
 
+#include <QUuid>
+
 #include "players_model.h"
 #include "rooms_model.h"
 
 NetSession::NetSession(QObject *parent)
     : QObject(parent),
       m_playersModel(new PlayersListModel()),
-      m_roomsModel(new RoomsListModel()) {}
+      m_roomsModel(new RoomsListModel()),
+      m_sessionState(NotConnected) {}
 
 NetSession::~NetSession() { close(); }
 
@@ -33,14 +36,14 @@
 
 QString NetSession::nickname() const { return m_nickname; }
 
-QString NetSession::password() const { return m_password; }
-
 NetSession::SessionState NetSession::sessionState() const {
   return m_sessionState;
 }
 
 QString NetSession::room() const { return m_room; }
 
+QString NetSession::passwordHash() const { return m_passwordHash; }
+
 void NetSession::setUrl(const QUrl &url) {
   if (m_url == url) return;
 
@@ -55,11 +58,13 @@
   emit nicknameChanged(m_nickname);
 }
 
-void NetSession::setPassword(const QString &password) {
-  if (m_password == password) return;
+void NetSession::setPasswordHash(const QString &passwordHash) {
+  if (m_passwordHash == passwordHash) return;
 
-  m_password = password;
-  emit passwordChanged(m_password);
+  m_passwordHash = passwordHash;
+  emit passwordHashChanged(m_passwordHash);
+
+  if (m_sessionState == Authentication) sendPassword();
 }
 
 void NetSession::setRoom(const QString &room) {
@@ -174,7 +179,23 @@
 
 void NetSession::handleAddTeam(const QStringList &parameters) {}
 
-void NetSession::handleAskPassword(const QStringList &parameters) {}
+void NetSession::handleAskPassword(const QStringList &parameters) {
+  if (parameters.length() != 1 || parameters[0].length() < 16) {
+    qWarning("Bad ASKPASSWORD message");
+    return;
+  }
+
+  setSessionState(Authentication);
+
+  m_serverSalt = parameters[0];
+  m_clientSalt = QUuid::createUuid().toString();
+
+  if (m_passwordHash.isEmpty()) {
+    emit passwordAsked();
+  } else {
+    sendPassword();
+  }
+}
 
 void NetSession::handleBanList(const QStringList &parameters) {}
 
@@ -306,6 +327,37 @@
   m_socket->write(message.join('\n').toUtf8() + "\n\n");
 }
 
+void NetSession::sendPassword() {
+  /* When we got password hash, and server asked us for a password, perform
+   * mutual authentication: at this point we have salt chosen by server. Client
+   * sends client salt and hash of secret (password hash) salted with client
+   * salt, server salt, and static salt (predefined string + protocol number).
+   * Server should respond with hash of the same set in different order.
+   */
+
+  if (m_passwordHash.isEmpty() || m_serverSalt.isEmpty()) return;
+
+  QString hash =
+      QCryptographicHash::hash(m_clientSalt.toLatin1()
+                                   .append(m_serverSalt.toLatin1())
+                                   .append(m_passwordHash)
+                                   .append(QByteArray::number(cProtocolVersion))
+                                   .append("!hedgewars"),
+                               QCryptographicHash::Sha1)
+          .toHex();
+
+  m_serverHash =
+      QCryptographicHash::hash(m_serverSalt.toLatin1()
+                                   .append(m_clientSalt.toLatin1())
+                                   .append(m_passwordHash)
+                                   .append(QByteArray::number(cProtocolVersion))
+                                   .append("!hedgewars"),
+                               QCryptographicHash::Sha1)
+          .toHex();
+
+  send("PASSWORD", QStringList{hash, m_clientSalt});
+}
+
 void NetSession::setSessionState(NetSession::SessionState sessionState) {
   if (m_sessionState == sessionState) return;
 
--- a/qmlfrontend/net_session.h	Wed May 29 01:05:20 2019 +0200
+++ b/qmlfrontend/net_session.h	Thu May 30 18:31:02 2019 +0200
@@ -18,13 +18,13 @@
   Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
   Q_PROPERTY(QAbstractSocket::SocketState state READ state NOTIFY stateChanged)
   Q_PROPERTY(QString nickname READ nickname WRITE setNickname NOTIFY nicknameChanged)
-  Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged)
   Q_PROPERTY(SessionState sessionState READ sessionState NOTIFY sessionStateChanged)
   Q_PROPERTY(QString room READ room NOTIFY roomChanged)
+  Q_PROPERTY(QString passwordHash READ passwordHash WRITE setPasswordHash NOTIFY passwordHashChanged)
   // clang-format on
 
  public:
-  enum SessionState { NotConnected, Login, Lobby, Room, Game };
+  enum SessionState { NotConnected, Login, Authentication, Lobby, Room, Game };
   Q_ENUMS(SessionState)
 
   explicit NetSession(QObject *parent = nullptr);
@@ -34,9 +34,9 @@
   QAbstractSocket::SocketState state() const;
 
   QString nickname() const;
-  QString password() const;
   SessionState sessionState() const;
   QString room() const;
+  QString passwordHash() const;
 
  public slots:
   void open();
@@ -44,17 +44,18 @@
 
   void setUrl(const QUrl &url);
   void setNickname(const QString &nickname);
-  void setPassword(const QString &password);
+  void setPasswordHash(const QString &passwordHash);
 
  signals:
   void urlChanged(const QUrl url);
   void stateChanged(QAbstractSocket::SocketState state);
   void nicknameChanged(const QString &nickname);
-  void passwordChanged(const QString &password);
   void sessionStateChanged(SessionState sessionState);
   void warning(const QString &message);
   void error(const QString &message);
   void roomChanged(const QString &room);
+  void passwordHashChanged(const QString &passwordHash);
+  void passwordAsked();
 
  private slots:
   void onReadyRead();
@@ -102,6 +103,9 @@
   void send(const QString &message, const QString &param);
   void send(const QString &message, const QStringList &parameters);
   void send(const QStringList &message);
+
+  void sendPassword();
+
   void setSessionState(SessionState sessionState);
   void setRoom(const QString &room);
 
@@ -111,11 +115,14 @@
   QSharedPointer<PlayersListModel> m_playersModel;
   QSharedPointer<RoomsListModel> m_roomsModel;
   QString m_nickname;
-  QString m_password;
   QStringList m_buffer;
   SessionState m_sessionState;
   QString m_serverAuthHash;
   QString m_room;
+  QString m_serverSalt;
+  QString m_serverHash;
+  QString m_clientSalt;
+  QString m_passwordHash;
 
   Q_DISABLE_COPY(NetSession)
 };