diff --git a/src/bin/finger.rs b/src/bin/finger.rs index 552e469..f6a6fd9 100644 --- a/src/bin/finger.rs +++ b/src/bin/finger.rs @@ -1,7 +1,10 @@ use anyhow::Context; use clap::{CommandFactory, Parser, builder::ArgPredicate}; use clap_complete::{Shell, generate}; -use roowho2_lib::server::varlink_api::VarlinkFingerClientProxy; +use roowho2_lib::server::{ + fingerd::{FingerRequestInfo, FingerRequestNetworking}, + varlink_api::VarlinkFingerClientProxy, +}; /// User information lookup program /// @@ -122,6 +125,32 @@ pub struct Args { users: Option>, } +fn determine_request_info(args: &Args) -> FingerRequestInfo { + if args.long { + FingerRequestInfo::Long { + prevent_files: args.prevent_files, + } + } else { + debug_assert!( + args.short, + "Either short or long output format must be selected" + ); + debug_assert!( + !args.host || !args.office, + "Host and office options cannot both be enabled for short output format" + ); + if args.host { + FingerRequestInfo::ShortHost { + restrict_gecos: args.gecos, + } + } else { + FingerRequestInfo::ShortOffice { + restrict_gecos: args.gecos, + } + } + } +} + #[tokio::main] async fn main() -> anyhow::Result<()> { let args = Args::parse(); @@ -140,8 +169,21 @@ async fn main() -> anyhow::Result<()> { .await .expect("Failed to connect to fingerd server"); + let request_info = determine_request_info(&args); + let request_networking = match (args.ipv4, args.ipv6) { + (true, false) => FingerRequestNetworking::IPv4Only, + (false, true) => FingerRequestNetworking::IPv6Only, + _ => FingerRequestNetworking::Any, + }; + let reply = conn - .finger(args.users) + .finger( + args.users, + !args.no_name_match, + request_info, + request_networking, + args.no_acct, + ) .await .context("Failed to send finger request")? .map_err(|e| anyhow::anyhow!("Server returned an error for finger request: {:?}", e))?; diff --git a/src/server/fingerd.rs b/src/server/fingerd.rs index 06c15da..cb8dd3e 100644 --- a/src/server/fingerd.rs +++ b/src/server/fingerd.rs @@ -6,15 +6,37 @@ use std::{ use chrono::{DateTime, Duration, Timelike, Utc}; use nix::sys::stat::stat; +use serde::{Deserialize, Serialize}; use users::all_users; use uucore::utmpx::Utmpx; use crate::proto::finger_protocol::{FingerResponseUserEntry, FingerResponseUserSession}; +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum FingerRequestNetworking { + Any, + IPv4Only, + IPv6Only, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum FingerRequestInfo { + ShortHost { + restrict_gecos: bool, + }, + ShortOffice { + restrict_gecos: bool, + }, + Long { + prevent_files: bool, + }, +} + /// Search for users whose username or full name contains the search string. pub fn search_for_user( search_string: &str, - dont_search_fullnames: bool, + match_fullnames: bool, + _request_info: &FingerRequestInfo, ) -> Vec> { (unsafe { all_users() }) .filter_map(|user| { @@ -42,7 +64,7 @@ pub fn search_for_user( .to_string(); let matches_username = username.contains(search_string); - let matches_fullname = !dont_search_fullnames && full_name.contains(search_string); + let matches_fullname = match_fullnames && full_name.contains(search_string); if matches_username || matches_fullname { match get_local_user(&username) { Ok(Some(user_entry)) => Some(Ok(user_entry)), diff --git a/src/server/varlink_api.rs b/src/server/varlink_api.rs index a55a076..b6f0d0e 100644 --- a/src/server/varlink_api.rs +++ b/src/server/varlink_api.rs @@ -7,7 +7,7 @@ use zlink::{ReplyError, service::MethodReply}; use crate::{ proto::{WhodStatusUpdate, WhodUserEntry, finger_protocol::FingerResponseUserEntry}, server::{ - fingerd::{self}, + fingerd::{self, FingerRequestInfo, FingerRequestNetworking}, rwhod::RwhodStatusStore, }, }; @@ -62,6 +62,10 @@ pub trait VarlinkFingerClientProxy { async fn finger( &mut self, user_queries: Option>, + match_fullnames: bool, + request_info: FingerRequestInfo, + request_networking: FingerRequestNetworking, + disable_user_account_db: bool, ) -> zlink::Result>; } @@ -69,7 +73,13 @@ pub trait VarlinkFingerClientProxy { #[serde(tag = "method", content = "parameters")] pub enum VarlinkFingerClientRequest { #[serde(rename = "no.ntnu.pvv.roowho2.finger.Finger")] - Finger { user_queries: Option> }, + Finger { + user_queries: Option>, + match_fullnames: bool, + request_info: FingerRequestInfo, + request_networking: FingerRequestNetworking, + disable_user_account_db: bool, + }, } #[derive(Debug, Serialize)] @@ -150,13 +160,17 @@ impl VarlinkRoowhoo2ClientServer { async fn handle_finger_request( &self, user_queries: Option>, + match_fullnames: bool, + request_info: FingerRequestInfo, + _request_networking: FingerRequestNetworking, + _disable_user_account_db: bool, ) -> VarlinkFingerResponse { match user_queries { // TODO: deduplicate results Some(usernames) => usernames .into_iter() .flat_map::, _>(|username| { - fingerd::search_for_user(&username, false) + fingerd::search_for_user(&username, match_fullnames, &request_info) .into_iter() .map(|res| (username.clone(), res)) .collect() @@ -211,10 +225,23 @@ impl zlink::Service for VarlinkRoowhoo2ClientServer { ))), Default::default(), ), - VarlinkMethod::Finger(VarlinkFingerClientRequest::Finger { user_queries }) => ( + VarlinkMethod::Finger(VarlinkFingerClientRequest::Finger { + user_queries, + match_fullnames, + request_info, + request_networking, + disable_user_account_db, + }) => ( MethodReply::Single(Some(VarlinkReply::Finger( VarlinkFingerClientResponse::Finger( - self.handle_finger_request(user_queries.clone()).await, + self.handle_finger_request( + user_queries.clone(), + *match_fullnames, + request_info.clone(), + request_networking.clone(), + *disable_user_account_db, + ) + .await, ), ))), Default::default(),