1 use mio; |
1 use mio; |
2 |
2 |
3 use crate::{ |
3 use crate::{ |
4 server::{ |
4 server::{ |
|
5 client::HWClient, |
5 server::HWServer, |
6 server::HWServer, |
6 coretypes::ClientId, |
7 coretypes::ClientId, |
7 actions::{Action, Action::*} |
8 actions::{Action, Action::*} |
8 }, |
9 }, |
9 protocol::messages::{ |
10 protocol::messages::{ |
10 HWProtocolMessage, HWServerMessage::* |
11 HWProtocolMessage, HWServerMessage::* |
11 }, |
12 }, |
12 utils::is_name_illegal |
13 utils::is_name_illegal |
13 }; |
14 }; |
|
15 #[cfg(feature = "official-server")] |
|
16 use openssl::sha::sha1; |
|
17 use std::fmt::{Formatter, LowerHex}; |
|
18 |
|
19 #[derive(PartialEq)] |
|
20 struct Sha1Digest([u8; 20]); |
|
21 |
|
22 impl LowerHex for Sha1Digest { |
|
23 fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { |
|
24 for byte in &self.0 { |
|
25 write!(f, "{:02x}", byte)?; |
|
26 } |
|
27 Ok(()) |
|
28 } |
|
29 } |
|
30 |
|
31 #[cfg(feature = "official-server")] |
|
32 fn get_hash(client: &HWClient, salt1: &str, salt2: &str) -> Sha1Digest { |
|
33 let s = format!("{}{}{}{}{}", salt1, salt2, |
|
34 client.web_password, client.protocol_number, "!hedgewars"); |
|
35 Sha1Digest(sha1(s.as_bytes())) |
|
36 } |
14 |
37 |
15 pub fn handle(server: & mut HWServer, client_id: ClientId, message: HWProtocolMessage) { |
38 pub fn handle(server: & mut HWServer, client_id: ClientId, message: HWProtocolMessage) { |
16 match message { |
39 match message { |
17 HWProtocolMessage::Nick(nick) => { |
40 HWProtocolMessage::Nick(nick) => { |
18 let client = &mut server.clients[client_id]; |
41 let client = &mut server.clients[client_id]; |
21 unreachable!() |
44 unreachable!() |
22 } |
45 } |
23 else if !client.nick.is_empty() { |
46 else if !client.nick.is_empty() { |
24 vec![ProtocolError("Nickname already provided.".to_string())] |
47 vec![ProtocolError("Nickname already provided.".to_string())] |
25 } |
48 } |
26 else if is_name_illegal(&nick) { |
49 else if is_name_illegal(&nick) { |
27 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())] |
50 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())] |
28 } |
51 } |
29 else { |
52 else { |
30 client.nick = nick.clone(); |
53 client.nick = nick.clone(); |
31 vec![Nick(nick).send_self().action(), |
54 vec![Nick(nick).send_self().action(), |
48 CheckRegistered] |
71 CheckRegistered] |
49 }; |
72 }; |
50 server.react(client_id, actions); |
73 server.react(client_id, actions); |
51 } |
74 } |
52 #[cfg(feature = "official-server")] |
75 #[cfg(feature = "official-server")] |
|
76 HWProtocolMessage::Password(hash, salt) => { |
|
77 let c = &server.clients[client_id]; |
|
78 |
|
79 let client_hash = get_hash(c, &salt, &c.server_salt); |
|
80 let server_hash = get_hash(c, &c.server_salt, &salt); |
|
81 let actions = if client_hash == server_hash { |
|
82 vec![ServerAuth(format!("{:x}", server_hash)).send_self().action(), |
|
83 JoinLobby] |
|
84 } else { |
|
85 vec![ByeClient("Authentication failed".to_string())] |
|
86 }; |
|
87 server.react(client_id, actions); |
|
88 } |
|
89 #[cfg(feature = "official-server")] |
53 HWProtocolMessage::Checker(protocol, nick, password) => { |
90 HWProtocolMessage::Checker(protocol, nick, password) => { |
54 let c = &mut server.clients[client_id]; |
91 let c = &mut server.clients[client_id]; |
55 c.nick = nick; |
92 c.nick = nick; |
56 c.web_password = password; |
93 c.web_password = password; |
57 c.set_is_checker(true); |
94 c.set_is_checker(true); |