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 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;
use adduser::passwd::Passwd;
use adduser::shadow::Shadow;
use adduser::Passwd;
use adduser::Shadow;
use std::fs::File;
use std::io::{prelude::*, BufReader};

View File

@ -10,7 +10,6 @@
use log::warn;
use regex::Regex;
use crate::passwd;
use crate::userlib_error::UserLibError;
use std::cmp::Eq;
use std::convert::TryFrom;
@ -41,7 +40,7 @@ impl<'a> TryFrom<&'a str> for Groupname<'a> {
Ok(Self { groupname: source })
} else {
Err(UserLibError::Message(format!(
"Invalid username {}",
"Invalid groupname -{}-",
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.
#[derive(Debug, PartialEq, Eq)]
pub struct Group<'a> {
groupname: Groupname<'a>, /* Username. */
pub(crate) password: passwd::Password<'a>, /* Usually not used (disabled with x) */
gid: passwd::Gid, /* Group ID. */
members: Vec<passwd::Username<'a>>, /* Real name. */
groupname: Groupname<'a>, /* Username. */
pub(crate) password: crate::Password<'a>, /* Usually not used (disabled with x) */
gid: crate::Gid, /* Group ID. */
members: Vec<crate::Username<'a>>, /* Real name. */
}
impl<'a> Group<'a> {
@ -63,7 +62,7 @@ impl<'a> Group<'a> {
self.groupname.groupname
}
#[must_use]
pub const fn get_members(&self) -> &Vec<passwd::Username<'a>> {
pub const fn get_members(&self) -> &Vec<crate::Username<'a>> {
&self.members
}
}
@ -104,8 +103,8 @@ impl<'a> Group<'a> {
if elements.len() == 4 {
Ok(Group {
groupname: Groupname::try_from(*elements.get(0).unwrap())?,
password: passwd::Password::Disabled,
gid: passwd::Gid::try_from(*elements.get(2).unwrap())?,
password: crate::Password::Disabled,
gid: crate::Gid::try_from(*elements.get(2).unwrap())?,
members: parse_members_list(*elements.get(3).unwrap()),
})
} 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![];
for mem in source.split(',') {
res.push(passwd::Username::try_from(mem).expect("failed to parse username"));
for mem in source.split(',').filter(|x| !x.is_empty()) {
res.push(crate::Username::try_from(mem).expect("failed to parse username"));
}
res
}
#[test]
fn test_parse_and_back_identity() {
println!("Test");
let line = "teste:x:1002:test,teste";
let line2 = Group::new_from_string(line).unwrap();
assert_eq!(format!("{}", line2), line);
@ -136,8 +134,13 @@ fn test_parse_and_back_identity() {
#[test]
fn test_groupname() {
println!("Test");
let line = "teste:x:1002:test,teste";
let line2 = Group::new_from_string(line).unwrap();
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 group;
pub mod passwd;
pub mod shadow;
pub mod user;
pub mod userlib;
pub mod userlib_error;
pub use group::Group;
pub use passwd::{Gecos, Gid, HomeDir, Passwd, Password, ShellPath, Uid, Username};
pub use shadow::Shadow;
pub use user::passwd_fields::{
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)]
pub enum Password<'a> {
Encrypted(EncryptedPassword<'a>),
Shadow(crate::shadow::Shadow<'a>),
Shadow(crate::Shadow<'a>),
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.
#[derive(Debug, PartialEq, Eq)]
pub struct Passwd<'a> {
source: &'a str,
username: Username<'a>, /* Username. */
password: Password<'a>, /* Hashed passphrase, if shadow database not in use (see shadow.h). */
uid: Uid, /* User ID. */
@ -359,6 +360,7 @@ impl<'a> Passwd<'a> {
let elements: Vec<&str> = line.split(':').collect();
if elements.len() == 7 {
Ok(Passwd {
source: line,
username: Username::try_from(*elements.get(0).unwrap())?,
password: Password::Encrypted(EncryptedPassword::try_from(
*elements.get(1).unwrap(),
@ -381,7 +383,7 @@ impl<'a> Passwd<'a> {
pub const fn get_password(&self) -> &'a str {
match self.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",
}
}
@ -410,6 +412,7 @@ impl<'a> Passwd<'a> {
impl Default for Passwd<'_> {
fn default() -> Self {
Passwd {
source: "",
username: Username {
username: "defaultuser",
},

View File

@ -9,7 +9,6 @@
use log::warn;
use crate::passwd;
use crate::userlib_error::UserLibError;
use std::cmp::Eq;
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.
#[derive(Debug, PartialEq, Eq)]
pub struct Shadow<'a> {
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. */
username: crate::Username<'a>, /* Username. */
pub(crate) password: crate::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> {
@ -97,8 +96,8 @@ impl<'a> Shadow<'a> {
if elements.len() == 9 {
let extra = elements.get(8).unwrap();
Ok(Shadow {
username: passwd::Username::try_from(*elements.get(0).unwrap())?,
password: passwd::EncryptedPassword::try_from(*elements.get(1).unwrap())?,
username: crate::Username::try_from(*elements.get(0).unwrap())?,
password: crate::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()),

View File

@ -14,7 +14,8 @@ use crate::userlib_error::UserLibError;
use std::cmp::Eq;
use std::convert::TryFrom;
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(crate) passwd_entries: Vec<crate::Passwd<'a>>,
@ -32,15 +33,34 @@ impl<'a> UserDBLocal<'a> {
let res = UserDBLocal {
passwd_entries: passwd_content
.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(),
group_entries: group_content
.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(),
shadow_entries: shadow_content
.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(),
};
res
@ -55,3 +75,20 @@ fn test_creator_user_db_local() {
"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"
);
}