From be07298867c692c66cd38f5cf4763be7c77d5ab1 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 29 Apr 2026 06:22:20 +0900 Subject: [PATCH] fingerd: add raw user response variant --- src/proto/finger_protocol.rs | 66 +++++++++++++++++---------- src/server/fingerd/local_user_info.rs | 10 ++-- src/server/varlink_api.rs | 4 ++ 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/src/proto/finger_protocol.rs b/src/proto/finger_protocol.rs index 4d5a895..94b914d 100644 --- a/src/proto/finger_protocol.rs +++ b/src/proto/finger_protocol.rs @@ -214,7 +214,13 @@ fn parse_bsd_finger_time(time: &str) -> anyhow::Result> { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct FingerResponseUserEntry { +pub enum FingerResponseUserEntry { + Structured(Box), + Raw(String), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct FingerResponseStructuredUserEntry { /// The unix username of this user, as noted in passwd pub username: String, @@ -258,7 +264,7 @@ pub struct FingerResponseUserEntry { pub plan: Option, } -impl FingerResponseUserEntry { +impl FingerResponseStructuredUserEntry { #[allow(clippy::too_many_arguments)] pub fn new( username: String, @@ -736,9 +742,11 @@ mod tests { .trim(); let response = RawFingerResponse::from(response_content.to_string()); - let user_entry = - FingerResponseUserEntry::try_from_raw_finger_response(&response, "alice".to_string()) - .unwrap(); + let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response( + &response, + "alice".to_string(), + ) + .unwrap(); assert_eq!(user_entry.username, "alice"); assert_eq!(user_entry.full_name, "Alice Wonderland"); assert_eq!(user_entry.home_dir, PathBuf::from("/home/alice")); @@ -762,9 +770,11 @@ mod tests { .trim(); let response = RawFingerResponse::from(response_content.to_string()); - let user_entry = - FingerResponseUserEntry::try_from_raw_finger_response(&response, "alice".to_string()) - .unwrap(); + let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response( + &response, + "alice".to_string(), + ) + .unwrap(); assert_eq!(user_entry.office, Some("123 Main St".to_string())); assert_eq!(user_entry.office_phone, Some("012-345-6789".to_string())); @@ -786,9 +796,11 @@ mod tests { .trim(); let response = RawFingerResponse::from(response_content.to_string()); - let user_entry = - FingerResponseUserEntry::try_from_raw_finger_response(&response, "alice".to_string()) - .unwrap(); + let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response( + &response, + "alice".to_string(), + ) + .unwrap(); assert_eq!(user_entry.office, Some("123 Main St".to_string())); assert_eq!(user_entry.office_phone, Some("012-345-6789".to_string())); @@ -807,9 +819,11 @@ mod tests { .trim(); let response = RawFingerResponse::from(response_content.to_string()); - let user_entry = - FingerResponseUserEntry::try_from_raw_finger_response(&response, "bob".to_string()) - .unwrap(); + let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response( + &response, + "bob".to_string(), + ) + .unwrap(); assert!(user_entry.never_logged_in); assert!(user_entry.sessions.is_empty()); @@ -827,9 +841,11 @@ mod tests { .trim(); let response = RawFingerResponse::from(response_content.to_string()); - let user_entry = - FingerResponseUserEntry::try_from_raw_finger_response(&response, "bob".to_string()) - .unwrap(); + let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response( + &response, + "bob".to_string(), + ) + .unwrap(); assert_eq!(user_entry.mail_status, Some(MailStatus::NoMail)); } @@ -846,9 +862,11 @@ mod tests { .trim(); let response = RawFingerResponse::from(response_content.to_string()); - let user_entry = - FingerResponseUserEntry::try_from_raw_finger_response(&response, "bob".to_string()) - .unwrap(); + let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response( + &response, + "bob".to_string(), + ) + .unwrap(); assert_eq!( user_entry.mail_status, Some(MailStatus::NewMailReceived { @@ -870,9 +888,11 @@ mod tests { .trim(); let response = RawFingerResponse::from(response_content.to_string()); - let user_entry = - FingerResponseUserEntry::try_from_raw_finger_response(&response, "bob".to_string()) - .unwrap(); + let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response( + &response, + "bob".to_string(), + ) + .unwrap(); assert_eq!( user_entry.mail_status, Some(MailStatus::MailLastRead( diff --git a/src/server/fingerd/local_user_info.rs b/src/server/fingerd/local_user_info.rs index 2aeaf0e..387c15f 100644 --- a/src/server/fingerd/local_user_info.rs +++ b/src/server/fingerd/local_user_info.rs @@ -11,7 +11,7 @@ use users::all_users; use uucore::utmpx::{Utmpx, UtmpxRecord}; use crate::{ - proto::finger_protocol::{FingerResponseUserEntry, FingerResponseUserSession}, + proto::finger_protocol::{FingerResponseStructuredUserEntry, FingerResponseUserSession}, server::fingerd::{FingerRequestInfo, local_email}, }; @@ -20,7 +20,7 @@ pub fn search_for_user( search_string: &str, match_fullnames: bool, _request_info: &FingerRequestInfo, -) -> Vec> { +) -> Vec> { (unsafe { all_users() }) .filter_map(|user| { let user = match nix::unistd::User::from_uid(user.uid().into()) { @@ -69,7 +69,7 @@ pub fn search_for_user( /// Retrieve information about all users currently logged in, based on utmpx records. pub fn finger_utmp_users( _request_info: &FingerRequestInfo, -) -> Vec> { +) -> Vec> { Utmpx::iter_all_records() .filter(|entry| entry.is_user_process()) .into_group_map_by(|entry| entry.user()) @@ -113,7 +113,7 @@ fn read_file_content_if_exists(path: &Path) -> anyhow::Result> { fn get_local_user( username: &str, utmp_records: Option>, -) -> anyhow::Result> { +) -> anyhow::Result> { tracing::trace!( "Retrieving local user information for username: {}", username @@ -211,7 +211,7 @@ fn get_local_user( let plan_path = user_entry.dir.join(".plan"); let plan = read_file_content_if_exists(&plan_path)?; - Ok(Some(FingerResponseUserEntry::new( + Ok(Some(FingerResponseStructuredUserEntry::new( username, full_name, home_dir, diff --git a/src/server/varlink_api.rs b/src/server/varlink_api.rs index 088bd2a..c984dfc 100644 --- a/src/server/varlink_api.rs +++ b/src/server/varlink_api.rs @@ -204,6 +204,8 @@ impl VarlinkRoowhoo2ClientServer { None } }) + .map(Box::new) + .map(FingerResponseUserEntry::Structured) .collect(), None => finger_utmp_users(&request_info) .into_iter() @@ -214,6 +216,8 @@ impl VarlinkRoowhoo2ClientServer { None } }) + .map(Box::new) + .map(FingerResponseUserEntry::Structured) .collect(), } }