dashboard/src/main.rs

231 lines
11 KiB
Rust

use regex::Regex;
use std::collections::HashSet;
use std::fmt::{Display, Formatter, Write};
use std::{fmt, fs};
use std::fs::{read_to_string, ReadDir};
use std::path::PathBuf;
use crate::socket::socket::{pids_to_string, Id, Tcp_Socket};
type inode = u64;
type pid = u64;
type pids = HashSet<pid>;
mod socket;
fn get_socket_inodes_by_pid(pid : u64, socket_patt : &Regex) -> HashSet<inode> {
let mut inodes = HashSet::<inode>::new();
let mut path = String::from("/proc/");
path.push_str(&pid.to_string());
path.push_str("/fd/");
let mut contents: ReadDir;
match fs::read_dir(path) {
Ok(dir) => {
contents = dir;
},
Err(_) => return HashSet::<inode>::new()
};
for fd in contents {
match fd {
Ok(fd) => {
let path_name = fs::read_link(fd.path());
let mut name : PathBuf;
match path_name {
Ok(link) => name = link,
Err(_) => continue,
}
let name2 = name.file_name().unwrap().to_str().unwrap();
if socket_patt.is_match(name2) {
inodes.insert(socket_patt.captures(name2).unwrap().get(1).unwrap().as_str().parse::<u64>().unwrap());
}
},
Err(_) => continue,
}
}
inodes
}
fn get_socket_by_inode(sockets : &HashSet<Tcp_Socket>, inode : u64) -> Option<Tcp_Socket> {
sockets.clone().iter().map(|x| x.to_owned()).find(|x|x.inode == inode)
}
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::<Vec<String>>().join("\n")
}
fn parse_tcp_file_line(line : String) -> socket::socket::Tcp_Socket {
socket::socket::Tcp_Socket::new(socket::socket::Peer::build_from_hex(&get_index(&line.clone(),1)), socket::socket::Peer::build_from_hex(&get_index(&line.clone(),2)), HashSet::<u64>::new(), socket::socket::Tcp_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<pid> {
let mut pids = Vec::<pid>::new();
let dirs = fs::read_dir("/proc/").expect("proc kann nicht gelesen werden, Berechtigung?");
for dir in dirs {
match dir {
Ok(dir) => {
let name = dir.file_name().into_string().unwrap();
if !pid_pattern.is_match(&name) {
continue;
}
pids.push(name.parse().unwrap())
},
Err(_) => continue
};
}
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 add_pid_to_tcp_sockets(sockets : &mut Vec<Tcp_Socket>, inodes : HashSet<inode>, pid : pid) -> (){
let s2 = sockets.clone();
for (i, v) in s2.iter().enumerate(){
if inodes.contains(&v.inode) {
sockets.get_mut(i).unwrap().pids.insert(pid);
}
}
}
pub fn format_output(combination : socket::socket::Combination, sockets : &Vec<Tcp_Socket>) -> String{
let header_loc_ip = "Local Address";
let header_loc_port = "Port";
let header_rem_ip = "Remote Address";
let header_state = "State";
let header_rem_port = header_loc_port;
let header_uid_real = "real-uid";
let header_uid_eff = "effective-uid";
let header_gid_real = "real-gid";
let header_gid_eff = "effective-gid";
let header_pids = "PIDs";
let mut ret_str = String::from("");
let mut max_loc_ip_len = header_loc_ip.len();
let mut max_loc_port_len = header_loc_port.len();
let mut max_rem_ip_len = header_rem_ip.len();
let mut max_rem_port_len = max_loc_port_len;
let mut max_state_len = header_state.len();
let mut max_real_uid_len = header_uid_real.len();
let mut max_eff_uid_len = header_uid_eff.len();
let mut max_real_gid_len = header_gid_real.len();
let mut max_eff_gid_len = header_gid_eff.len();
let mut max_pids_len = header_pids.len();
sockets.clone().iter().for_each(|x| {
let curr_loc_ip_len = x.get_loc_ip_string().len();
let curr_loc_port_len = x.get_loc_port_string().len();
let curr_rem_ip_len = x.get_rem_ip_string().len();
let curr_rem_port_len = x.get_rem_port_string().len();
let curr_state_len = x.get_state().to_string().len();
let (curr_real_uid,curr_eff_uid) = x.get_real_eff_uid_string();
let curr_real_uid_len = curr_real_uid.len();
let curr_eff_uid_len = curr_eff_uid.len();
let (curr_real_gid, curr_eff_gid) = x.get_real_eff_gid_String();
let curr_real_gid_len = curr_real_gid.len();
let curr_eff_gid_len = curr_eff_gid.len();
let curr_pids_len = pids_to_string(&x.pids).len();
max_loc_ip_len = if (curr_loc_ip_len > max_loc_ip_len) { curr_loc_ip_len } else { max_loc_ip_len };
max_loc_port_len = if (curr_loc_port_len > max_loc_port_len) { curr_loc_port_len } else { max_loc_port_len };
max_rem_ip_len = if (curr_rem_ip_len > max_rem_ip_len) { curr_rem_ip_len } else { max_rem_ip_len };
max_rem_port_len = if (curr_rem_port_len > max_rem_port_len) { curr_rem_port_len } else { max_rem_port_len };
max_state_len = if(curr_state_len > max_state_len) { curr_state_len } else { max_state_len };
if combination == socket::socket::Combination::tnap{
max_real_uid_len = if (curr_real_uid_len > max_real_uid_len) { curr_real_uid_len } else { max_real_uid_len };
max_eff_uid_len = if (curr_eff_uid_len > max_eff_uid_len) { curr_eff_uid_len } else { max_eff_uid_len };
max_real_gid_len = if (curr_real_gid_len > max_real_gid_len) { curr_real_gid_len } else { max_real_gid_len };
max_eff_gid_len = if (curr_eff_gid_len > max_eff_gid_len) { curr_eff_gid_len } else { max_eff_gid_len };
max_pids_len = if (curr_pids_len > max_pids_len) { curr_pids_len } else { max_pids_len };
}
});
max_loc_ip_len = max_loc_ip_len + 3;
max_rem_ip_len = max_rem_ip_len + 3;
max_real_uid_len = max_real_uid_len + 3;
max_real_gid_len = max_real_gid_len + 3;
max_pids_len = max_pids_len + 3;
match combination {
socket::socket::Combination::tna => {
ret_str.push_str(&format!("{:>max_state_len$} {:>max_loc_ip_len$}:{:<max_loc_port_len$} {:>max_rem_ip_len$}:{:<max_rem_port_len$}\n", header_state , header_loc_ip , header_loc_port, header_rem_ip,header_rem_port));
sockets.clone().iter().for_each(|x| {
ret_str.push_str(&format!("{:>max_state_len$} {:>max_loc_ip_len$}:{:<max_loc_port_len$} {:>max_rem_ip_len$}:{:<max_rem_port_len$}", x.get_state().to_string(), x.get_loc_ip_string(), x.get_loc_port_string(), x.get_rem_ip_string(), x.get_rem_port_string()));
ret_str.push('\n');
});
}
socket::socket::Combination::tnap => {
ret_str.push_str(&format!("{:>max_state_len$} {:>max_loc_ip_len$}:{:<max_loc_port_len$} {:>max_rem_ip_len$}:{:<max_rem_port_len$} {:>max_real_uid_len$}|{:<max_eff_uid_len$} {:>max_real_gid_len$}|{:<max_eff_gid_len$} {:>max_pids_len$}\n", header_state , header_loc_ip , header_loc_port, header_rem_ip,header_rem_port, header_uid_real, header_uid_eff, header_gid_real, header_gid_eff, header_pids ));
sockets.clone().iter().for_each(|x| {
let (real_uid, eff_uid) = x.get_real_eff_uid_string();
let (real_gid,eff_gid) = x.get_real_eff_gid_String();
ret_str.push_str(&format!("{:>max_state_len$} {:>max_loc_ip_len$}:{:<max_loc_port_len$} {:>max_rem_ip_len$}:{:<max_rem_port_len$} {:>max_real_uid_len$}|{:<max_eff_uid_len$} {:>max_real_gid_len$}|{:<max_eff_gid_len$} {:>max_pids_len$}\n", x.get_state().to_string(), x.get_loc_ip_string(), x.get_loc_port_string(), x.get_rem_ip_string(), x.get_rem_port_string(), real_uid, eff_uid , real_gid , eff_gid, pids_to_string(&x.pids)))
});
}
}
ret_str
}
fn get_all_tcp_sockets(pid_pattern : &Regex, socket_patt : &Regex) -> Vec<socket::socket::Tcp_Socket> {
let mut sockets = Vec::<socket::socket::Tcp_Socket>::new();
let pids = get_readable_proc_pids(pid_pattern);
let mut inodes = HashSet::<inode>::new();
pids.iter().for_each(|x| {
get_tcp_file_by_pid(&pid_pattern.clone(), *x).lines().for_each(|y| {
add_to_tcp_sockets(&mut sockets, parse_tcp_file_line(y.to_owned()));
});
inodes = get_socket_inodes_by_pid(*x, socket_patt);
let (uid, gid) = get_uid_guid_by_pid(*x);
for (i, v) in sockets.clone().iter().enumerate() {
if inodes.contains(&v.inode){
add_pid_to_tcp_sockets(&mut sockets, inodes.clone(), *x);
}
Tcp_Socket::add_uid_gid(sockets.get_mut(i).unwrap(),uid, gid);
}
});
sockets
}
fn add_to_tcp_sockets(sockets : &mut Vec<socket::socket::Tcp_Socket>, socket: socket::socket::Tcp_Socket) -> (){
if !sockets.contains(&socket) {
sockets.push(socket);
}
}
fn get_socket_info() -> Vec<socket::socket::Tcp_Socket> {
let mut sockets = Vec::<socket::socket::Tcp_Socket>::new();
sockets
}
fn get_index(line: &String, index: usize) -> String {
line.clone().split_whitespace().nth(index).expect("upsi").to_owned()
}
fn get_remote_address() {}
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 sockets = get_all_tcp_sockets(&pid_pattern, &socket_patt);
println!("{}", format_output(socket::socket::Combination::tnap, &sockets));
}