1 #include "net_session.h" |
1 #include "net_session.h" |
|
2 |
|
3 #include <QUuid> |
2 |
4 |
3 #include "players_model.h" |
5 #include "players_model.h" |
4 #include "rooms_model.h" |
6 #include "rooms_model.h" |
5 |
7 |
6 NetSession::NetSession(QObject *parent) |
8 NetSession::NetSession(QObject *parent) |
7 : QObject(parent), |
9 : QObject(parent), |
8 m_playersModel(new PlayersListModel()), |
10 m_playersModel(new PlayersListModel()), |
9 m_roomsModel(new RoomsListModel()) {} |
11 m_roomsModel(new RoomsListModel()), |
|
12 m_sessionState(NotConnected) {} |
10 |
13 |
11 NetSession::~NetSession() { close(); } |
14 NetSession::~NetSession() { close(); } |
12 |
15 |
13 QUrl NetSession::url() const { return m_url; } |
16 QUrl NetSession::url() const { return m_url; } |
14 |
17 |
31 static_cast<quint16>(m_url.port(46631))); |
34 static_cast<quint16>(m_url.port(46631))); |
32 } |
35 } |
33 |
36 |
34 QString NetSession::nickname() const { return m_nickname; } |
37 QString NetSession::nickname() const { return m_nickname; } |
35 |
38 |
36 QString NetSession::password() const { return m_password; } |
|
37 |
|
38 NetSession::SessionState NetSession::sessionState() const { |
39 NetSession::SessionState NetSession::sessionState() const { |
39 return m_sessionState; |
40 return m_sessionState; |
40 } |
41 } |
41 |
42 |
42 QString NetSession::room() const { return m_room; } |
43 QString NetSession::room() const { return m_room; } |
43 |
44 |
|
45 QString NetSession::passwordHash() const { return m_passwordHash; } |
|
46 |
44 void NetSession::setUrl(const QUrl &url) { |
47 void NetSession::setUrl(const QUrl &url) { |
45 if (m_url == url) return; |
48 if (m_url == url) return; |
46 |
49 |
47 m_url = url; |
50 m_url = url; |
48 emit urlChanged(m_url); |
51 emit urlChanged(m_url); |
53 |
56 |
54 m_nickname = nickname; |
57 m_nickname = nickname; |
55 emit nicknameChanged(m_nickname); |
58 emit nicknameChanged(m_nickname); |
56 } |
59 } |
57 |
60 |
58 void NetSession::setPassword(const QString &password) { |
61 void NetSession::setPasswordHash(const QString &passwordHash) { |
59 if (m_password == password) return; |
62 if (m_passwordHash == passwordHash) return; |
60 |
63 |
61 m_password = password; |
64 m_passwordHash = passwordHash; |
62 emit passwordChanged(m_password); |
65 emit passwordHashChanged(m_passwordHash); |
|
66 |
|
67 if (m_sessionState == Authentication) sendPassword(); |
63 } |
68 } |
64 |
69 |
65 void NetSession::setRoom(const QString &room) { |
70 void NetSession::setRoom(const QString &room) { |
66 if (m_room == room) return; |
71 if (m_room == room) return; |
67 |
72 |
172 qWarning() << "Command is not recognized"; |
177 qWarning() << "Command is not recognized"; |
173 } |
178 } |
174 |
179 |
175 void NetSession::handleAddTeam(const QStringList ¶meters) {} |
180 void NetSession::handleAddTeam(const QStringList ¶meters) {} |
176 |
181 |
177 void NetSession::handleAskPassword(const QStringList ¶meters) {} |
182 void NetSession::handleAskPassword(const QStringList ¶meters) { |
|
183 if (parameters.length() != 1 || parameters[0].length() < 16) { |
|
184 qWarning("Bad ASKPASSWORD message"); |
|
185 return; |
|
186 } |
|
187 |
|
188 setSessionState(Authentication); |
|
189 |
|
190 m_serverSalt = parameters[0]; |
|
191 m_clientSalt = QUuid::createUuid().toString(); |
|
192 |
|
193 if (m_passwordHash.isEmpty()) { |
|
194 emit passwordAsked(); |
|
195 } else { |
|
196 sendPassword(); |
|
197 } |
|
198 } |
178 |
199 |
179 void NetSession::handleBanList(const QStringList ¶meters) {} |
200 void NetSession::handleBanList(const QStringList ¶meters) {} |
180 |
201 |
181 void NetSession::handleCfg(const QStringList ¶meters) {} |
202 void NetSession::handleCfg(const QStringList ¶meters) {} |
182 |
203 |
304 qDebug() << "[CLIENT]" << message; |
325 qDebug() << "[CLIENT]" << message; |
305 |
326 |
306 m_socket->write(message.join('\n').toUtf8() + "\n\n"); |
327 m_socket->write(message.join('\n').toUtf8() + "\n\n"); |
307 } |
328 } |
308 |
329 |
|
330 void NetSession::sendPassword() { |
|
331 /* When we got password hash, and server asked us for a password, perform |
|
332 * mutual authentication: at this point we have salt chosen by server. Client |
|
333 * sends client salt and hash of secret (password hash) salted with client |
|
334 * salt, server salt, and static salt (predefined string + protocol number). |
|
335 * Server should respond with hash of the same set in different order. |
|
336 */ |
|
337 |
|
338 if (m_passwordHash.isEmpty() || m_serverSalt.isEmpty()) return; |
|
339 |
|
340 QString hash = |
|
341 QCryptographicHash::hash(m_clientSalt.toLatin1() |
|
342 .append(m_serverSalt.toLatin1()) |
|
343 .append(m_passwordHash) |
|
344 .append(QByteArray::number(cProtocolVersion)) |
|
345 .append("!hedgewars"), |
|
346 QCryptographicHash::Sha1) |
|
347 .toHex(); |
|
348 |
|
349 m_serverHash = |
|
350 QCryptographicHash::hash(m_serverSalt.toLatin1() |
|
351 .append(m_clientSalt.toLatin1()) |
|
352 .append(m_passwordHash) |
|
353 .append(QByteArray::number(cProtocolVersion)) |
|
354 .append("!hedgewars"), |
|
355 QCryptographicHash::Sha1) |
|
356 .toHex(); |
|
357 |
|
358 send("PASSWORD", QStringList{hash, m_clientSalt}); |
|
359 } |
|
360 |
309 void NetSession::setSessionState(NetSession::SessionState sessionState) { |
361 void NetSession::setSessionState(NetSession::SessionState sessionState) { |
310 if (m_sessionState == sessionState) return; |
362 if (m_sessionState == sessionState) return; |
311 |
363 |
312 m_sessionState = sessionState; |
364 m_sessionState = sessionState; |
313 |
365 |