# HG changeset patch # User alfadur # Date 1576786438 -10800 # Node ID abd5eb80716662e7b71ac9deab6189837443c914 # Parent b907b9071ec596050539e4c7179c519185dbd016 add ip ban check diff -r b907b9071ec5 -r abd5eb807166 rust/hedgewars-server/Cargo.toml --- a/rust/hedgewars-server/Cargo.toml Tue Dec 17 18:54:17 2019 +0300 +++ b/rust/hedgewars-server/Cargo.toml Thu Dec 19 23:13:58 2019 +0300 @@ -12,6 +12,7 @@ [dependencies] getopts = "0.2.18" rand = "0.6" +chrono = "0.4" mio = "0.6" mio-extras = "2.0.5" slab = "0.4" diff -r b907b9071ec5 -r abd5eb807166 rust/hedgewars-server/src/core/server.rs --- a/rust/hedgewars-server/src/core/server.rs Tue Dec 17 18:54:17 2019 +0300 +++ b/rust/hedgewars-server/src/core/server.rs Thu Dec 19 23:13:58 2019 +0300 @@ -7,12 +7,11 @@ use crate::{protocol::messages::HwProtocolMessage::Greeting, utils}; use bitflags::*; +use chrono::{offset, DateTime}; use log::*; -use slab; +use slab::Slab; use std::{borrow::BorrowMut, collections::HashSet, iter, mem::replace, num::NonZeroU16}; -type Slab = slab::Slab; - #[derive(Debug)] pub enum CreateRoomError { InvalidName, @@ -88,14 +87,58 @@ pub is_contributor: bool, } +struct Ipv4AddrRange { + min: [u8; 4], + max: [u8; 4], +} + +impl Ipv4AddrRange { + fn contains(&self, addr: [u8; 4]) -> bool { + (0..4).all(|i| self.min[i] <= addr[i] && addr[i] <= self.max[i]) + } +} + +struct BanCollection { + ban_ips: Vec, + ban_timeouts: Vec>, + ban_reasons: Vec, +} + +impl BanCollection { + fn new() -> Self { + Self { + ban_ips: vec![], + ban_timeouts: vec![], + ban_reasons: vec![], + } + } + + fn find(&self, addr: [u8; 4]) -> Option { + let time = offset::Utc::now(); + self.ban_ips + .iter() + .enumerate() + .find(|(i, r)| r.contains(addr) && time < self.ban_timeouts[*i]) + .map(|(i, _)| self.ban_reasons[i].clone()) + } +} + pub struct HwAnteroom { pub clients: IndexSlab, + bans: BanCollection, } impl HwAnteroom { pub fn new(clients_limit: usize) -> Self { let clients = IndexSlab::with_capacity(clients_limit); - HwAnteroom { clients } + HwAnteroom { + clients, + bans: BanCollection::new(), + } + } + + pub fn find_ip_ban(&self, addr: [u8; 4]) -> Option { + self.bans.find(addr) } pub fn add_client(&mut self, client_id: ClientId, salt: String, is_local_admin: bool) { diff -r b907b9071ec5 -r abd5eb807166 rust/hedgewars-server/src/handlers.rs --- a/rust/hedgewars-server/src/handlers.rs Tue Dec 17 18:54:17 2019 +0300 +++ b/rust/hedgewars-server/src/handlers.rs Thu Dec 19 23:13:58 2019 +0300 @@ -354,16 +354,25 @@ server: &mut HwServer, client_id: ClientId, response: &mut Response, + addr: [u8; 4], is_local: bool, ) { - let mut salt = [0u8; 18]; - thread_rng().fill_bytes(&mut salt); + let ban_reason = Some(addr) + .filter(|_| !is_local) + .and_then(|a| server.anteroom.find_ip_ban(a)); + if let Some(reason) = ban_reason { + response.add(HwServerMessage::Bye(reason).send_self()); + response.remove_client(client_id); + } else { + let mut salt = [0u8; 18]; + thread_rng().fill_bytes(&mut salt); - server - .anteroom - .add_client(client_id, encode(&salt), is_local); + server + .anteroom + .add_client(client_id, encode(&salt), is_local); - response.add(HwServerMessage::Connected(utils::SERVER_VERSION).send_self()); + response.add(HwServerMessage::Connected(utils::SERVER_VERSION).send_self()); + } } pub fn handle_client_loss(server: &mut HwServer, client_id: ClientId, response: &mut Response) { diff -r b907b9071ec5 -r abd5eb807166 rust/hedgewars-server/src/server/database.rs --- a/rust/hedgewars-server/src/server/database.rs Tue Dec 17 18:54:17 2019 +0300 +++ b/rust/hedgewars-server/src/server/database.rs Thu Dec 19 23:13:58 2019 +0300 @@ -7,8 +7,7 @@ const CHECK_ACCOUNT_EXISTS_QUERY: &str = r"SELECT 1 FROM users WHERE users.name = :username LIMIT 1"; -const GET_ACCOUNT_QUERY: &str = - r"SELECT CASE WHEN users.status = 1 THEN users.pass ELSE '' END, +const GET_ACCOUNT_QUERY: &str = r"SELECT CASE WHEN users.status = 1 THEN users.pass ELSE '' END, (SELECT COUNT(users_roles.rid) FROM users_roles WHERE users.uid = users_roles.uid AND users_roles.rid = 3), (SELECT COUNT(users_roles.rid) FROM users_roles WHERE users.uid = users_roles.uid AND users_roles.rid = 13) FROM users WHERE users.name = :username"; diff -r b907b9071ec5 -r abd5eb807166 rust/hedgewars-server/src/server/network.rs --- a/rust/hedgewars-server/src/server/network.rs Tue Dec 17 18:54:17 2019 +0300 +++ b/rust/hedgewars-server/src/server/network.rs Thu Dec 19 23:13:58 2019 +0300 @@ -523,13 +523,18 @@ response.add(Redirect(self.ssl.listener.local_addr().unwrap().port()).send_self()) } - handlers::handle_client_accept( - &mut self.server, - client_id, - &mut response, - self.clients[client_id].peer_addr.ip().is_loopback(), - ); - self.handle_response(response, poll); + if let IpAddr::V4(addr) = self.clients[client_id].peer_addr.ip() { + handlers::handle_client_accept( + &mut self.server, + client_id, + &mut response, + addr.octets(), + addr.is_loopback(), + ); + self.handle_response(response, poll); + } else { + todo!("implement something") + } } pub fn accept_client(&mut self, poll: &Poll, server_token: mio::Token) -> io::Result<()> {