--- a/QTfrontend/net/newnetclient.cpp Sun Jan 26 00:09:50 2014 +0400
+++ b/QTfrontend/net/newnetclient.cpp Sun Jan 26 02:17:04 2014 +0400
@@ -239,7 +239,7 @@
void HWNewNet::SendPasswordHash(const QString & hash)
{
// don't send it immediately, only store and check if server asked us for a password
- m_passwordHash = hash;
+ m_passwordHash = hash.toAscii();
maybeSendPassword();
}
@@ -311,7 +311,7 @@
return;
}
- if(lst[2] != m_serverHash)
+ if(lst[1] != m_serverHash)
{
Error("Server authentication error");
Disconnect();
@@ -1145,15 +1145,13 @@
if(m_passwordHash.isEmpty() || m_serverSalt.isEmpty())
return;
- QString hash;
-
- hash = QCryptographicHash::hash(
+ QString hash = QCryptographicHash::hash(
m_clientSalt.toAscii()
.append(m_serverSalt.toAscii())
.append(m_passwordHash)
.append(cProtoVer->toAscii())
.append("!hedgewars")
- , QCryptographicHash::Sha1);
+ , QCryptographicHash::Sha1).toHex();
m_serverHash = QCryptographicHash::hash(
m_serverSalt.toAscii()
@@ -1161,7 +1159,7 @@
.append(m_passwordHash)
.append(cProtoVer->toAscii())
.append("!hedgewars")
- , QCryptographicHash::Sha1);
+ , QCryptographicHash::Sha1).toHex();
RawSendNet(QString("PASSWORD%1%2%1%3").arg(delimeter).arg(hash).arg(m_clientSalt));
}
--- a/gameServer/Actions.hs Sun Jan 26 00:09:50 2014 +0400
+++ b/gameServer/Actions.hs Sun Jan 26 02:17:04 2014 +0400
@@ -466,9 +466,9 @@
else
[ByeClient $ loc "Authentication failed"]
playerLogin p a contr = do
- chan <- client's sendChan
+ cl <- client's id
mapM_ processAction [
- AnswerClients [chan] ["ASKPASSWORD"]
+ AnswerClients [sendChan cl] $ ("ASKPASSWORD") : if clientProto cl < 48 then [] else [serverSalt cl]
, ModifyClient (\c -> c{webPassword = p, isAdministrator = a, isContributor = contr})
]
--- a/gameServer/Consts.hs Sun Jan 26 00:09:50 2014 +0400
+++ b/gameServer/Consts.hs Sun Jan 26 02:17:04 2014 +0400
@@ -4,4 +4,4 @@
import qualified Data.ByteString.Char8 as B
serverVersion :: B.ByteString
-serverVersion = "2"
+serverVersion = "3"
--- a/gameServer/CoreTypes.hs Sun Jan 26 00:09:50 2014 +0400
+++ b/gameServer/CoreTypes.hs Sun Jan 26 02:17:04 2014 +0400
@@ -98,6 +98,7 @@
connectTime :: UTCTime,
nick :: B.ByteString,
webPassword :: B.ByteString,
+ serverSalt :: B.ByteString,
logonPassed :: Bool,
isVisible :: Bool,
clientProto :: !Word16,
--- a/gameServer/HWProtoNEState.hs Sun Jan 26 00:09:50 2014 +0400
+++ b/gameServer/HWProtoNEState.hs Sun Jan 26 02:17:04 2014 +0400
@@ -2,7 +2,9 @@
module HWProtoNEState where
import Control.Monad.Reader
+import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Char8 as B
+import Data.Digest.Pure.SHA
--------------------------------------
import CoreTypes
import Actions
@@ -42,12 +44,29 @@
(ci, irnc) <- ask
let cl = irnc `client` ci
- if passwd == webPassword cl then
+ if clientProto cl < 48 && passwd == webPassword cl then
return $ JoinLobby : [AnswerClients [sendChan cl] ["ADMIN_ACCESS"] | isAdministrator cl]
else
return [ByeClient "Authentication failed"]
+handleCmd_NotEntered ["PASSWORD", passwd, clientSalt] = do
+ (ci, irnc) <- ask
+ let cl = irnc `client` ci
+
+ let clientHash = h [clientSalt, serverSalt cl, webPassword cl, showB $ clientProto cl, "!hedgewars"]
+ let serverHash = h [serverSalt cl, clientSalt, webPassword cl, showB $ clientProto cl, "!hedgewars"]
+
+ if passwd == clientHash then
+ return $
+ AnswerClients [sendChan cl] ["SERVER_AUTH", serverHash]
+ : JoinLobby
+ : [AnswerClients [sendChan cl] ["ADMIN_ACCESS"] | isAdministrator cl]
+ else
+ return [ByeClient "Authentication failed"]
+ where
+ h = B.pack . showDigest . sha1 . BL.fromChunks
+
#if defined(OFFICIAL_SERVER)
handleCmd_NotEntered ["CHECKER", protoNum, newNick, password] = do
(ci, irnc) <- ask
--- a/gameServer/NetRoutines.hs Sun Jan 26 00:09:50 2014 +0400
+++ b/gameServer/NetRoutines.hs Sun Jan 26 02:17:04 2014 +0400
@@ -6,13 +6,20 @@
import Data.Time
import Control.Monad
import Data.Unique
+import qualified Codec.Binary.Base64 as Base64
+import qualified Data.ByteString as BW
+import qualified Data.ByteString.Char8 as B
+import qualified Control.Exception as E
+import System.Entropy
-----------------------------
import CoreTypes
import Utils
-import RoomsAndClients
+
acceptLoop :: Socket -> Chan CoreMessage -> IO ()
-acceptLoop servSock chan = forever $
+acceptLoop servSock chan = E.bracket openHandle closeHandle f
+ where
+ f ch = forever $
do
(sock, sockAddr) <- Network.Socket.accept servSock
@@ -23,6 +30,7 @@
sendChan' <- newChan
uid <- newUnique
+ salt <- liftM (B.pack . Base64.encode . BW.unpack) $ hGetEntropy ch 16
let newClient =
(ClientInfo
@@ -33,6 +41,7 @@
currentTime
""
""
+ salt
False
False
0
--- a/gameServer/hedgewars-server.cabal Sun Jan 26 00:09:50 2014 +0400
+++ b/gameServer/hedgewars-server.cabal Sun Jan 26 02:17:04 2014 +0400
@@ -28,6 +28,8 @@
hslogger,
process,
deepseq,
- utf8-string
+ utf8-string,
+ SHA,
+ entropy
ghc-options: -O2