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