QTfrontend/net/newnetclient.cpp
changeset 10074 66cab76eb56f
parent 10015 4feced261c68
child 10076 b235e520ea21
equal deleted inserted replaced
10073:865a4089278d 10074:66cab76eb56f
    19 
    19 
    20 #include <QDebug>
    20 #include <QDebug>
    21 #include <QInputDialog>
    21 #include <QInputDialog>
    22 #include <QCryptographicHash>
    22 #include <QCryptographicHash>
    23 #include <QSortFilterProxyModel>
    23 #include <QSortFilterProxyModel>
       
    24 #include <QUuid>
    24 
    25 
    25 #include "hwconsts.h"
    26 #include "hwconsts.h"
    26 #include "newnetclient.h"
    27 #include "newnetclient.h"
    27 #include "proto.h"
    28 #include "proto.h"
    28 #include "game.h"
    29 #include "game.h"
    34 char delimeter='\n';
    35 char delimeter='\n';
    35 
    36 
    36 HWNewNet::HWNewNet() :
    37 HWNewNet::HWNewNet() :
    37     isChief(false),
    38     isChief(false),
    38     m_game_connected(false),
    39     m_game_connected(false),
    39     loginStep(0),
       
    40     netClientState(Disconnected)
    40     netClientState(Disconnected)
    41 {
    41 {
    42     m_roomsListModel = new RoomsListModel(this);
    42     m_roomsListModel = new RoomsListModel(this);
    43 
    43 
    44     m_playersModel = new PlayersListModel(this);
    44     m_playersModel = new PlayersListModel(this);
   236     }
   236     }
   237 }
   237 }
   238 
   238 
   239 void HWNewNet::SendPasswordHash(const QString & hash)
   239 void HWNewNet::SendPasswordHash(const QString & hash)
   240 {
   240 {
   241     RawSendNet(QString("PASSWORD%1%2").arg(delimeter).arg(hash));
   241     // don't send it immediately, only store and check if server asked us for a password
       
   242     m_passwordHash = hash;
       
   243 
       
   244     maybeSendPassword();
   242 }
   245 }
   243 
   246 
   244 void HWNewNet::ParseCmd(const QStringList & lst)
   247 void HWNewNet::ParseCmd(const QStringList & lst)
   245 {
   248 {
   246     qDebug() << "Server: " << lst;
   249     qDebug() << "Server: " << lst;
   295         RawSendNet(QString("NICK%1%2").arg(delimeter).arg(mynick));
   298         RawSendNet(QString("NICK%1%2").arg(delimeter).arg(mynick));
   296         RawSendNet(QString("PROTO%1%2").arg(delimeter).arg(*cProtoVer));
   299         RawSendNet(QString("PROTO%1%2").arg(delimeter).arg(*cProtoVer));
   297         netClientState = Connected;
   300         netClientState = Connected;
   298         m_game_connected = true;
   301         m_game_connected = true;
   299         emit adminAccess(false);
   302         emit adminAccess(false);
       
   303         return;
       
   304     }
       
   305 
       
   306     if (lst[0] == "SERVER_AUTH")
       
   307     {
       
   308         if(lst.size() < 2)
       
   309         {
       
   310             qWarning("Net: Malformed SERVER_AUTH message");
       
   311             return;
       
   312         }
       
   313 
       
   314         if(lst[2] != m_serverHash)
       
   315         {
       
   316             Error("Server authentication error");
       
   317             Disconnect();
       
   318         } else
       
   319         {
       
   320             // empty m_serverHash variable means no authentication was performed
       
   321             // or server passed authentication
       
   322             m_serverHash.clear();
       
   323         }
       
   324 
   300         return;
   325         return;
   301     }
   326     }
   302 
   327 
   303     if (lst[0] == "PING")
   328     if (lst[0] == "PING")
   304     {
   329     {
   513 
   538 
   514         for(int i = 1; i < lst.size(); ++i)
   539         for(int i = 1; i < lst.size(); ++i)
   515         {
   540         {
   516             if (lst[i] == mynick)
   541             if (lst[i] == mynick)
   517             {
   542             {
       
   543                 // check if server is authenticated or no authentication was performed at all
       
   544                 if(!m_serverHash.isEmpty())
       
   545                 {
       
   546                     Error(tr("Server authentication error"));
       
   547 
       
   548                     Disconnect();
       
   549                 }
       
   550 
   518                 netClientState = InLobby;
   551                 netClientState = InLobby;
   519                 RawSendNet(QString("LIST"));
   552                 RawSendNet(QString("LIST"));
   520                 emit connected();
   553                 emit connected();
   521             }
   554             }
   522 
   555 
   576         return;
   609         return;
   577     }
   610     }
   578 
   611 
   579     if (lst[0] == "ASKPASSWORD")
   612     if (lst[0] == "ASKPASSWORD")
   580     {
   613     {
       
   614         // server should send us salt of at least 16 characters
       
   615 
       
   616         if(lst.size() < 2 || lst[1].size() < 16)
       
   617         {
       
   618             qWarning("Net: Bad ASKPASSWORD message");
       
   619             return;
       
   620         }
       
   621 
   581         emit NickRegistered(mynick);
   622         emit NickRegistered(mynick);
   582         m_nick_registered = true;
   623         m_nick_registered = true;
       
   624 
       
   625         // store server salt
       
   626         // when this variable is set, it is assumed that server asked us for a password
       
   627         m_serverSalt = lst[1];
       
   628         m_clientSalt = QUuid::createUuid().toString();
       
   629 
       
   630         maybeSendPassword();
       
   631 
   583         return;
   632         return;
   584     }
   633     }
   585 
   634 
   586     if (lst[0] == "NOTICE")
   635     if (lst[0] == "NOTICE")
   587     {
   636     {
  1081 void HWNewNet::roomPasswordEntered(const QString &password)
  1130 void HWNewNet::roomPasswordEntered(const QString &password)
  1082 {
  1131 {
  1083     if(!myroom.isEmpty())
  1132     if(!myroom.isEmpty())
  1084         JoinRoom(myroom, password);
  1133         JoinRoom(myroom, password);
  1085 }
  1134 }
       
  1135 
       
  1136 void HWNewNet::maybeSendPassword()
       
  1137 {
       
  1138 /* When we got password hash, and server asked us for a password, perform mutual authentication:
       
  1139  * at this point we have salt chosen by server
       
  1140  * client sends client salt and hash of secret (password hash) salted with client salt, server salt,
       
  1141  * and static salt (predefined string + protocol number)
       
  1142  * server should respond with hash of the same set in different order.
       
  1143  */
       
  1144 
       
  1145     if(m_passwordHash.isEmpty() || m_serverSalt.isEmpty())
       
  1146         return;
       
  1147 
       
  1148     QString hash;
       
  1149 
       
  1150     hash = QCryptographicHash::hash(
       
  1151                 m_clientSalt.toAscii()
       
  1152                 .append(m_serverSalt.toAscii())
       
  1153                 .append(m_passwordHash)
       
  1154                 .append(cProtoVer->toAscii())
       
  1155                 .append("!hedgewars")
       
  1156                 , QCryptographicHash::Sha1);
       
  1157 
       
  1158     m_serverHash = QCryptographicHash::hash(
       
  1159                 m_serverSalt.toAscii()
       
  1160                 .append(m_clientSalt.toAscii())
       
  1161                 .append(m_passwordHash)
       
  1162                 .append(cProtoVer->toAscii())
       
  1163                 .append("!hedgewars")
       
  1164                 , QCryptographicHash::Sha1);
       
  1165 
       
  1166     RawSendNet(QString("PASSWORD%1%2%1%3").arg(delimeter).arg(hash).arg(m_clientSalt));
       
  1167 }