Skip to content

Commit

Permalink
Merge pull request #539 from 7flying/rm-shadow-passwd
Browse files Browse the repository at this point in the history
feat: replace shadow and passwd crates with our built-in functions
  • Loading branch information
mergify[bot] authored Jul 27, 2023
2 parents ab7acf5 + 10dc523 commit ccc719b
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 50 deletions.
21 changes: 0 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion client-linuxapp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ log = "0.4"
tokio = { version = "1", features = ["full"] }
sys-info = "0.9"
serde_bytes = "0.11"
passwd = "0.0.1"
rand = "0.8.4"
nix = "0.26"
uuid = "1.3"
Expand Down
23 changes: 11 additions & 12 deletions client-linuxapp/src/serviceinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use fdo_data_formats::{
types::{CborSimpleTypeExt, Hash, ServiceInfo},
};
use fdo_http_wrapper::client::{RequestResult, ServiceClient};
use fdo_util::passwd_shadow;

const MAX_SERVICE_INFO_LOOPS: u32 = 1000;

Expand Down Expand Up @@ -56,8 +57,7 @@ fn set_perm_mode(path: &Path, mode: u32) -> Result<()> {

fn create_user(user: &str) -> Result<()> {
// Checks if user already present
let user_info = passwd::Passwd::from_name(user);
if user_info.is_some() {
if passwd_shadow::is_user_in_passwd(user)? {
log::info!("User: {user} already present");
return Ok(());
}
Expand Down Expand Up @@ -99,8 +99,7 @@ fn is_password_encrypted(s: &str) -> bool {

fn create_user_with_password(user: &str, password: &str) -> Result<()> {
// Checks if user already present
let user_info = passwd::Passwd::from_name(user);
if user_info.is_some() {
if passwd_shadow::is_user_in_passwd(user)? {
log::info!("User {user} is already present");
return Ok(());
}
Expand Down Expand Up @@ -151,17 +150,17 @@ fn create_user_with_password(user: &str, password: &str) -> Result<()> {
}

fn install_ssh_key(user: &str, key: &str) -> Result<()> {
let user_info = passwd::Passwd::from_name(user);
if user_info.is_none() {
bail!("User {} for SSH key installation missing", user);
}
let user_info = user_info.unwrap();
let uid = nix::unistd::Uid::from_raw(user_info.uid);
let gid = nix::unistd::Gid::from_raw(user_info.gid);
let (uid, gid, home) = match passwd_shadow::get_user_uid_gid_home(user) {
Ok((uid, gid, home)) => (uid, gid, home),
Err(e) => bail!(e),
};

let uid = nix::unistd::Uid::from(uid);
let gid = nix::unistd::Gid::from(gid);
let key_path = if let Ok(val) = env::var("SSH_KEY_PATH") {
PathBuf::from(&val)
} else {
let ssh_dir = Path::new(&user_info.home_dir).join(".ssh");
let ssh_dir = Path::new(&home).join(".ssh");
if !ssh_dir.exists() {
log::debug!("Creating SSH directory at {}", ssh_dir.display());
fs::create_dir(&ssh_dir).context("Error creating SSH key directory")?;
Expand Down
2 changes: 0 additions & 2 deletions integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ serde_cbor = "0.11"
serde_json = "1.0"
pretty_assertions = "1.0.0"
paste = "1.0"
passwd = "0.0.1"
shadow = "0.0.1"
pem = "2.0"
users = "0.11.0"

Expand Down
18 changes: 11 additions & 7 deletions integration-tests/tests/e2e.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod common;
use fdo_util::passwd_shadow;
use std::env;
use std::{fs, io::Write, process::Command, time::Duration};

Expand Down Expand Up @@ -401,17 +402,20 @@ ssh-ed25519 sshkey_default [email protected]
if ci {
L.l("Running create initial user validation");
pretty_assertions::assert_eq!(
passwd::Passwd::from_name(new_user).is_some(),
passwd_shadow::is_user_in_passwd(new_user)?,
true,
"User: {} is not created during onboarding",
&new_user
);
if let Some(test_user) = shadow::Shadow::from_name(new_user) {
pretty_assertions::assert_eq!(
test_user.password.is_empty(),
false,
"Password not created during onboarding"
);
match passwd_shadow::get_user_passwd(new_user) {
Ok(pass) => {
pretty_assertions::assert_eq!(
pass.is_empty(),
false,
"Password not created during onboarding"
);
}
Err(e) => bail!(e),
}
} else {
L.l("Skipped create initial user validation
Expand Down
19 changes: 12 additions & 7 deletions integration-tests/tests/service_info.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod common;
use fdo_util::passwd_shadow;
use std::env;
#[allow(unused_imports)]
use std::{fs, io::Write, process::Command, time::Duration};
Expand Down Expand Up @@ -280,17 +281,21 @@ ssh-ed25519 sshkey_default [email protected]
if ci {
L.l("Running create initial user validation");
pretty_assertions::assert_eq!(
passwd::Passwd::from_name(new_user).is_some(),
passwd_shadow::is_user_in_passwd(new_user)?,
true,
"User: {} is not created during onboarding",
&new_user
);
if let Some(test_user) = shadow::Shadow::from_name(new_user) {
pretty_assertions::assert_eq!(
test_user.password.is_empty(),
false,
"Password not created during onboarding"
);

match passwd_shadow::get_user_passwd(new_user) {
Ok(pass) => {
pretty_assertions::assert_eq!(
pass.is_empty(),
false,
"Password not created during onboarding"
);
}
Err(e) => bail!(e),
}
} else {
L.l("Skipped create initial user validation
Expand Down
1 change: 1 addition & 0 deletions util/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod device_credential_locations;
pub mod device_identification;
pub mod passwd_shadow;
pub mod servers;

pub fn maybe_print_version(
Expand Down
42 changes: 42 additions & 0 deletions util/src/passwd_shadow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use anyhow::{bail, Result};
use std::fs;

/// Checks whether an entry for the given user name 'username' exists in
/// /etc/passwd
pub fn is_user_in_passwd(username: &str) -> Result<bool> {
for line in fs::read_to_string("/etc/passwd")?.lines() {
let contents: Vec<&str> = line.split(':').collect();
if !contents.is_empty() && contents[0] == username {
return Ok(true);
}
}
Ok(false)
}

/// Returns the uid, gid and home of the given user or Error if user does not
/// exist in /etc/passwd.
pub fn get_user_uid_gid_home(username: &str) -> Result<(u32, u32, String)> {
for line in fs::read_to_string("/etc/passwd")?.lines() {
let contents: Vec<&str> = line.split(':').collect();
if !contents.is_empty() && contents[0] == username {
return Ok((
contents[2].parse::<u32>()?,
contents[3].parse::<u32>()?,
contents[5].to_string(),
));
}
}
bail!("User {username} not found")
}

/// Returns the password of a given user. Errors if the user does not exist
/// in /etc/shadow.
pub fn get_user_passwd(username: &str) -> Result<String> {
for line in fs::read_to_string("/etc/shadow")?.lines() {
let contents: Vec<&str> = line.split(':').collect();
if !contents.is_empty() && contents[0] == username {
return Ok(contents[1].to_string());
}
}
bail!("User {username} not found")
}

0 comments on commit ccc719b

Please sign in to comment.