gel_auth/
lib.rs

1pub mod handshake;
2pub mod md5;
3pub mod scram;
4
5use rand::Rng;
6
7/// Specifies the type of authentication or indicates the authentication method used for a connection.
8#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
9pub enum AuthType {
10    /// Denies a login or indicates that a connection was denied.
11    ///
12    /// When used with the server, this will cause it to emulate the given
13    /// authentication type, but unconditionally return a failure.
14    ///
15    /// This is used for testing purposes, and to emulate timing when a user
16    /// does not exist.
17    #[default]
18    Deny,
19    /// Trusts a login without requiring authentication, or indicates
20    /// that a connection required no authentication.
21    ///
22    /// When used with the server side of the handshake, this will cause it to
23    /// emulate the given authentication type, but unconditionally succeed.
24    /// Not compatible with SCRAM-SHA-256 as that protocol requires server and client
25    /// to cryptographically agree on a password.
26    Trust,
27    /// Plain text authentication, or indicates that plain text authentication was required.
28    Plain,
29    /// MD5 password authentication, or indicates that MD5 password authentication was required.
30    Md5,
31    /// SCRAM-SHA-256 authentication, or indicates that SCRAM-SHA-256 authentication was required.
32    ScramSha256,
33}
34
35#[derive(derive_more::Debug, Clone)]
36pub enum CredentialData {
37    /// A credential that always succeeds, regardless of input password. Due to
38    /// the design of SCRAM-SHA-256, this cannot be used with that auth type.
39    Trust,
40    /// A credential that always fails, regardless of the input password.
41    Deny,
42    /// A plain-text password.
43    #[debug("Plain(...)")]
44    Plain(String),
45    /// A stored MD5 hash + salt.
46    #[debug("Md5(...)")]
47    Md5(md5::StoredHash),
48    /// A stored SCRAM-SHA-256 key.
49    #[debug("Scram(...)")]
50    Scram(scram::StoredKey),
51}
52
53impl CredentialData {
54    pub fn new(ty: AuthType, username: String, password: String) -> Self {
55        match ty {
56            AuthType::Deny => Self::Deny,
57            AuthType::Trust => Self::Trust,
58            AuthType::Plain => Self::Plain(password),
59            AuthType::Md5 => Self::Md5(md5::StoredHash::generate(password.as_bytes(), &username)),
60            AuthType::ScramSha256 => {
61                let salt: [u8; 32] = rand::thread_rng().gen();
62                Self::Scram(scram::StoredKey::generate(password.as_bytes(), &salt, 4096))
63            }
64        }
65    }
66
67    pub fn auth_type(&self) -> AuthType {
68        match self {
69            CredentialData::Trust => AuthType::Trust,
70            CredentialData::Deny => AuthType::Deny,
71            CredentialData::Plain(..) => AuthType::Plain,
72            CredentialData::Md5(..) => AuthType::Md5,
73            CredentialData::Scram(..) => AuthType::ScramSha256,
74        }
75    }
76}