From c5f2c58f5855f359d8b30674c01d01e1889002ea Mon Sep 17 00:00:00 2001 From: Luca BRUNO Date: Wed, 17 Mar 2021 18:22:02 +0000 Subject: [PATCH] rust/treefile: tweak check-passwd/check-groups data This tweaks the data and types parsed from `check-passwd` and `check-groups`, so that it can be more easily iterated and consumed by passwd-handling logic. --- rust/src/treefile.rs | 60 +++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/rust/src/treefile.rs b/rust/src/treefile.rs index cc4273d0..5ecd6550 100644 --- a/rust/src/treefile.rs +++ b/rust/src/treefile.rs @@ -22,6 +22,7 @@ use crate::cxxrsutil::*; use anyhow::{anyhow, bail, Result}; use c_utf8::CUtf8Buf; +use nix::unistd::{Gid, Uid}; use openat_ext::OpenatDirExt; use serde_derive::{Deserialize, Serialize}; use std::collections::btree_map::Entry; @@ -760,7 +761,7 @@ impl TreefileExternals { let group_file = self .group .as_mut() - .ok_or_else(|| anyhow::anyhow!("missing passwd file"))?; + .ok_or_else(|| anyhow::anyhow!("missing group file"))?; group_file.seek(io::SeekFrom::Start(0))?; Ok(group_file) } @@ -865,7 +866,7 @@ pub(crate) struct CheckFile { #[derive(Serialize, Deserialize, Debug, PartialEq)] pub(crate) struct CheckGroupsData { - entries: HashMap, + pub(crate) entries: BTreeMap, } #[derive(Serialize, Deserialize, Debug, PartialEq)] @@ -883,31 +884,43 @@ pub(crate) enum CheckPasswd { #[derive(Serialize, Deserialize, Debug, PartialEq)] pub(crate) struct CheckPasswdData { - entries: HashMap, + pub(crate) entries: BTreeMap, } #[derive(Serialize, Deserialize, Debug, PartialEq)] #[serde(untagged)] pub(crate) enum CheckPasswdDataEntries { - IdValue(u64), - IdTuple([u64; 1]), - UidGid((u64, u64)), + IdValue(u32), + IdTuple([u32; 1]), + UidGid((u32, u32)), } -impl From for CheckPasswdDataEntries { - fn from(item: u64) -> Self { +impl CheckPasswdDataEntries { + /// Return IDs for user and group. + pub fn ids(&self) -> (Uid, Gid) { + let (user, group) = match self { + CheckPasswdDataEntries::IdValue(v) => (*v, *v), + CheckPasswdDataEntries::IdTuple([v]) => (*v, *v), + CheckPasswdDataEntries::UidGid(v) => *v, + }; + (Uid::from_raw(user), Gid::from_raw(group)) + } +} + +impl From for CheckPasswdDataEntries { + fn from(item: u32) -> Self { Self::IdValue(item) } } -impl From<[u64; 1]> for CheckPasswdDataEntries { - fn from(item: [u64; 1]) -> Self { +impl From<[u32; 1]> for CheckPasswdDataEntries { + fn from(item: [u32; 1]) -> Self { Self::IdTuple(item) } } -impl From<(u64, u64)> for CheckPasswdDataEntries { - fn from(item: (u64, u64)) -> Self { +impl From<(u32, u32)> for CheckPasswdDataEntries { + fn from(item: (u32, u32)) -> Self { Self::UidGid(item) } } @@ -1645,16 +1658,27 @@ etc-group-members: let workdir = tempfile::tempdir().unwrap(); let tf = new_test_treefile(workdir.path(), &input, None).unwrap(); let custom_cfg = tf.parsed.get_check_passwd(); + let data = match custom_cfg { + CheckPasswd::Data(ref v) => v, + x => panic!("unexpected variant {:?}", x), + }; assert_eq!( - custom_cfg, - &CheckPasswd::Data(CheckPasswdData { - entries: maplit::hashmap!( - "bin".into() => 1.into(), + data, + &CheckPasswdData { + entries: maplit::btreemap!( "adm".into() => (3, 4).into(), + "bin".into() => 1.into(), "foo".into() => [2].into(), ), - }) + } ); + let ids: Vec<_> = data.entries.iter().map(|(_k, v)| v.ids()).collect(); + let expected = vec![ + (Uid::from_raw(3), Gid::from_raw(4)), + (Uid::from_raw(1), Gid::from_raw(1)), + (Uid::from_raw(2), Gid::from_raw(2)), + ]; + assert_eq!(ids, expected); } { let input = VALID_PRELUDE.to_string() @@ -1699,7 +1723,7 @@ etc-group-members: assert_eq!( custom_cfg, &CheckGroups::Data(CheckGroupsData { - entries: maplit::hashmap!( + entries: maplit::btreemap!( "bin".into() => 1, ), })