mirror of https://github.com/chipsenkbeil/distant
More progress
parent
ab849e8f9f
commit
47c8af6c1b
@ -1,6 +1,10 @@
|
||||
mod authenticated;
|
||||
mod authenticator;
|
||||
mod handler;
|
||||
mod methods;
|
||||
pub mod msg;
|
||||
|
||||
pub use authenticated::*;
|
||||
pub use authenticator::*;
|
||||
pub use handler::*;
|
||||
pub use methods::*;
|
||||
|
@ -0,0 +1,38 @@
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
/// Wrapper type around `T` that provides compile-time confirmation of being authenticated
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Authenticated<T>(T);
|
||||
|
||||
impl<T> Authenticated<T> {
|
||||
/// Consumes authenticated wrapper and returns the inner value
|
||||
pub fn into_inner(self) -> T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<T> for Authenticated<T> {
|
||||
fn as_ref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsMut<T> for Authenticated<T> {
|
||||
fn as_mut(&mut self) -> &mut T {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Authenticated<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for Authenticated<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
use super::{msg::*, Authenticator};
|
||||
use crate::HeapSecretKey;
|
||||
use async_trait::async_trait;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
|
||||
/// Represents the type of authentication method to use
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum MethodType {
|
||||
/// Indicates no authentication, which means this will always succeed
|
||||
None,
|
||||
|
||||
/// Indicates that a static key is being used for authentication
|
||||
StaticKey,
|
||||
|
||||
/// Indicates that re-authentication is being employed (using specialized key)
|
||||
Reauthentication,
|
||||
|
||||
/// When the method is unknown (happens when other side is unaware of the method)
|
||||
#[serde(other)]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// Represents an interface to authenticate using some method
|
||||
#[async_trait]
|
||||
pub trait AuthenticationMethod {
|
||||
async fn authenticate<A: Authenticator>(&self, authenticator: &mut A) -> io::Result<()>;
|
||||
}
|
||||
|
||||
/// Authenticaton method for a static secret key
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct NoneAuthenticationMethod;
|
||||
|
||||
impl NoneAuthenticationMethod {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for NoneAuthenticationMethod {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AuthenticationMethod for NoneAuthenticationMethod {
|
||||
async fn authenticate<A: Authenticator>(&self, _: &mut A) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Authenticaton method for a static secret key
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StaticKeyAuthenticationMethod {
|
||||
key: HeapSecretKey,
|
||||
}
|
||||
|
||||
impl StaticKeyAuthenticationMethod {
|
||||
#[inline]
|
||||
pub fn new(key: impl Into<HeapSecretKey>) -> Self {
|
||||
Self { key: key.into() }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AuthenticationMethod for StaticKeyAuthenticationMethod {
|
||||
async fn authenticate<A: Authenticator>(&self, authenticator: &mut A) -> io::Result<()> {
|
||||
let response = authenticator
|
||||
.challenge(Challenge {
|
||||
questions: vec![Question::new("key")],
|
||||
options: Default::default(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
if response.answers.is_empty() {
|
||||
let x = Error::fatal("missing answer");
|
||||
authenticator.error(x.clone()).await?;
|
||||
return Err(x.into_io_permission_denied());
|
||||
} else if response.answers.len() > 1 {
|
||||
authenticator
|
||||
.error(Error::error("more than one answer, picking first"))
|
||||
.await?;
|
||||
}
|
||||
|
||||
match response
|
||||
.answers
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap()
|
||||
.parse::<HeapSecretKey>()
|
||||
{
|
||||
Ok(key) if key == self.key => Ok(()),
|
||||
_ => {
|
||||
let x = Error::fatal("answer not a valid key");
|
||||
authenticator.error(x.clone()).await?;
|
||||
Err(x.into_io_permission_denied())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Authenticaton method for reauthentication
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ReauthenticationMethod {
|
||||
method: StaticKeyAuthenticationMethod,
|
||||
}
|
||||
|
||||
impl ReauthenticationMethod {
|
||||
#[inline]
|
||||
pub fn new(key: impl Into<HeapSecretKey>) -> Self {
|
||||
Self {
|
||||
method: StaticKeyAuthenticationMethod::new(key),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AuthenticationMethod for ReauthenticationMethod {
|
||||
async fn authenticate<A: Authenticator>(&self, authenticator: &mut A) -> io::Result<()> {
|
||||
self.method.authenticate(authenticator).await
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue