14 use std::{ |
15 use std::{ |
15 fmt::{Formatter, LowerHex}, |
16 fmt::{Formatter, LowerHex}, |
16 num::NonZeroU16, |
17 num::NonZeroU16, |
17 }; |
18 }; |
18 |
19 |
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(protocol_number: u16, web_password: &str, salt1: &str, salt2: &str) -> Sha1Digest { |
|
33 let s = format!( |
|
34 "{}{}{}{}{}", |
|
35 salt1, salt2, web_password, protocol_number, "!hedgewars" |
|
36 ); |
|
37 Sha1Digest(sha1(s.as_bytes())) |
|
38 } |
|
39 |
|
40 pub enum LoginResult { |
20 pub enum LoginResult { |
41 Unchanged, |
21 Unchanged, |
42 Complete, |
22 Complete, |
43 Exit, |
23 Exit, |
|
24 } |
|
25 |
|
26 fn completion_result(client: &HWAnteClient, response: &mut super::Response) -> LoginResult { |
|
27 #[cfg(feature = "official-server")] |
|
28 { |
|
29 response.add(AskPassword(client.server_salt.clone()).send_self()); |
|
30 LoginResult::Unchanged |
|
31 } |
|
32 |
|
33 #[cfg(not(feature = "official-server"))] |
|
34 { |
|
35 LoginResult::Complete |
|
36 } |
44 } |
37 } |
45 |
38 |
46 pub fn handle( |
39 pub fn handle( |
47 anteroom: &mut HWAnteroom, |
40 anteroom: &mut HWAnteroom, |
48 client_id: ClientId, |
41 client_id: ClientId, |
85 } else { |
78 } else { |
86 client.protocol_number = NonZeroU16::new(proto); |
79 client.protocol_number = NonZeroU16::new(proto); |
87 response.add(Proto(proto).send_self()); |
80 response.add(Proto(proto).send_self()); |
88 |
81 |
89 if client.nick.is_some() { |
82 if client.nick.is_some() { |
90 LoginResult::Complete |
83 completion_result(&client, response) |
91 } else { |
84 } else { |
92 LoginResult::Unchanged |
85 LoginResult::Unchanged |
93 } |
86 } |
94 } |
87 } |
95 } |
88 } |
96 #[cfg(feature = "official-server")] |
89 #[cfg(feature = "official-server")] |
97 HWProtocolMessage::Password(hash, salt) => { |
90 HWProtocolMessage::Password(hash, salt) => { |
98 let client = &anteroom.clients[client_id]; |
91 let client = &anteroom.clients[client_id]; |
99 |
92 |
100 if let (Some(protocol), Some(password)) = |
93 if let (Some(nick), Some(protocol)) = (client.nick.as_ref(), client.protocol_number) { |
101 (client.protocol_number, client.web_password.as_ref()) |
94 response.request_io(super::IoTask::GetAccount { |
102 { |
95 nick: nick.clone(), |
103 let client_hash = get_hash(protocol.get(), &password, &salt, &client.server_salt); |
96 protocol: protocol.get(), |
104 let server_hash = get_hash(protocol.get(), &password, &client.server_salt, &salt); |
97 server_salt: client.server_salt.clone(), |
105 if client_hash == server_hash { |
98 client_salt: salt, |
106 response.add(ServerAuth(format!("{:x}", server_hash)).send_self()); |
99 password_hash: hash, |
107 LoginResult::Complete |
100 }); |
108 } else { |
101 }; |
109 response.add(Bye("No protocol provided.".to_string()).send_self()); |
102 |
110 LoginResult::Unchanged |
103 LoginResult::Unchanged |
111 } |
|
112 } else { |
|
113 response.add(Bye("Authentication failed.".to_string()).send_self()); |
|
114 LoginResult::Exit |
|
115 } |
|
116 } |
104 } |
117 #[cfg(feature = "official-server")] |
105 #[cfg(feature = "official-server")] |
118 HWProtocolMessage::Checker(protocol, nick, password) => { |
106 HWProtocolMessage::Checker(protocol, nick, password) => { |
119 let client = &mut anteroom.clients[client_id]; |
107 let client = &mut anteroom.clients[client_id]; |
120 client.protocol_number = NonZeroU16::new(protocol); |
108 client.protocol_number = NonZeroU16::new(protocol); |
121 client.nick = Some(nick); |
109 client.nick = Some(nick); |
122 client.web_password = Some(password); |
|
123 //client.set_is_checker(true); |
110 //client.set_is_checker(true); |
124 LoginResult::Complete |
111 LoginResult::Complete |
125 } |
112 } |
126 _ => { |
113 _ => { |
127 warn!("Incorrect command in logging-in state"); |
114 warn!("Incorrect command in logging-in state"); |