restructuring beginn

This commit is contained in:
Dietrich 2020-10-06 13:05:26 +02:00
parent bceb479c78
commit 8fa154bdd8
8 changed files with 108 additions and 38 deletions

View File

@ -20,3 +20,16 @@ trait UserDBWrite {
fn set_group(&self) -> Option<crate::Group>; fn set_group(&self) -> Option<crate::Group>;
fn new_group(&self) -> Option<crate::Group>; fn new_group(&self) -> Option<crate::Group>;
} }
trait UserRead {
fn get_username(&self) -> Option<crate::Passwd>;
fn get_uid(&self) -> Option<crate::Passwd>;
fn get_gid(&self) -> Option<crate::Passwd>;
// …
}
trait UserWrite {}
trait GroupRead {}
trait GroupWrite {}

View File

@ -1,7 +1,7 @@
extern crate adduser; extern crate adduser;
use adduser::passwd::Passwd; use adduser::Passwd;
use adduser::shadow::Shadow; use adduser::Shadow;
use std::fs::File; use std::fs::File;
use std::io::{prelude::*, BufReader}; use std::io::{prelude::*, BufReader};

View File

@ -10,7 +10,6 @@
use log::warn; use log::warn;
use regex::Regex; use regex::Regex;
use crate::passwd;
use crate::userlib_error::UserLibError; use crate::userlib_error::UserLibError;
use std::cmp::Eq; use std::cmp::Eq;
use std::convert::TryFrom; use std::convert::TryFrom;
@ -41,7 +40,7 @@ impl<'a> TryFrom<&'a str> for Groupname<'a> {
Ok(Self { groupname: source }) Ok(Self { groupname: source })
} else { } else {
Err(UserLibError::Message(format!( Err(UserLibError::Message(format!(
"Invalid username {}", "Invalid groupname -{}-",
source source
))) )))
} }
@ -51,10 +50,10 @@ impl<'a> TryFrom<&'a str> for Groupname<'a> {
/// 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 Group<'a> { pub struct Group<'a> {
groupname: Groupname<'a>, /* Username. */ groupname: Groupname<'a>, /* Username. */
pub(crate) password: passwd::Password<'a>, /* Usually not used (disabled with x) */ pub(crate) password: crate::Password<'a>, /* Usually not used (disabled with x) */
gid: passwd::Gid, /* Group ID. */ gid: crate::Gid, /* Group ID. */
members: Vec<passwd::Username<'a>>, /* Real name. */ members: Vec<crate::Username<'a>>, /* Real name. */
} }
impl<'a> Group<'a> { impl<'a> Group<'a> {
@ -63,7 +62,7 @@ impl<'a> Group<'a> {
self.groupname.groupname self.groupname.groupname
} }
#[must_use] #[must_use]
pub const fn get_members(&self) -> &Vec<passwd::Username<'a>> { pub const fn get_members(&self) -> &Vec<crate::Username<'a>> {
&self.members &self.members
} }
} }
@ -104,8 +103,8 @@ impl<'a> Group<'a> {
if elements.len() == 4 { if elements.len() == 4 {
Ok(Group { Ok(Group {
groupname: Groupname::try_from(*elements.get(0).unwrap())?, groupname: Groupname::try_from(*elements.get(0).unwrap())?,
password: passwd::Password::Disabled, password: crate::Password::Disabled,
gid: passwd::Gid::try_from(*elements.get(2).unwrap())?, gid: crate::Gid::try_from(*elements.get(2).unwrap())?,
members: parse_members_list(*elements.get(3).unwrap()), members: parse_members_list(*elements.get(3).unwrap()),
}) })
} else { } else {
@ -118,17 +117,16 @@ impl<'a> Group<'a> {
} }
} }
fn parse_members_list<'a>(source: &'a str) -> Vec<passwd::Username<'a>> { fn parse_members_list<'a>(source: &'a str) -> Vec<crate::Username<'a>> {
let mut res = vec![]; let mut res = vec![];
for mem in source.split(',') { for mem in source.split(',').filter(|x| !x.is_empty()) {
res.push(passwd::Username::try_from(mem).expect("failed to parse username")); res.push(crate::Username::try_from(mem).expect("failed to parse username"));
} }
res res
} }
#[test] #[test]
fn test_parse_and_back_identity() { fn test_parse_and_back_identity() {
println!("Test");
let line = "teste:x:1002:test,teste"; let line = "teste:x:1002:test,teste";
let line2 = Group::new_from_string(line).unwrap(); let line2 = Group::new_from_string(line).unwrap();
assert_eq!(format!("{}", line2), line); assert_eq!(format!("{}", line2), line);
@ -136,8 +134,13 @@ fn test_parse_and_back_identity() {
#[test] #[test]
fn test_groupname() { fn test_groupname() {
println!("Test");
let line = "teste:x:1002:test,teste"; let line = "teste:x:1002:test,teste";
let line2 = Group::new_from_string(line).unwrap(); let line2 = Group::new_from_string(line).unwrap();
assert_eq!(line2.get_groupname(), "teste"); assert_eq!(line2.get_groupname(), "teste");
} }
#[test]
fn test_root_group() {
let line = "root:x:0:";
let line2 = Group::new_from_string(line).unwrap();
assert_eq!(line2.get_groupname(), "root");
}

View File

@ -5,10 +5,11 @@ extern crate log;
pub mod api; pub mod api;
pub mod group; pub mod group;
pub mod passwd; pub mod user;
pub mod shadow;
pub mod userlib; pub mod userlib;
pub mod userlib_error; pub mod userlib_error;
pub use group::Group; pub use group::Group;
pub use passwd::{Gecos, Gid, HomeDir, Passwd, Password, ShellPath, Uid, Username}; pub use user::passwd_fields::{
pub use shadow::Shadow; EncryptedPassword, Gecos, Gid, HomeDir, Passwd, Password, ShellPath, Uid, Username,
};
pub use user::shadow_fields::Shadow;

14
src/user/mod.rs Normal file
View File

@ -0,0 +1,14 @@
pub mod passwd_fields;
pub mod shadow_fields;
/// A record(line) in the user database `/etc/passwd` found in most linux systems.
#[derive(Debug, PartialEq, Eq)]
pub struct User<'a> {
source: &'a str,
username: crate::Username<'a>, /* Username. */
password: crate::Password<'a>, /* Hashed passphrase, if shadow database not in use (see shadow.h). */
uid: crate::Uid, /* User ID. */
gid: crate::Gid, /* Group ID. */
gecos: crate::Gecos<'a>, /* Real name. */
home_dir: crate::HomeDir<'a>, /* Home directory. */
shell_path: crate::ShellPath<'a>, /* Shell program. */
}

View File

@ -56,7 +56,7 @@ impl<'a> TryFrom<&'a str> for Username<'a> {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum Password<'a> { pub enum Password<'a> {
Encrypted(EncryptedPassword<'a>), Encrypted(EncryptedPassword<'a>),
Shadow(crate::shadow::Shadow<'a>), Shadow(crate::Shadow<'a>),
Disabled, Disabled,
} }
@ -333,6 +333,7 @@ impl<'a> TryFrom<&'a str> for ShellPath<'a> {
/// A record(line) in the user database `/etc/passwd` found in most linux systems. /// A record(line) in the user database `/etc/passwd` found in most linux systems.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Passwd<'a> { pub struct Passwd<'a> {
source: &'a str,
username: Username<'a>, /* Username. */ username: Username<'a>, /* Username. */
password: Password<'a>, /* Hashed passphrase, if shadow database not in use (see shadow.h). */ password: Password<'a>, /* Hashed passphrase, if shadow database not in use (see shadow.h). */
uid: Uid, /* User ID. */ uid: Uid, /* User ID. */
@ -359,6 +360,7 @@ impl<'a> Passwd<'a> {
let elements: Vec<&str> = line.split(':').collect(); let elements: Vec<&str> = line.split(':').collect();
if elements.len() == 7 { if elements.len() == 7 {
Ok(Passwd { Ok(Passwd {
source: line,
username: Username::try_from(*elements.get(0).unwrap())?, username: Username::try_from(*elements.get(0).unwrap())?,
password: Password::Encrypted(EncryptedPassword::try_from( password: Password::Encrypted(EncryptedPassword::try_from(
*elements.get(1).unwrap(), *elements.get(1).unwrap(),
@ -381,7 +383,7 @@ impl<'a> Passwd<'a> {
pub const fn get_password(&self) -> &'a str { pub const fn get_password(&self) -> &'a str {
match self.password { match self.password {
Password::Encrypted(EncryptedPassword { password }) => password, Password::Encrypted(EncryptedPassword { password }) => password,
Password::Shadow(crate::shadow::Shadow { ref password, .. }) => password.password, Password::Shadow(crate::Shadow { ref password, .. }) => password.password,
Password::Disabled => "x", Password::Disabled => "x",
} }
} }
@ -410,6 +412,7 @@ impl<'a> Passwd<'a> {
impl Default for Passwd<'_> { impl Default for Passwd<'_> {
fn default() -> Self { fn default() -> Self {
Passwd { Passwd {
source: "",
username: Username { username: Username {
username: "defaultuser", username: "defaultuser",
}, },

View File

@ -9,7 +9,6 @@
use log::warn; use log::warn;
use crate::passwd;
use crate::userlib_error::UserLibError; use crate::userlib_error::UserLibError;
use std::cmp::Eq; use std::cmp::Eq;
use std::convert::TryFrom; use std::convert::TryFrom;
@ -18,15 +17,15 @@ 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: crate::Username<'a>, /* Username. */
pub(crate) password: passwd::EncryptedPassword<'a>, /* Hashed passphrase */ pub(crate) password: crate::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> { impl<'a> Shadow<'a> {
@ -97,8 +96,8 @@ impl<'a> Shadow<'a> {
if elements.len() == 9 { if elements.len() == 9 {
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: crate::Username::try_from(*elements.get(0).unwrap())?,
password: passwd::EncryptedPassword::try_from(*elements.get(1).unwrap())?, password: crate::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()),

View File

@ -14,7 +14,8 @@ use crate::userlib_error::UserLibError;
use std::cmp::Eq; use std::cmp::Eq;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::io::{BufRead, Read}; use std::fs::File;
use std::io::{BufRead, BufReader, Read};
pub struct UserDBLocal<'a> { pub struct UserDBLocal<'a> {
pub(crate) passwd_entries: Vec<crate::Passwd<'a>>, pub(crate) passwd_entries: Vec<crate::Passwd<'a>>,
@ -32,15 +33,34 @@ impl<'a> UserDBLocal<'a> {
let res = UserDBLocal { let res = UserDBLocal {
passwd_entries: passwd_content passwd_entries: passwd_content
.lines() .lines()
.map(|line| crate::Passwd::new_from_string(line).expect("failed to read lines")) .filter_map(|line| {
if line.len() > 5 {
println!("{}", line);
Some(crate::Passwd::new_from_string(line).expect("failed to read lines"))
} else {
None
}
})
.collect(), .collect(),
group_entries: group_content group_entries: group_content
.lines() .lines()
.map(|line| crate::Group::new_from_string(line).expect("Parsing failed")) .filter_map(|line| {
if line.len() > 5 {
Some(crate::Group::new_from_string(line).expect("Parsing failed"))
} else {
None
}
})
.collect(), .collect(),
shadow_entries: shadow_content shadow_entries: shadow_content
.lines() .lines()
.map(|line| crate::Shadow::new_from_string(line).expect("Parsing failed")) .filter_map(|line| {
if line.len() > 5 {
Some(crate::Shadow::new_from_string(line).expect("Parsing failed"))
} else {
None
}
})
.collect(), .collect(),
}; };
res res
@ -55,3 +75,20 @@ fn test_creator_user_db_local() {
"testuser" "testuser"
) )
} }
#[test]
fn test_parsing_local_database() {
let passwd_file = File::open("/etc/passwd").unwrap();
let mut passwd_reader = BufReader::new(passwd_file);
let mut my_passwd_lines = "".to_string();
passwd_reader.read_to_string(&mut my_passwd_lines).unwrap();
let group_file = File::open("/etc/group").unwrap();
let mut group_reader = BufReader::new(group_file);
let mut my_group_lines = "".to_string();
group_reader.read_to_string(&mut my_group_lines).unwrap();
let data = UserDBLocal::import_from_strings(&my_passwd_lines, "", &my_group_lines);
assert_eq!(
format!("{}", data.group_entries.get(0).unwrap().get_groupname()),
"teste"
);
}