Server auth handling improvements.

This commit is contained in:
Acrimon 2020-01-01 21:17:43 +01:00 committed by Marcel Märtens
parent 584dcddba9
commit 403deecc6d
5 changed files with 56 additions and 15 deletions

1
Cargo.lock generated
View File

@ -3878,6 +3878,7 @@ dependencies = [
name = "veloren-common"
version = "0.5.0"
dependencies = [
"authc 1.0.0 (git+https://gitlab.com/veloren/auth.git?rev=7c1abde83f0ea7d83b0e7c655fac82eb9bb3d7ad)",
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -552,6 +552,7 @@ impl Client {
ServerError::TooManyPlayers => return Err(Error::ServerWentMad),
ServerError::InvalidAuth => return Err(Error::InvalidAuth),
ServerError::AlreadyLoggedIn => return Err(Error::AlreadyLoggedIn),
ServerError::AuthError(_) => unreachable!(),
//TODO: ServerError::InvalidAlias => return Err(Error::InvalidAlias),
},
ServerMsg::Shutdown => return Err(Error::ServerShutdown),

View File

@ -33,6 +33,7 @@ crossbeam = "=0.7.2"
notify = "5.0.0-pre.1"
indexmap = "1.3.0"
sum_type = "0.2.0"
authc = { git = "https://gitlab.com/veloren/auth.git", rev = "7c1abde83f0ea7d83b0e7c655fac82eb9bb3d7ad" }
[dev-dependencies]
criterion = "0.3"

View File

@ -4,6 +4,7 @@ use crate::{
terrain::{Block, TerrainChunk},
ChatType,
};
use authc::AuthClientError;
use hashbrown::HashMap;
use vek::*;
@ -88,9 +89,14 @@ pub enum ServerError {
TooManyPlayers,
InvalidAuth,
AlreadyLoggedIn,
AuthError(String),
//TODO: InvalidAlias,
}
impl From<AuthClientError> for ServerError {
fn from(err: AuthClientError) -> Self { Self::AuthError(err.to_string()) }
}
impl ServerMsg {
pub fn chat(message: String) -> ServerMsg {
ServerMsg::ChatMsg {

View File

@ -1,8 +1,39 @@
use authc::{AuthClient, AuthToken};
use authc::{AuthClient, AuthToken, Uuid};
use common::msg::ServerError;
use hashbrown::HashMap;
use std::str::FromStr;
fn contains_value(map: &HashMap<String, String>, value: &str) -> bool {
let mut contains = false;
for ev in map.values() {
if value == ev {
contains = true;
}
}
contains
}
fn derive_uuid(username: &str) -> Uuid {
let mut state: [u8; 16] = [
52, 17, 19, 239, 52, 17, 19, 239, 52, 17, 19, 239, 52, 17, 19, 239,
];
for mix_byte_1 in username.as_bytes() {
for i in 0..16 {
let mix_byte_step: u8 = mix_byte_1
.wrapping_pow(239)
.wrapping_mul((i as u8).wrapping_pow(43));
let mix_byte_2 = state[i + mix_byte_step as usize % 16];
let rot_step: u8 = mix_byte_1
.wrapping_pow(29)
.wrapping_mul((i as u8).wrapping_pow(163));
state[i] = (state[i] ^ mix_byte_1)
.wrapping_mul(mix_byte_2)
.rotate_left(rot_step as u32);
}
}
Uuid::from_slice(&state).unwrap()
}
pub struct AuthProvider {
accounts: HashMap<String, String>,
auth_server: Option<AuthClient>,
@ -27,28 +58,29 @@ impl AuthProvider {
match &self.auth_server {
// Token from auth server expected
Some(srv) => {
// TODO: Check if already logged in!
log::info!("Validating '{}' token.", &username_or_token);
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)
if let Ok(token) = AuthToken::from_str(&username_or_token) {
match srv.validate(token) {
Ok(id) => {
if contains_value(&self.accounts, &id.to_string()) {
return Err(ServerError::AlreadyLoggedIn);
}
let username = srv.uuid_to_username(id.clone())?;
self.accounts.insert(username, id.to_string());
Ok(true)
},
Err(e) => Err(ServerError::from(e)),
}
} else {
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
let uuid = derive_uuid(&username_or_token);
self.accounts.insert(username_or_token, uuid.to_string());
Ok(true)
} else {
Err(ServerError::AlreadyLoggedIn)