Finish verion 0.1.0
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use async_trait::async_trait;
|
||||
use network_interface::{Addr, NetworkInterface, NetworkInterfaceConfig};
|
||||
use regex::Regex;
|
||||
use std::collections::HashMap;
|
||||
use sha2::Digest;
|
||||
use x509_parser::oid_registry::{
|
||||
OID_KEY_TYPE_DSA, OID_KEY_TYPE_EC_PUBLIC_KEY, OID_KEY_TYPE_GOST_R3410_2012_256,
|
||||
@@ -302,6 +303,7 @@ fn parse_ipconfig_dns(text: &str) -> DnsConfigSnapshot {
|
||||
}
|
||||
|
||||
fn parse_windows_listeners() -> Result<Vec<ListenSocket>, PlatformError> {
|
||||
let proc_map = load_windows_process_map();
|
||||
let output = std::process::Command::new("netstat")
|
||||
.arg("-ano")
|
||||
.output()
|
||||
@@ -316,11 +318,13 @@ fn parse_windows_listeners() -> Result<Vec<ListenSocket>, PlatformError> {
|
||||
for line in text.lines() {
|
||||
let trimmed = line.trim();
|
||||
if trimmed.starts_with("TCP") {
|
||||
if let Some(socket) = parse_netstat_tcp_line(trimmed) {
|
||||
if let Some(mut socket) = parse_netstat_tcp_line(trimmed) {
|
||||
enrich_socket(&mut socket, &proc_map);
|
||||
sockets.push(socket);
|
||||
}
|
||||
} else if trimmed.starts_with("UDP") {
|
||||
if let Some(socket) = parse_netstat_udp_line(trimmed) {
|
||||
if let Some(mut socket) = parse_netstat_udp_line(trimmed) {
|
||||
enrich_socket(&mut socket, &proc_map);
|
||||
sockets.push(socket);
|
||||
}
|
||||
}
|
||||
@@ -414,6 +418,103 @@ fn extract_port(value: &str) -> Option<u16> {
|
||||
None
|
||||
}
|
||||
|
||||
fn enrich_socket(socket: &mut ListenSocket, map: &HashMap<u32, ProcInfo>) {
|
||||
let pid = match socket.pid {
|
||||
Some(pid) => pid,
|
||||
None => return,
|
||||
};
|
||||
if let Some(info) = map.get(&pid) {
|
||||
socket.process_name = info.name.clone();
|
||||
socket.process_path = info.path.clone();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ProcInfo {
|
||||
name: Option<String>,
|
||||
path: Option<String>,
|
||||
}
|
||||
|
||||
fn load_windows_process_map() -> HashMap<u32, ProcInfo> {
|
||||
let mut map = HashMap::new();
|
||||
let mut name_map = HashMap::new();
|
||||
let tasklist = std::process::Command::new("tasklist")
|
||||
.args(["/fo", "csv", "/nh"])
|
||||
.output();
|
||||
if let Ok(output) = tasklist {
|
||||
if output.status.success() {
|
||||
let text = String::from_utf8_lossy(&output.stdout);
|
||||
for line in text.lines() {
|
||||
let parts = parse_csv_line(line);
|
||||
if parts.len() < 2 {
|
||||
continue;
|
||||
}
|
||||
if let Ok(pid) = parts[1].parse::<u32>() {
|
||||
name_map.insert(pid, parts[0].to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let wmic = std::process::Command::new("wmic")
|
||||
.args(["process", "get", "ProcessId,ExecutablePath", "/FORMAT:CSV"])
|
||||
.output();
|
||||
if let Ok(output) = wmic {
|
||||
if output.status.success() {
|
||||
let text = String::from_utf8_lossy(&output.stdout);
|
||||
for line in text.lines() {
|
||||
let parts = parse_csv_line(line);
|
||||
if parts.len() < 3 {
|
||||
continue;
|
||||
}
|
||||
let path = parts[1].trim();
|
||||
let pid = parts[2].trim().parse::<u32>().ok();
|
||||
if let Some(pid) = pid {
|
||||
let name = name_map.get(&pid).cloned();
|
||||
let path = if path.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(path.to_string())
|
||||
};
|
||||
map.insert(pid, ProcInfo { name, path });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (pid, name) in name_map {
|
||||
map.entry(pid)
|
||||
.or_insert_with(|| ProcInfo {
|
||||
name: Some(name),
|
||||
path: None,
|
||||
});
|
||||
}
|
||||
|
||||
map
|
||||
}
|
||||
|
||||
fn parse_csv_line(line: &str) -> Vec<String> {
|
||||
let mut out = Vec::new();
|
||||
let mut current = String::new();
|
||||
let mut in_quotes = false;
|
||||
for ch in line.chars() {
|
||||
match ch {
|
||||
'"' => {
|
||||
in_quotes = !in_quotes;
|
||||
}
|
||||
',' if !in_quotes => {
|
||||
out.push(current.trim_matches('"').to_string());
|
||||
current.clear();
|
||||
}
|
||||
_ => current.push(ch),
|
||||
}
|
||||
}
|
||||
if !current.is_empty() {
|
||||
out.push(current.trim_matches('"').to_string());
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn load_native_roots(store: &str) -> Result<Vec<RootCert>, PlatformError> {
|
||||
let certs = rustls_native_certs::load_native_certs()
|
||||
.map_err(|err| PlatformError::new(ErrorCode::IoError, err.to_string()))?;
|
||||
|
||||
Reference in New Issue
Block a user