Make shadow an entry of the passwd struct

This commit is contained in:
Dietrich 2020-10-03 21:07:47 +02:00
parent 4af05c1134
commit 180934b789
2 changed files with 51 additions and 20 deletions

View File

@ -23,7 +23,7 @@ use std::fmt::{self, Display};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Username<'a> { pub struct Username<'a> {
/// The username value /// The username value
username: &'a str, pub(crate) username: &'a str,
} }
impl Display for Username<'_> { impl Display for Username<'_> {
@ -54,17 +54,32 @@ impl<'a> TryFrom<&'a str> for Username<'a> {
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Password<'a> { pub enum Password<'a> {
password: &'a str, Encrypted(EncryptedPassword<'a>),
Shadow(crate::shadow::Shadow<'a>),
} }
impl Display for Password<'_> { impl Display for Password<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Password::Encrypted(EncryptedPassword { password }) => write!(f, "{}", password,),
Password::Shadow(_) => write!(f, "x"),
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct EncryptedPassword<'a> {
pub(crate) password: &'a str,
}
impl Display for EncryptedPassword<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.password,) write!(f, "{}", self.password,)
} }
} }
impl<'a> TryFrom<&'a str> for Password<'a> { impl<'a> TryFrom<&'a str> for EncryptedPassword<'a> {
type Error = UserLibError; type Error = UserLibError;
fn try_from(source: &'a str) -> std::result::Result<Self, Self::Error> { fn try_from(source: &'a str) -> std::result::Result<Self, Self::Error> {
if source == "x" { if source == "x" {
@ -343,7 +358,9 @@ impl<'a> Passwd<'a> {
if elements.len() == 7 { if elements.len() == 7 {
Ok(Passwd { Ok(Passwd {
username: Username::try_from(*elements.get(0).unwrap())?, username: Username::try_from(*elements.get(0).unwrap())?,
password: Password::try_from(*elements.get(1).unwrap())?, password: Password::Encrypted(EncryptedPassword::try_from(
*elements.get(1).unwrap(),
)?),
uid: Uid::try_from(*elements.get(2).unwrap())?, uid: Uid::try_from(*elements.get(2).unwrap())?,
gid: Gid::try_from(*elements.get(3).unwrap())?, gid: Gid::try_from(*elements.get(3).unwrap())?,
gecos: Gecos::try_from(*elements.get(4).unwrap())?, gecos: Gecos::try_from(*elements.get(4).unwrap())?,
@ -360,7 +377,10 @@ impl<'a> Passwd<'a> {
} }
#[must_use] #[must_use]
pub const fn get_password(&self) -> &'a str { pub const fn get_password(&self) -> &'a str {
self.password.password match self.password {
Password::Encrypted(EncryptedPassword { password }) => password,
Password::Shadow(crate::shadow::Shadow { ref password, .. }) => password.password,
}
} }
#[must_use] #[must_use]
pub const fn get_uid(&self) -> u32 { pub const fn get_uid(&self) -> u32 {
@ -390,9 +410,9 @@ impl Default for Passwd<'_> {
username: Username { username: Username {
username: "defaultuser", username: "defaultuser",
}, },
password: Password { password: Password::Encrypted(EncryptedPassword {
password: "notencrypted", password: "notencrypted",
}, }),
uid: Uid { uid: 1001 }, uid: Uid { uid: 1001 },
gid: Gid { gid: 1001 }, gid: Gid { gid: 1001 },
gecos: Gecos::Simple { gecos: Gecos::Simple {

View File

@ -18,15 +18,26 @@ use std::fmt::{self, Debug, Display};
/// A record(line) in the user database `/etc/shadow` found in most linux systems. /// A record(line) in the user database `/etc/shadow` found in most linux systems.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Shadow<'a> { pub struct Shadow<'a> {
username: passwd::Username<'a>, /* Username. */ username: passwd::Username<'a>, /* Username. */
password: passwd::Password<'a>, /* Hashed passphrase */ pub(crate) password: passwd::EncryptedPassword<'a>, /* Hashed passphrase */
last_change: Option<chrono::NaiveDateTime>, /* User ID. */ last_change: Option<chrono::NaiveDateTime>, /* User ID. */
earliest_change: Option<chrono::NaiveDateTime>, /* Group ID. */ earliest_change: Option<chrono::NaiveDateTime>, /* Group ID. */
latest_change: Option<chrono::NaiveDateTime>, /* Real name. */ latest_change: Option<chrono::NaiveDateTime>, /* Real name. */
warn_period: Option<chrono::Duration>, /* Home directory. */ warn_period: Option<chrono::Duration>, /* Home directory. */
deactivated: Option<chrono::Duration>, /* Shell program. */ deactivated: Option<chrono::Duration>, /* Shell program. */
deactivated_since: Option<chrono::Duration>, /* Shell program. */ deactivated_since: Option<chrono::Duration>, /* Shell program. */
extensions: Option<u64>, /* Shell program. */ extensions: Option<u64>, /* Shell program. */
}
impl<'a> Shadow<'a> {
#[must_use]
pub const fn get_username(&self) -> &'a str {
self.username.username
}
#[must_use]
pub const fn get_password(&self) -> &'a str {
self.password.password
}
} }
impl<'a> Display for Shadow<'a> { impl<'a> Display for Shadow<'a> {
@ -72,10 +83,10 @@ impl<'a> Shadow<'a> {
/// ///
/// # Example /// # Example
/// ``` /// ```
/// let pwd = adduser::shadow::Shadow::new_from_string( /// let shad = adduser::shadow::Shadow::new_from_string(
/// "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::" /// "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::"
/// ).unwrap(); /// ).unwrap();
/// /// assert_eq!(shad.get_username(), "test");
/// ``` /// ```
/// ///
/// # Errors /// # Errors
@ -87,7 +98,7 @@ impl<'a> Shadow<'a> {
let extra = elements.get(8).unwrap(); let extra = elements.get(8).unwrap();
Ok(Shadow { Ok(Shadow {
username: passwd::Username::try_from(*elements.get(0).unwrap())?, username: passwd::Username::try_from(*elements.get(0).unwrap())?,
password: passwd::Password::try_from(*elements.get(1).unwrap())?, password: passwd::EncryptedPassword::try_from(*elements.get(1).unwrap())?,
last_change: date_since_epoch(elements.get(2).unwrap()), last_change: date_since_epoch(elements.get(2).unwrap()),
earliest_change: date_since_epoch(elements.get(3).unwrap()), earliest_change: date_since_epoch(elements.get(3).unwrap()),
latest_change: date_since_epoch(elements.get(4).unwrap()), latest_change: date_since_epoch(elements.get(4).unwrap()),