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)]
pub struct Username<'a> {
/// The username value
username: &'a str,
pub(crate) username: &'a str,
}
impl Display for Username<'_> {
@ -54,17 +54,32 @@ impl<'a> TryFrom<&'a str> for Username<'a> {
}
#[derive(Debug, PartialEq, Eq)]
pub struct Password<'a> {
password: &'a str,
pub enum Password<'a> {
Encrypted(EncryptedPassword<'a>),
Shadow(crate::shadow::Shadow<'a>),
}
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 {
write!(f, "{}", self.password,)
}
}
impl<'a> TryFrom<&'a str> for Password<'a> {
impl<'a> TryFrom<&'a str> for EncryptedPassword<'a> {
type Error = UserLibError;
fn try_from(source: &'a str) -> std::result::Result<Self, Self::Error> {
if source == "x" {
@ -343,7 +358,9 @@ impl<'a> Passwd<'a> {
if elements.len() == 7 {
Ok(Passwd {
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())?,
gid: Gid::try_from(*elements.get(3).unwrap())?,
gecos: Gecos::try_from(*elements.get(4).unwrap())?,
@ -360,7 +377,10 @@ impl<'a> Passwd<'a> {
}
#[must_use]
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]
pub const fn get_uid(&self) -> u32 {
@ -390,9 +410,9 @@ impl Default for Passwd<'_> {
username: Username {
username: "defaultuser",
},
password: Password {
password: Password::Encrypted(EncryptedPassword {
password: "notencrypted",
},
}),
uid: Uid { uid: 1001 },
gid: Gid { gid: 1001 },
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.
#[derive(Debug, PartialEq, Eq)]
pub struct Shadow<'a> {
username: passwd::Username<'a>, /* Username. */
password: passwd::Password<'a>, /* Hashed passphrase */
last_change: Option<chrono::NaiveDateTime>, /* User ID. */
earliest_change: Option<chrono::NaiveDateTime>, /* Group ID. */
latest_change: Option<chrono::NaiveDateTime>, /* Real name. */
warn_period: Option<chrono::Duration>, /* Home directory. */
deactivated: Option<chrono::Duration>, /* Shell program. */
deactivated_since: Option<chrono::Duration>, /* Shell program. */
extensions: Option<u64>, /* Shell program. */
username: passwd::Username<'a>, /* Username. */
pub(crate) password: passwd::EncryptedPassword<'a>, /* Hashed passphrase */
last_change: Option<chrono::NaiveDateTime>, /* User ID. */
earliest_change: Option<chrono::NaiveDateTime>, /* Group ID. */
latest_change: Option<chrono::NaiveDateTime>, /* Real name. */
warn_period: Option<chrono::Duration>, /* Home directory. */
deactivated: Option<chrono::Duration>, /* Shell program. */
deactivated_since: Option<chrono::Duration>, /* 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> {
@ -72,10 +83,10 @@ impl<'a> Shadow<'a> {
///
/// # 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:::"
/// ).unwrap();
///
/// assert_eq!(shad.get_username(), "test");
/// ```
///
/// # Errors
@ -87,7 +98,7 @@ impl<'a> Shadow<'a> {
let extra = elements.get(8).unwrap();
Ok(Shadow {
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()),
earliest_change: date_since_epoch(elements.get(3).unwrap()),
latest_change: date_since_epoch(elements.get(4).unwrap()),