Make the conten of shadow part of the user struct

This commit is contained in:
Dietrich 2020-10-17 20:38:28 +02:00
parent 9482e85821
commit ffafa7e473
2 changed files with 71 additions and 60 deletions

View File

@ -10,13 +10,13 @@ use std::fmt::{self, Display};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct User { pub struct User {
source: String, source: String,
username: crate::Username, /* Username. */ username: crate::Username, /* Username. */
password: crate::Password, /* Hashed passphrase, if shadow database not in use (see shadow.h). */ pub(crate) password: crate::Password, /* Hashed passphrase, if shadow database not in use (see shadow.h). */
uid: crate::Uid, /* User ID. */ uid: crate::Uid, /* User ID. */
gid: crate::Gid, /* Group ID. */ gid: crate::Gid, /* Group ID. */
gecos: crate::Gecos, /* Real name. */ gecos: crate::Gecos, /* Real name. */
home_dir: crate::HomeDir, /* Home directory. */ home_dir: crate::HomeDir, /* Home directory. */
shell_path: crate::ShellPath, /* Shell program. */ shell_path: crate::ShellPath, /* Shell program. */
} }
impl NewFromString for User { impl NewFromString for User {

View File

@ -8,14 +8,14 @@
#![allow(clippy::non_ascii_literal)] #![allow(clippy::non_ascii_literal)]
use log::warn; use log::warn;
use std::collections::HashMap;
use std::fs::File; use std::fs::File;
use std::io::{BufReader, Read}; use std::io::{BufReader, Read};
use std::path::PathBuf; use std::path::PathBuf;
pub struct UserDBLocal { pub struct UserDBLocal {
source_files: Files, source_files: Files,
pub passwd_entries: Vec<crate::User>, pub users: HashMap<String, crate::User>,
pub shadow_entries: Vec<crate::Shadow>,
pub group_entries: Vec<crate::Group>, pub group_entries: Vec<crate::Group>,
} }
@ -42,21 +42,30 @@ impl UserDBLocal {
shadow_content: &str, shadow_content: &str,
group_content: &str, group_content: &str,
) -> Self { ) -> Self {
let res = Self { let shadow_entries: Vec<crate::Shadow> = shadow_content
.lines()
.filter_map(|line| {
if line.len() > 5 {
Some(crate::Shadow::new_from_string(line.to_owned()).expect("Parsing failed"))
} else {
None
}
})
.collect();
let mut res = Self {
source_files: Files { source_files: Files {
passwd: None, passwd: None,
group: None, group: None,
shadow: None, shadow: None,
}, },
passwd_entries: passwd_content users: passwd_content
.lines() .lines()
.filter_map(|line| { .filter_map(|line| {
if line.len() > 5 { if line.len() > 5 {
println!("{}", line); println!("{}", line);
Some( let user = crate::User::new_from_string(line.to_owned())
crate::User::new_from_string(line.to_owned()) .expect("failed to read lines");
.expect("failed to read lines"), Some((user.get_username().to_owned(), user))
)
} else { } else {
None None
} }
@ -74,60 +83,65 @@ impl UserDBLocal {
} }
}) })
.collect(), .collect(),
shadow_entries: shadow_content
.lines()
.filter_map(|line| {
if line.len() > 5 {
Some(
crate::Shadow::new_from_string(line.to_owned())
.expect("Parsing failed"),
)
} else {
None
}
})
.collect(),
}; };
for shadow in shadow_entries {
let user = res.users.get_mut(shadow.get_username()).expect(&format!(
"the user {} does not exist",
shadow.get_username()
));
user.password = crate::Password::Shadow(shadow);
}
res res
} }
#[must_use] #[must_use]
pub fn load_files(files: Files) -> Self { pub fn load_files(files: Files) -> Self {
let passwd_file = File::open( let my_passwd_lines = file_to_string(files.passwd.as_ref());
files let my_group_lines = file_to_string(files.group.as_ref());
.group let my_shadow_lines = file_to_string(files.shadow.as_ref());
.clone()
.expect("passwd file path cannot be None"),
)
.unwrap();
let mut passwd_reader = BufReader::new(passwd_file);
let mut my_passwd_lines = String::new();
passwd_reader.read_to_string(&mut my_passwd_lines).unwrap();
let group_file =
File::open(files.group.clone().expect("group file path cannot be None")).unwrap();
let mut group_reader = BufReader::new(group_file);
let mut my_group_lines = String::new();
group_reader.read_to_string(&mut my_group_lines).unwrap();
let shadow_file = File::open(
files
.shadow
.clone()
.expect("shadow file path cannot be None"),
)
.expect("Failed to read the shadow file. Most of the time root permissions are needed");
let mut shadow_reader = BufReader::new(shadow_file);
let mut my_shadow_lines = String::new();
shadow_reader.read_to_string(&mut my_shadow_lines).unwrap();
let mut users = user_vec_to_hashmap(string_to(&my_passwd_lines));
let passwds: Vec<crate::Shadow> = string_to(&my_shadow_lines);
shadow_to_users(&mut users, passwds);
Self { Self {
source_files: files, source_files: files,
passwd_entries: string_to(&my_passwd_lines), users,
group_entries: string_to(&my_group_lines), group_entries: string_to(&my_group_lines),
shadow_entries: string_to(&my_shadow_lines),
} }
} }
} }
fn file_to_string(path: Option<&PathBuf>) -> String {
let file = File::open(path.expect("Path cannot be None".into()))
.expect("Failed to read the file. Most of the time root permissions are needed".into());
let mut reader = BufReader::new(file);
let mut lines = String::new();
reader.read_to_string(&mut lines).unwrap();
lines
}
/// Merge the Shadow passwords into the users.
fn shadow_to_users(
users: &mut HashMap<String, crate::User>,
shadow: Vec<crate::Shadow>,
) -> &mut HashMap<String, crate::User> {
for pass in shadow {
let user = users
.get_mut(pass.get_username())
.expect(&format!("the user {} does not exist", pass.get_username()));
user.password = crate::Password::Shadow(pass);
}
users
}
/// Convert a `Vec<crate::User>` to a `HashMap<String, crate::User>` where the username is used as key.
fn user_vec_to_hashmap(users: Vec<crate::User>) -> HashMap<String, crate::User> {
users
.into_iter()
.map(|x| (x.get_username().to_owned(), x))
.collect()
}
/// Try to parse a String into some Object /// Try to parse a String into some Object
/// ///
/// # Errors /// # Errors
@ -157,11 +171,8 @@ where
#[test] #[test]
fn test_creator_user_db_local() { fn test_creator_user_db_local() {
let data = UserDBLocal::import_from_strings("testuser:x:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test", "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::", "teste:x:1002:test,teste"); let data = UserDBLocal::import_from_strings("test:x:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test", "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::", "teste:x:1002:test,test");
assert_eq!( assert_eq!(data.users.get("test").unwrap().get_username(), "test")
data.passwd_entries.get(0).unwrap().get_username(),
"testuser"
)
} }
#[test] #[test]