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}