12147
|
1 |
use mio;
|
|
2 |
|
13666
|
3 |
use crate::{
|
|
4 |
server::{
|
13800
|
5 |
client::HWClient,
|
13666
|
6 |
server::HWServer,
|
|
7 |
coretypes::ClientId,
|
|
8 |
actions::{Action, Action::*}
|
|
9 |
},
|
|
10 |
protocol::messages::{
|
|
11 |
HWProtocolMessage, HWServerMessage::*
|
|
12 |
},
|
|
13 |
utils::is_name_illegal
|
13419
|
14 |
};
|
13800
|
15 |
#[cfg(feature = "official-server")]
|
|
16 |
use openssl::sha::sha1;
|
|
17 |
use std::fmt::{Formatter, LowerHex};
|
13805
|
18 |
use log::*;
|
13800
|
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 |
}
|
12147
|
38 |
|
13419
|
39 |
pub fn handle(server: & mut HWServer, client_id: ClientId, message: HWProtocolMessage) {
|
12147
|
40 |
match message {
|
13416
|
41 |
HWProtocolMessage::Nick(nick) => {
|
13666
|
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())]
|
13416
|
49 |
}
|
13800
|
50 |
else if is_name_illegal(&nick) {
|
13666
|
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 |
|
13419
|
59 |
server.react(client_id, actions);
|
13798
|
60 |
}
|
12147
|
61 |
HWProtocolMessage::Proto(proto) => {
|
13666
|
62 |
let client = &mut server.clients[client_id];
|
|
63 |
let actions = if client.protocol_number != 0 {
|
|
64 |
vec![ProtocolError("Protocol already known.".to_string())]
|
13416
|
65 |
}
|
13666
|
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 |
};
|
13419
|
74 |
server.react(client_id, actions);
|
13798
|
75 |
}
|
|
76 |
#[cfg(feature = "official-server")]
|
13800
|
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")]
|
13798
|
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 |
}
|
12147
|
97 |
_ => warn!("Incorrect command in logging-in state"),
|
|
98 |
}
|
|
99 |
}
|