:/ and reactivated the password field

This commit is contained in:
Songtronix 2019-12-21 18:02:39 +01:00 committed by Marcel Märtens
parent 3672f4916e
commit 50b845d1c3
13 changed files with 759 additions and 33 deletions

652
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@ pub enum Error {
ServerShutdown, ServerShutdown,
TooManyPlayers, TooManyPlayers,
InvalidAuth, InvalidAuth,
AlreadyLoggedIn,
//TODO: InvalidAlias, //TODO: InvalidAlias,
Other(String), Other(String),
} }

View File

@ -105,6 +105,8 @@ impl Client {
); );
} }
log::error!("Auth Server: {:?}", server_info.auth_provider);
// Initialize `State` // Initialize `State`
let mut state = State::default(); let mut state = State::default();
let entity = state.ecs_mut().apply_entity_package(entity_package); let entity = state.ecs_mut().apply_entity_package(entity_package);
@ -549,6 +551,7 @@ impl Client {
ServerMsg::Error(e) => match e { ServerMsg::Error(e) => match e {
ServerError::TooManyPlayers => return Err(Error::ServerWentMad), ServerError::TooManyPlayers => return Err(Error::ServerWentMad),
ServerError::InvalidAuth => return Err(Error::InvalidAuth), ServerError::InvalidAuth => return Err(Error::InvalidAuth),
ServerError::AlreadyLoggedIn => return Err(Error::AlreadyLoggedIn),
//TODO: ServerError::InvalidAlias => return Err(Error::InvalidAlias), //TODO: ServerError::InvalidAlias => return Err(Error::InvalidAlias),
}, },
ServerMsg::Shutdown => return Err(Error::ServerShutdown), ServerMsg::Shutdown => return Err(Error::ServerShutdown),

View File

@ -21,6 +21,7 @@ pub struct ServerInfo {
pub description: String, pub description: String,
pub git_hash: String, pub git_hash: String,
pub git_date: String, pub git_date: String,
pub auth_provider: Option<String>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -86,6 +87,7 @@ pub enum ServerMsg {
pub enum ServerError { pub enum ServerError {
TooManyPlayers, TooManyPlayers,
InvalidAuth, InvalidAuth,
AlreadyLoggedIn,
//TODO: InvalidAlias, //TODO: InvalidAlias,
} }

View File

@ -31,3 +31,4 @@ prometheus = "0.7"
prometheus-static-metric = "0.2" prometheus-static-metric = "0.2"
rouille = "3.0.0" rouille = "3.0.0"
portpicker = { git = "https://github.com/wusyong/portpicker-rs", branch = "fix_ipv6" } portpicker = { git = "https://github.com/wusyong/portpicker-rs", branch = "fix_ipv6" }
authc = { git = "https://gitlab.com/veloren/auth.git" }

View File

@ -1,32 +1,59 @@
use authc::{AuthClient, AuthToken};
use common::msg::ServerError;
use hashbrown::HashMap; use hashbrown::HashMap;
use log::{info, warn}; use std::str::FromStr;
pub struct AuthProvider { pub struct AuthProvider {
accounts: HashMap<String, String>, accounts: HashMap<String, String>,
auth_server: Option<AuthClient>,
} }
impl AuthProvider { impl AuthProvider {
pub fn new() -> Self { pub fn new(auth_addr: Option<String>) -> Self {
let auth_server = match auth_addr {
Some(addr) => Some(AuthClient::new(addr)),
None => None,
};
AuthProvider { AuthProvider {
accounts: HashMap::new(), accounts: HashMap::new(),
auth_server,
} }
} }
pub fn query(&mut self, username: String, password: String) -> bool { pub fn query(&mut self, username_or_token: String) -> Result<bool, ServerError> {
let pwd = password.clone(); // Based on whether auth server is provided or not we expect an username or
if self.accounts.entry(username.clone()).or_insert_with(|| { // token
info!("Registered new user '{}'", &username); match &self.auth_server {
pwd // Token from auth server expected
}) == &password Some(srv) => {
{ // TODO: Check if already logged in!
info!("User '{}' successfully authenticated", username); log::info!("Validating '{}' token.", &username_or_token);
true match srv.validate(
AuthToken::from_str(&username_or_token).expect("Failed parsing token"), // TODO: POSSIBLE DOS, handle result!
) {
Ok(id) => {
// TODO: Get username!
self.accounts.insert("peter".into(), id.to_string());
Ok(true)
}
Err(e) => {
log::error!("{}", e);
Ok(false)
}
}
},
// Username is expected
None => {
if !self.accounts.contains_key(&username_or_token) {
log::info!("New User '{}'", username_or_token);
self.accounts
.insert(username_or_token, "whateverUUID".into()); // TODO: generate UUID
Ok(true)
} else { } else {
warn!( Err(ServerError::AlreadyLoggedIn)
"User '{}' attempted to log in with invalid password '{}'!", }
username, password },
);
false
} }
} }
} }

View File

@ -86,7 +86,9 @@ impl Server {
let mut state = State::default(); let mut state = State::default();
state.ecs_mut().insert(EventBus::<ServerEvent>::default()); state.ecs_mut().insert(EventBus::<ServerEvent>::default());
// TODO: anything but this // TODO: anything but this
state.ecs_mut().insert(AuthProvider::new()); state
.ecs_mut()
.insert(AuthProvider::new(settings.auth_server_address.clone()));
state.ecs_mut().insert(Tick(0)); state.ecs_mut().insert(Tick(0));
state.ecs_mut().insert(ChunkGenerator::new()); state.ecs_mut().insert(ChunkGenerator::new());
// System timers for performance monitoring // System timers for performance monitoring
@ -196,6 +198,7 @@ impl Server {
description: settings.server_description.clone(), description: settings.server_description.clone(),
git_hash: common::util::GIT_HASH.to_string(), git_hash: common::util::GIT_HASH.to_string(),
git_date: common::util::GIT_DATE.to_string(), git_date: common::util::GIT_DATE.to_string(),
auth_provider: settings.auth_server_address.clone(),
}, },
metrics: ServerMetrics::new(settings.metrics_address) metrics: ServerMetrics::new(settings.metrics_address)
.expect("Failed to initialize server metrics submodule."), .expect("Failed to initialize server metrics submodule."),

View File

@ -10,12 +10,12 @@ const DEFAULT_WORLD_SEED: u32 = 5284;
pub struct ServerSettings { pub struct ServerSettings {
pub gameserver_address: SocketAddr, pub gameserver_address: SocketAddr,
pub metrics_address: SocketAddr, pub metrics_address: SocketAddr,
pub auth_server_address: Option<String>,
pub max_players: usize, pub max_players: usize,
pub world_seed: u32, pub world_seed: u32,
//pub pvp_enabled: bool, //pub pvp_enabled: bool,
pub server_name: String, pub server_name: String,
pub server_description: String, pub server_description: String,
//pub login_server: whatever
pub start_time: f64, pub start_time: f64,
pub admins: Vec<String>, pub admins: Vec<String>,
/// When set to None, loads the default map file (if available); otherwise, /// When set to None, loads the default map file (if available); otherwise,
@ -28,6 +28,7 @@ impl Default for ServerSettings {
Self { Self {
gameserver_address: SocketAddr::from(([0; 4], 14004)), gameserver_address: SocketAddr::from(([0; 4], 14004)),
metrics_address: SocketAddr::from(([0; 4], 14005)), metrics_address: SocketAddr::from(([0; 4], 14005)),
auth_server_address: Some("https://auth.veloren.net".into()),
world_seed: DEFAULT_WORLD_SEED, world_seed: DEFAULT_WORLD_SEED,
server_name: "Veloren Alpha".to_owned(), server_name: "Veloren Alpha".to_owned(),
server_description: "This is the best Veloren server.".to_owned(), server_description: "This is the best Veloren server.".to_owned(),
@ -107,6 +108,7 @@ impl ServerSettings {
[127, 0, 0, 1], [127, 0, 0, 1],
pick_unused_port().expect("Failed to find unused port!"), pick_unused_port().expect("Failed to find unused port!"),
)), )),
auth_server_address: None,
// If loading the default map file, make sure the seed is also default. // If loading the default map file, make sure the seed is also default.
world_seed: if load.map_file.is_some() { world_seed: if load.map_file.is_some() {
load.world_seed load.world_seed

View File

@ -124,7 +124,12 @@ impl<'a> System<'a> for Sys {
}, },
// Valid player // Valid player
ClientMsg::Register { player, password } if player.is_valid() => { ClientMsg::Register { player, password } if player.is_valid() => {
if !accounts.query(player.alias.clone(), password) { if !accounts
.query(password.clone())
.expect("Handle this error!")
{
// TODO: Graceful error handling!
// TODO: Graceful error handling! (e.g. AlreadyLoggedIn)
client.error_state(RequestStateError::Denied); client.error_state(RequestStateError::Denied);
break; break;
} }

View File

@ -64,6 +64,7 @@ rust-argon2 = "0.5"
bincode = "1.2" bincode = "1.2"
deunicode = "1.0" deunicode = "1.0"
uvth = "3.1.1" uvth = "3.1.1"
authc = { git = "https://gitlab.com/veloren/auth.git" }
[target.'cfg(target_os = "macos")'.dependencies] [target.'cfg(target_os = "macos")'.dependencies]
dispatch = "0.1.4" dispatch = "0.1.4"

View File

@ -68,13 +68,40 @@ impl ClientInit {
{ {
match Client::new(socket_addr, player.view_distance) { match Client::new(socket_addr, player.view_distance) {
Ok(mut client) => { Ok(mut client) => {
// Authentication
let username_or_token = match &client.server_info.auth_provider
{
Some(addr) => {
let auth_client = authc::AuthClient::new(addr);
// TODO: PROMPT USER INCASE OF THE AUTH SERVER BEING
// UNKNOWN!
log::error!(
"Logging in with '{}', '{}'.",
&player.alias,
&password
);
match auth_client.sign_in(
&player.alias,
&password,
socket_addr.ip(),
) {
Ok(token) => token.serialize(),
// TODO: Properly deal with it
Err(e) => panic!(
"Failed to sign in to auth server '{}'! {}",
addr, e
),
}
},
None => player.alias.clone(),
};
if let Err(ClientError::InvalidAuth) = if let Err(ClientError::InvalidAuth) =
client.register(player.clone(), password.clone()) client.register(player.clone(), username_or_token.clone())
{ {
last_err = Some(Error::InvalidAuth); last_err = Some(Error::InvalidAuth);
break; break;
} }
//client.register(player, password);
let _ = tx.send(Ok(client)); let _ = tx.send(Ok(client));
return; return;
}, },

View File

@ -8,7 +8,6 @@ use crate::{
window::Event, window::Event,
Direction, GlobalState, PlayState, PlayStateResult, Direction, GlobalState, PlayState, PlayStateResult,
}; };
use argon2::{self, Config};
use client_init::{ClientInit, Error as InitError}; use client_init::{ClientInit, Error as InitError};
use common::{assets::load_expect, clock::Clock, comp}; use common::{assets::load_expect, clock::Clock, comp};
use log::warn; use log::warn;
@ -202,9 +201,10 @@ fn attempt_login(
(server_address, server_port, false), (server_address, server_port, false),
player, player,
{ {
let salt = b"staticsalt_zTuGkGvybZIjZbNUDtw15"; password
/*let salt = b"staticsalt_zTuGkGvybZIjZbNUDtw15";
let config = Config::default(); let config = Config::default();
argon2::hash_encoded(password.as_bytes(), salt, &config).unwrap() argon2::hash_encoded(password.as_bytes(), salt, &config).unwrap()*/
}, },
)); ));
} }

View File

@ -90,7 +90,7 @@ image_ids! {
button_hover: "voxygen.element.buttons.button_hover", button_hover: "voxygen.element.buttons.button_hover",
button_press: "voxygen.element.buttons.button_press", button_press: "voxygen.element.buttons.button_press",
input_bg_top: "voxygen.element.misc_bg.textbox_top", input_bg_top: "voxygen.element.misc_bg.textbox_top",
//input_bg_mid: "voxygen.element.misc_bg.textbox_mid", <-- For password input input_bg_mid: "voxygen.element.misc_bg.textbox_mid",
input_bg_bot: "voxygen.element.misc_bg.textbox_bot", input_bg_bot: "voxygen.element.misc_bg.textbox_bot",
@ -461,14 +461,14 @@ impl MainMenuUi {
} }
} }
// Password // Password
// TODO: REACTIVATE THIS WHEN A PROPER ACCOUNT SYSTEM IS IN PLACE // TODO: Why isn't it showing up?
/*Rectangle::fill_with([320.0, 50.0], color::rgba(0.0, 0.0, 0.0, 0.97)) // Password
Rectangle::fill_with([320.0, 50.0], color::rgba(0.0, 0.0, 0.0, 0.97))
.down_from(self.ids.usrnm_bg, 30.0) .down_from(self.ids.usrnm_bg, 30.0)
.set(self.ids.passwd_bg, ui_widgets); .set(self.ids.passwd_bg, ui_widgets);
Image::new(self.imgs.input_bg_mid) Image::new(self.imgs.input_bg_mid)
.w_h(337.0, 67.0) .w_h(337.0, 67.0)
.middle_of(self.ids.passwd_bg) .middle_of(self.ids.passwd_bg)
.color(Some(INACTIVE))
.set(self.ids.password_bg, ui_widgets); .set(self.ids.password_bg, ui_widgets);
for event in TextBox::new(&self.password) for event in TextBox::new(&self.password)
.w_h(290.0, 30.0) .w_h(290.0, 30.0)
@ -485,12 +485,13 @@ impl MainMenuUi {
TextBoxEvent::Update(password) => { TextBoxEvent::Update(password) => {
// Note: TextBox limits the input string length to what fits in it // Note: TextBox limits the input string length to what fits in it
self.password = password; self.password = password;
} },
TextBoxEvent::Enter => { TextBoxEvent::Enter => {
login!(); login!();
},
} }
} }
}*/
if self.show_servers { if self.show_servers {
Image::new(self.imgs.info_frame) Image::new(self.imgs.info_frame)
.mid_top_with_margin_on(self.ids.username_bg, -320.0) .mid_top_with_margin_on(self.ids.username_bg, -320.0)
@ -556,7 +557,7 @@ impl MainMenuUi {
} }
// Server address // Server address
Rectangle::fill_with([320.0, 50.0], color::rgba(0.0, 0.0, 0.0, 0.97)) Rectangle::fill_with([320.0, 50.0], color::rgba(0.0, 0.0, 0.0, 0.97))
.down_from(self.ids.usrnm_bg, 30.0) .down_from(self.ids.passwd_bg, 30.0)
.set(self.ids.srvr_bg, ui_widgets); .set(self.ids.srvr_bg, ui_widgets);
Image::new(self.imgs.input_bg_bot) Image::new(self.imgs.input_bg_bot)
.w_h(337.0, 67.0) .w_h(337.0, 67.0)
@ -582,6 +583,7 @@ impl MainMenuUi {
}, },
} }
} }
// Login button // Login button
if Button::image(self.imgs.button) if Button::image(self.imgs.button)
.hover_image(self.imgs.button_hover) .hover_image(self.imgs.button_hover)