gameServer2/src/server/handlers/loggingin.rs
changeset 13800 0118b7412570
parent 13798 4664da990556
child 13805 0463a4221327
--- a/gameServer2/src/server/handlers/loggingin.rs	Thu Sep 06 23:12:32 2018 +0300
+++ b/gameServer2/src/server/handlers/loggingin.rs	Fri Sep 07 04:16:05 2018 +0300
@@ -2,6 +2,7 @@
 
 use crate::{
     server::{
+        client::HWClient,
         server::HWServer,
         coretypes::ClientId,
         actions::{Action, Action::*}
@@ -11,6 +12,28 @@
     },
     utils::is_name_illegal
 };
+#[cfg(feature = "official-server")]
+use openssl::sha::sha1;
+use std::fmt::{Formatter, LowerHex};
+
+#[derive(PartialEq)]
+struct Sha1Digest([u8; 20]);
+
+impl LowerHex for Sha1Digest {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
+        for byte in &self.0 {
+            write!(f, "{:02x}", byte)?;
+        }
+        Ok(())
+    }
+}
+
+#[cfg(feature = "official-server")]
+fn get_hash(client: &HWClient, salt1: &str, salt2: &str) -> Sha1Digest {
+    let s = format!("{}{}{}{}{}", salt1, salt2,
+                    client.web_password, client.protocol_number, "!hedgewars");
+    Sha1Digest(sha1(s.as_bytes()))
+}
 
 pub fn handle(server: & mut HWServer, client_id: ClientId, message: HWProtocolMessage) {
     match message {
@@ -23,7 +46,7 @@
             else if !client.nick.is_empty() {
                 vec![ProtocolError("Nickname already provided.".to_string())]
             }
-            else if     is_name_illegal(&nick) {
+            else if is_name_illegal(&nick) {
                 vec![ByeClient("Illegal nickname! Nicknames must be between 1-40 characters long, must not have a trailing or leading space and must not have any of these characters: $()*+?[]^{|}".to_string())]
             }
             else {
@@ -50,6 +73,20 @@
             server.react(client_id, actions);
         }
         #[cfg(feature = "official-server")]
+        HWProtocolMessage::Password(hash, salt) => {
+            let c = &server.clients[client_id];
+
+            let client_hash = get_hash(c, &salt, &c.server_salt);
+            let server_hash = get_hash(c, &c.server_salt, &salt);
+            let actions = if client_hash == server_hash {
+                vec![ServerAuth(format!("{:x}", server_hash)).send_self().action(),
+                     JoinLobby]
+            } else {
+                vec![ByeClient("Authentication failed".to_string())]
+            };
+            server.react(client_id, actions);
+        }
+        #[cfg(feature = "official-server")]
         HWProtocolMessage::Checker(protocol, nick, password) => {
             let c = &mut server.clients[client_id];
             c.nick = nick;