1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
use derive_more::Display;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
mod client;
pub use client::*;
mod handshake;
pub use handshake::*;
mod server;
pub use server::*;
/// Represents authentication messages that can be sent over the wire
///
/// NOTE: Must use serde's content attribute with the tag attribute. Just the tag attribute will
/// cause deserialization to fail
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type", content = "data")]
pub enum Auth {
/// Represents a request to perform an authentication handshake,
/// providing the public key and salt from one side in order to
/// derive the shared key
#[serde(rename = "auth_handshake")]
Handshake {
/// Bytes of the public key
#[serde(with = "serde_bytes")]
public_key: PublicKeyBytes,
/// Randomly generated salt
#[serde(with = "serde_bytes")]
salt: Salt,
},
/// Represents the bytes of an encrypted message
///
/// Underneath, will be one of either [`AuthRequest`] or [`AuthResponse`]
#[serde(rename = "auth_msg")]
Msg {
#[serde(with = "serde_bytes")]
encrypted_payload: Vec<u8>,
},
}
/// Represents authentication messages that act as initiators such as providing
/// a challenge, verifying information, presenting information, or highlighting an error
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type")]
pub enum AuthRequest {
/// Represents a challenge comprising a series of questions to be presented
Challenge {
questions: Vec<AuthQuestion>,
options: HashMap<String, String>,
},
/// Represents an ask to verify some information
Verify { kind: AuthVerifyKind, text: String },
/// Represents some information to be presented
Info { text: String },
/// Represents some error that occurred
Error { kind: AuthErrorKind, text: String },
}
/// Represents authentication messages that are responses to auth requests such
/// as answers to challenges or verifying information
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type")]
pub enum AuthResponse {
/// Represents the answers to a previously-asked challenge
Challenge { answers: Vec<String> },
/// Represents the answer to a previously-asked verify
Verify { valid: bool },
}
/// Represents the type of verification being requested
#[derive(Copy, Clone, Debug, Display, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum AuthVerifyKind {
/// An ask to verify the host such as with SSH
#[display(fmt = "host")]
Host,
}
/// Represents a single question in a challenge
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuthQuestion {
/// The text of the question
pub text: String,
/// Any options information specific to a particular auth domain
/// such as including a username and instructions for SSH authentication
pub options: HashMap<String, String>,
}
impl AuthQuestion {
/// Creates a new question without any options data
pub fn new(text: impl Into<String>) -> Self {
Self {
text: text.into(),
options: HashMap::new(),
}
}
}
/// Represents the type of error encountered during authentication
#[derive(Copy, Clone, Debug, Display, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuthErrorKind {
/// When the answer(s) to a challenge do not pass authentication
FailedChallenge,
/// When verification during authentication fails
/// (e.g. a host is not allowed or blocked)
FailedVerification,
/// When the error is unknown
Unknown,
}