restructuring beginn
This commit is contained in:
parent
bceb479c78
commit
8fa154bdd8
13
src/api.rs
13
src/api.rs
@ -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 {}
|
||||||
|
@ -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};
|
||||||
|
|
@ -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");
|
||||||
|
}
|
@ -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
14
src/user/mod.rs
Normal 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. */
|
||||||
|
}
|
@ -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",
|
||||||
},
|
},
|
@ -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()),
|
@ -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"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user