From 29c1c5af5cde5236a215e6b2692a48666c1f544f Mon Sep 17 00:00:00 2001 From: mux Date: Fri, 8 Aug 2025 04:47:10 +0200 Subject: [PATCH] get all socket info gehtamal --- src/main.rs | 52 ++++++++++++++++-- src/socket.rs | 149 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 169 insertions(+), 32 deletions(-) diff --git a/src/main.rs b/src/main.rs index 698d350..de3763d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,13 +3,14 @@ use std::collections::HashSet; use std::fs; use std::fs::read_to_string; use std::os::unix::fs::MetadataExt; +use crate::socket::socket::Id; type inode = u64; type pid = u64; mod socket; -fn get_socket_inodes_by_pid(pid : u64, socket_patt : Regex) -> Vec { +fn get_socket_inodes_by_pid(pid : u64, socket_patt : &Regex) -> Vec { let mut inodes : Vec = Vec::::new(); let mut path = String::from("/proc/"); path.push_str(&pid.to_string()); @@ -20,7 +21,7 @@ fn get_socket_inodes_by_pid(pid : u64, socket_patt : Regex) -> Vec { Ok(fd) => { let name = fs::read_link(fd.path()).unwrap(); let name2 = name.file_name().unwrap().to_str().unwrap(); - if (socket_patt.is_match(name2)){ + if socket_patt.is_match(name2) { inodes.push(socket_patt.captures(name2).unwrap().get(1).unwrap().as_str().parse::().unwrap()) } }, @@ -30,7 +31,18 @@ fn get_socket_inodes_by_pid(pid : u64, socket_patt : Regex) -> Vec { inodes } -fn get_readable_proc_pids(pid_pattern : Regex) -> Vec { +fn get_tcp_file_by_pid(pid_pattern : &Regex, pid: pid) -> String { + let mut path = String::from("/proc/"); + path.push_str(&pid.to_string()); + path.push_str("/net/tcp"); + fs::read_to_string(path).unwrap().lines().skip(1).map(|x| x.to_owned()).collect::>().join("\n") +} + +fn parse_tcp_file_line(line : String) -> socket::socket::Socket { + socket::socket::Socket::new(socket::socket::Peer::build_from_hex(&get_index(line.clone(),1)), socket::socket::Peer::build_from_hex(&get_index(line.clone(),2)), Vec::::new(), socket::socket::SocketState::new(socket::socket::Peer::convert_port_hex_dec(&get_index(line.clone(), 3))), socket::socket::Id::create_def(), socket::socket::Id::create_def(), get_index(line, 9).parse().unwrap()) +} + +fn get_readable_proc_pids(pid_pattern : &Regex) -> Vec { let mut pids = Vec::::new(); let dirs = fs::read_dir("/proc/").expect("proc kann nicht gelesen werden, Berechtigung?"); for dir in dirs { @@ -49,6 +61,34 @@ fn get_readable_proc_pids(pid_pattern : Regex) -> Vec { pids } +fn get_uid_guid_by_pid(pid : pid) -> (socket::socket::Id,socket::socket::Id) { + let mut uid : Id; + let mut gid : Id; + let mut status_path = String::from("/proc/"); + status_path.push_str(&pid.to_string()); + status_path.push_str("/status"); + let status_file = fs::read_to_string(status_path).unwrap(); + let mut iter = status_file.lines(); + let uid_str = iter.find(|x| x.starts_with("Uid:")).unwrap().to_owned(); + let gid_str = iter.find(|x| x.starts_with("Gid:")).unwrap().to_owned(); + (Id::new(get_index(uid_str.clone(), 1).parse().unwrap(), get_index(uid_str.clone(), 2).parse().unwrap(), + get_index(uid_str.clone(), 3).parse().unwrap(), get_index(uid_str, 4).parse().unwrap()), + Id::new(get_index(gid_str.clone(), 1).parse().unwrap(), get_index(gid_str.clone(), 2).parse().unwrap(), + get_index(gid_str.clone(), 3).parse().unwrap(), get_index(gid_str, 4).parse().unwrap())) + +} + +fn get_all_tcp_sockets(pid_pattern : &Regex, socket_patt : &Regex) -> HashSet { + let mut sockets = HashSet::::new(); + let pids = get_readable_proc_pids(pid_pattern); + pids.iter().for_each(|x| { + get_tcp_file_by_pid(&pid_pattern.clone(), *x).lines().for_each(|y| { + sockets.insert(parse_tcp_file_line(y.to_owned())); + }) + }); + sockets +} + fn get_socket_info() -> Vec { let mut sockets = Vec::::new(); sockets @@ -64,7 +104,7 @@ fn get_remote_port() {} fn main() { let socket_patt : Regex = Regex::new(r"socket:\[([0-9]+)\]").expect("kannst kein regex?? xd"); let pid_pattern = Regex::new(r"^[1-4]?[0-9]{1,6}$").expect("kannst kein regex??"); - let mut socket_infos : Vec; - println!("{:?}", get_socket_inodes_by_pid(55238, socket_patt)); - println!("{:?}", get_readable_proc_pids(pid_pattern)); + let sockets = get_all_tcp_sockets(&pid_pattern, &socket_patt); + println!("{:?}", sockets); + println!("{}", sockets.len()); } diff --git a/src/socket.rs b/src/socket.rs index 1f5d1cc..2f7532e 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -1,10 +1,12 @@ pub mod socket { - + use std::cmp::PartialEq; use regex::Regex; use std::collections::HashSet; + use std::fmt::Display; use std::fs; use std::fs::read_to_string; + use std::hash::{Hash, Hasher}; use std::os::unix::fs::MetadataExt; #[derive(PartialEq)] @@ -14,6 +16,29 @@ pub mod socket { pub ip_address: String, pub port: usize, } + #[derive(PartialEq)] + #[derive(Clone)] + #[derive(Debug)] + pub struct Id { + pub real : usize, + pub effective : usize, + pub saved_set : usize, + pub fs : usize, + } + + impl Id { + pub fn new(real : usize, effective : usize, saved_set : usize, fs : usize) -> Id { + Id { + real, + effective, + saved_set, + fs, + } + } + pub fn create_def() -> Id { + Id::new(0,0,0,0) + } + } impl Peer { fn new() -> Peer { @@ -23,7 +48,10 @@ pub mod socket { } } - pub fn build_from_hex(hex_ip: &str, hex_port: &str) -> Peer { + pub fn build_from_hex(hex_peer : &str) -> Peer { + let mut split = hex_peer.split(":"); + let hex_ip = split.nth(0).unwrap(); + let hex_port = split.nth(0).unwrap(); Peer { ip_address: Self::convert_ip_hex_dec(hex_ip), port: Self::convert_port_hex_dec(hex_port), @@ -54,46 +82,109 @@ pub mod socket { .join(".") } - fn convert_port_hex_dec(port: &str) -> usize { + pub fn convert_port_hex_dec(port: &str) -> usize { usize::from_str_radix(port, 16).expect("upsi 3") } } #[derive(PartialEq)] #[derive(Clone)] + #[derive(Debug)] pub enum SocketState{ - Listening, Established, - Closed + SYN_Sent, + SYN_Recv, + FIN_Wait1, + FIN_Wait2, + TIME_Wait, + Close, + Close_Wait, + Last_ACK, + Listening, + Closing, + New_SYN_Recv, + Bound_Inactive, + Max_States, + Undefined, } - #[derive(PartialEq)] - #[derive(Clone)] + impl SocketState { + pub fn new(index : usize) -> SocketState { + match index { + 1 => SocketState::Established, + 2 => SocketState::SYN_Sent, + 3 => SocketState::SYN_Recv, + 4 => SocketState::FIN_Wait1, + 5 => SocketState::FIN_Wait2, + 6 => SocketState::TIME_Wait, + 7 => SocketState::Close, + 8 => SocketState::Close_Wait, + 9 => SocketState::Last_ACK, + 10 => SocketState::Listening, + 11 => SocketState::Closing, + 12 => SocketState::New_SYN_Recv, + 13 => SocketState::Bound_Inactive, + 14 => SocketState::Max_States, + _ => SocketState::Undefined, + } + } + + pub fn to_string(&self) -> String { + match self { + SocketState::Established => String::from("Established"), + SocketState::SYN_Sent => String::from("SYN_Sent"), + SocketState::SYN_Recv => String::from("SYN_Recv"), + SocketState::FIN_Wait1 => String::from("FIN_Wait1"), + SocketState::FIN_Wait2 => String::from("FIN_Wait2"), + SocketState::TIME_Wait => String::from("TIME_Wait"), + SocketState::Close => String::from("Close"), + SocketState::Close_Wait => String::from("Close_Wait"), + SocketState::Last_ACK => String::from("Last_ACK"), + SocketState::Listening => String::from("Listening"), + SocketState::Closing => String::from("Closing"), + SocketState::New_SYN_Recv => String::from("New_SYN_Recv"), + SocketState::Bound_Inactive => String::from("Bound_Inactive"), + SocketState::Max_States => String::from("Max_States"), + SocketState::Undefined => String::from("Undefined"), + } + } + } + + impl PartialEq for Socket { + fn eq(&self, other: &Self) -> bool { + return self.inode == other.inode; + } + } + + impl Eq for Socket {} + + impl Hash for Socket { + fn hash(&self, state: &mut H) -> (){ + let mut state = self.inode * 31; + state = state + 11; + } + } + + #[derive(Clone, Debug)] pub struct Socket { peer_loc: Peer, peer_rem: Peer, pids: Vec, state : SocketState, - user : String, - group : String, + user : Id, + group : Id, inode : u64 } impl Socket { - pub fn new(ip_loc: &str, port_loc: usize, ip_rem: &str, port_rem: usize, pids : Vec, state : SocketState, user : &str, group : &str, inode : u64) -> Socket { + pub fn new(peer_loc : Peer, peer_rem : Peer, pids : Vec, state : SocketState, user : Id, group : Id, inode : u64) -> Socket { Socket { - peer_loc: Peer { - ip_address: ip_loc.to_string(), - port: port_loc, - }, - peer_rem: Peer { - ip_address: ip_rem.to_string(), - port: port_rem, - }, + peer_loc, + peer_rem, pids, state, - user : user.to_string(), - group : group.to_string(), + user, + group, inode, } } @@ -186,17 +277,23 @@ mod tests { fn init_sockets() -> Vec { let mut sockets = Vec::::new(); - sockets.push(socket::Socket::new("93.83.160.12", 21345, "0.0.0.0", 0, Vec::::new(), socket::SocketState::Listening, "root", "root", 123123)); - sockets.push(socket::Socket::new("195.201.90.97", 8843, "0.0.0.0", 443, Vec::::new(), socket::SocketState::Established, "apache", "apache", 218389)); - sockets.push(socket::Socket::new("255.255.255.255", 193193, "0.0.0.0", 8080, Vec::::new(), socket::SocketState::Listening, "node", "node", 1301011)); + let root_uid = socket::Id::new(0,0,0,0); + let root_gid = root_uid.clone(); + let mux_uid = socket::Id::new(1000,1000,1000,1000); + let mux_gid = mux_uid.clone(); + let sudo_mux_uid = socket::Id::new(1000,0,0,0); + let sudo_mux_gid = root_gid.clone(); + // sockets.push(socket::Socket::new("93.83.160.12", 21345, "0.0.0.0", 0, Vec::::new(), socket::SocketState::Listening, root_uid, root_gid, 123123)); + // sockets.push(socket::Socket::new("195.201.90.97", 8843, "0.0.0.0", 443, Vec::::new(), socket::SocketState::Established, mux_uid, mux_gid, 218389)); + // sockets.push(socket::Socket::new("255.255.255.255", 193193, "0.0.0.0", 8080, Vec::::new(), socket::SocketState::Listening, sudo_mux_uid, sudo_mux_gid, 1301011)); sockets } #[test] fn test_build_from_hex() -> () { let hex_val = "0100007F"; - assert_eq!(socket::Peer::build_from_hex("0100007F", "F168"), socket::Peer { ip_address: "127.0.0.1".to_owned(), port: 61800 }); - assert_eq!(socket::Peer::build_from_hex("980FB23E", "ACCE"), socket::Peer { ip_address: "62.178.15.152".to_owned(), port: 44238 }); - assert_eq!(socket::Peer::build_from_hex("00000000", "30C8"), socket::Peer { ip_address: "0.0.0.0".to_owned(), port: 12488 }); + assert_eq!(socket::Peer::build_from_hex("0100007F:F168"), socket::Peer { ip_address: "127.0.0.1".to_owned(), port: 61800 }); + assert_eq!(socket::Peer::build_from_hex("980FB23E:ACCE"), socket::Peer { ip_address: "62.178.15.152".to_owned(), port: 44238 }); + assert_eq!(socket::Peer::build_from_hex("00000000:30C8"), socket::Peer { ip_address: "0.0.0.0".to_owned(), port: 12488 }); } #[test] fn test_to_string() -> () {