Compare commits
3 Commits
8dd2c53aa9
...
6389bb988d
Author | SHA1 | Date | |
---|---|---|---|
6389bb988d | |||
bacbfae4d1 | |||
4207e1dc0f |
@ -24,6 +24,13 @@ pub struct User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
|
pub fn get_shadow(&self) -> Option<&crate::Shadow> {
|
||||||
|
match self.password {
|
||||||
|
crate::Password::Encrypted(_) => None,
|
||||||
|
crate::Password::Shadow(ref s) => Some(s),
|
||||||
|
crate::Password::Disabled => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
/*fn get_nth_line(content: &str, n: u32) -> (String, u64) {
|
/*fn get_nth_line(content: &str, n: u32) -> (String, u64) {
|
||||||
use std::io::BufRead;
|
use std::io::BufRead;
|
||||||
let mut cursor = std::io::Cursor::new(content);
|
let mut cursor = std::io::Cursor::new(content);
|
||||||
|
@ -40,6 +40,13 @@ impl Shadow {
|
|||||||
pub fn get_password(&self) -> &str {
|
pub fn get_password(&self) -> &str {
|
||||||
&self.password.password
|
&self.password.password
|
||||||
}
|
}
|
||||||
|
pub fn remove_in(&self, content: &str) -> String {
|
||||||
|
content
|
||||||
|
.split(&self.source)
|
||||||
|
.map(|x| x.trim())
|
||||||
|
.collect::<Vec<&str>>()
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Shadow {
|
impl Display for Shadow {
|
||||||
|
@ -85,6 +85,7 @@ impl LockedFileGuard {
|
|||||||
self.file
|
self.file
|
||||||
.write_all(&new_content.into_bytes())
|
.write_all(&new_content.into_bytes())
|
||||||
.expect("Failed to write all users.");
|
.expect("Failed to write all users.");
|
||||||
|
let _ = self.file.write("\n".as_bytes());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
37
src/userlib/hashes.rs
Normal file
37
src/userlib/hashes.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#[allow(unused_imports)]
|
||||||
|
use log::{debug, error, info, trace, warn};
|
||||||
|
pub struct SourceHash {
|
||||||
|
hashvalue: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SourceHash {
|
||||||
|
pub fn new(src: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
hashvalue: src.to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn has_changed(&self, new: &str) -> bool {
|
||||||
|
trace!(
|
||||||
|
"Old and new lengths: {}, {}",
|
||||||
|
self.hashvalue.len(),
|
||||||
|
new.len()
|
||||||
|
);
|
||||||
|
!self.hashvalue.eq(new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Hashes {
|
||||||
|
pub passwd: SourceHash,
|
||||||
|
pub shadow: SourceHash,
|
||||||
|
pub group: SourceHash,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hashes {
|
||||||
|
pub fn new(passwd: &str, shadow: &str, group: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
passwd: SourceHash::new(passwd),
|
||||||
|
shadow: SourceHash::new(shadow),
|
||||||
|
group: SourceHash::new(group),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@
|
|||||||
#![allow(clippy::non_ascii_literal)]
|
#![allow(clippy::non_ascii_literal)]
|
||||||
|
|
||||||
pub mod files;
|
pub mod files;
|
||||||
|
pub mod hashes;
|
||||||
|
|
||||||
use crate::api::GroupRead;
|
use crate::api::GroupRead;
|
||||||
use crate::api::UserRead;
|
use crate::api::UserRead;
|
||||||
@ -19,7 +20,7 @@ use std::io::{BufReader, Read};
|
|||||||
|
|
||||||
pub struct UserDBLocal {
|
pub struct UserDBLocal {
|
||||||
source_files: files::Files,
|
source_files: files::Files,
|
||||||
source_hashes: Hashes, // to detect changes
|
source_hashes: hashes::Hashes, // to detect changes
|
||||||
pub users: HashMap<String, crate::User>,
|
pub users: HashMap<String, crate::User>,
|
||||||
pub groups: Vec<crate::Group>,
|
pub groups: Vec<crate::Group>,
|
||||||
}
|
}
|
||||||
@ -44,7 +45,7 @@ impl UserDBLocal {
|
|||||||
},
|
},
|
||||||
users,
|
users,
|
||||||
groups,
|
groups,
|
||||||
source_hashes: Hashes::new(&passwd_content, &shadow_content, &group_content),
|
source_hashes: hashes::Hashes::new(&passwd_content, &shadow_content, &group_content),
|
||||||
};
|
};
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
@ -71,7 +72,7 @@ impl UserDBLocal {
|
|||||||
source_files: files,
|
source_files: files,
|
||||||
users,
|
users,
|
||||||
groups: string_to(&my_group_lines),
|
groups: string_to(&my_group_lines),
|
||||||
source_hashes: Hashes::new(&my_passwd_lines, &my_shadow_lines, &my_group_lines),
|
source_hashes: hashes::Hashes::new(&my_passwd_lines, &my_shadow_lines, &my_group_lines),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,33 +98,60 @@ impl UserDBWrite for UserDBLocal {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let opened = self.source_files.lock_all_get();
|
let opened = self.source_files.lock_all_get();
|
||||||
let (mut locked_p, locked_s, locked_g) = opened.expect("failed to lock files!");
|
let (mut locked_p, mut locked_s, locked_g) = opened.expect("failed to lock files!");
|
||||||
|
|
||||||
// read the files to strings
|
// read the files to strings
|
||||||
let p = file_to_string(&locked_p.file)?;
|
let p = file_to_string(&locked_p.file)?;
|
||||||
let _s = file_to_string(&locked_s.file)?;
|
let s = file_to_string(&locked_s.file)?;
|
||||||
let _g = file_to_string(&locked_g.file)?;
|
let _g = file_to_string(&locked_g.file)?;
|
||||||
{
|
{
|
||||||
if self.source_hashes.passwd.has_changed(&p) {
|
let src = &self.source_hashes;
|
||||||
|
if src.passwd.has_changed(&p) | src.shadow.has_changed(&s) {
|
||||||
error!("The source files have changed. Deleting the user could corrupt the userdatabase. Aborting!");
|
error!("The source files have changed. Deleting the user could corrupt the userdatabase. Aborting!");
|
||||||
} else {
|
} else {
|
||||||
// create the new content of passwd
|
// create the new content of passwd
|
||||||
let modified = user.remove_in(&p);
|
let modified_p = user.remove_in(&p);
|
||||||
|
|
||||||
// write the new content to the file.
|
// write the new content to the file.
|
||||||
let ncont = locked_p.replace_contents(modified);
|
let ncont = locked_p.replace_contents(modified_p);
|
||||||
match ncont {
|
match ncont {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
let shad = user.get_shadow();
|
||||||
|
match shad {
|
||||||
|
Some(shadow) => {
|
||||||
|
let modified_s = shadow.remove_in(&s);
|
||||||
|
let ncont = locked_s.replace_contents(modified_s);
|
||||||
|
match ncont {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(e) => {
|
||||||
|
return Err(format!(
|
||||||
|
"Error during write to the database. \
|
||||||
|
Please doublecheck as the shadowdatabase could be corrupted: {}",
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
// Remove the user from the memory database(HashMap)
|
||||||
let res = self.users.remove(username);
|
let res = self.users.remove(username);
|
||||||
return Ok(res.unwrap());
|
return Ok(
|
||||||
|
res.expect("Failed to remove the user from the internal HashMap")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(e) => {
|
||||||
return Err("Error during write to the database. \
|
return Err(format!(
|
||||||
Please doublecheck as the userdatabase could be corrupted: {}"
|
"Error during write to the database. \
|
||||||
.into());
|
Please doublecheck as the userdatabase could be corrupted: {}",
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(format!("The user has been changed {}", username).into())
|
Err(format!("The userdatabase has been changed {}", username).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,42 +282,6 @@ impl UserDBValidation for UserDBLocal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SourceHash {
|
|
||||||
hashvalue: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SourceHash {
|
|
||||||
pub fn new(src: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
hashvalue: src.to_owned(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn has_changed(&self, new: &str) -> bool {
|
|
||||||
trace!(
|
|
||||||
"Old and new lengths: {}, {}",
|
|
||||||
self.hashvalue.len(),
|
|
||||||
new.len()
|
|
||||||
);
|
|
||||||
!self.hashvalue.eq(new)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Hashes {
|
|
||||||
pub passwd: SourceHash,
|
|
||||||
pub shadow: SourceHash,
|
|
||||||
pub group: SourceHash,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hashes {
|
|
||||||
pub fn new(passwd: &str, shadow: &str, group: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
passwd: SourceHash::new(passwd),
|
|
||||||
shadow: SourceHash::new(shadow),
|
|
||||||
group: SourceHash::new(group),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a file to a string
|
/// Parse a file to a string
|
||||||
fn file_to_string(file: &File) -> Result<String, crate::UserLibError> {
|
fn file_to_string(file: &File) -> Result<String, crate::UserLibError> {
|
||||||
let mut reader = BufReader::new(file);
|
let mut reader = BufReader::new(file);
|
||||||
|
Loading…
Reference in New Issue
Block a user