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