use std::{
collections::HashSet,
fs,
io::{Read, Write},
path::PathBuf,
process::{Command, Stdio},
};
use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
use crate::keys::get_passwd_key;
fn is_usb(devices: &mut Vec<MyDevices>) {
let mut i = 0;
while i < devices.len() {
if !pipe(&devices[i].serial_number) {
devices.remove(i);
continue;
}
i += 1;
}
}
pub fn get_trusted_devices() -> HashSet<String> {
let mut trusted_devices: HashSet<String> = HashSet::new();
let serial_number = fs::read_to_string("/etc/etapkilit/trusted_devices.txt");
match serial_number {
Ok(lines) => {
lines.trim().lines().for_each(|line| {
trusted_devices.insert(line.to_string());
});
}
Err(_) => (),
}
trusted_devices
}
fn is_device_trusted(serial_number: &String, trusted_devices: HashSet<String>) -> bool {
trusted_devices.get(serial_number).is_some()
}
fn add_trusted_device(serial_number: &String) {
let mut file = fs::OpenOptions::new()
.write(true)
.append(true)
.open("/etc/etapkilit/trusted_devices.txt")
.unwrap();
writeln!(file, "{serial_number}");
}
pub fn get_devices() -> Vec<MyDevices> {
let stdout_reader = String::from_utf8(lsblk_output()).unwrap();
//let stdout_lines: Vec<String> = stdout_reader.lines().map(|l| l.unwrap()).collect();
let stdout_lines = stdout_reader.lines();
let mut devices = Vec::new();
for l in stdout_lines {
let device: Vec<&str> = l.split(" ").collect();
let disk = device[0];
if disk.len() == 3 {
let new_device = MyDevices {
vendor: device[3].to_string(),
model: device[2].to_string(),
name: disk.to_string(),
serial_number: get_serial_number(disk),
mountpoint: Vec::new(),
};
devices.push(new_device);
} else {
let last_disk = devices.last_mut().unwrap();
let mount = device[1];
if mount.len() > 0 {
last_disk.mountpoint.push(mount.to_string());
}
}
}
is_usb(&mut devices);
devices
}
fn get_serial_number(disk: &str) -> String {
let mut cmd_ls = Command::new("udevadm")
.args(["info", "--query=all"])
.arg(format!("--name={}", disk))
.stdout(Stdio::piped())
.spawn()
.unwrap();
let mut cmd_grep = Command::new("grep")
.arg("ID_SERIAL_SHORT")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.unwrap();
if let Some(ref mut stdout) = cmd_ls.stdout {
if let Some(ref mut stdin) = cmd_grep.stdin {
let mut buf: Vec<u8> = Vec::new();
stdout.read_to_end(&mut buf).unwrap();
stdin.write_all(&buf).unwrap();
}
}
let res = cmd_grep.wait_with_output().unwrap().stdout;
let res = String::from_utf8(res).unwrap();
let res = res.trim().split("=").collect::<Vec<&str>>();
//println!("{res:?}");
res[1].to_string()
}
fn lsblk_output() -> Vec<u8> {
let a = Command::new("lsblk")
.arg("-o")
.arg("name,mountpoInt,model,vendor")
.args(["-n", "-r", "-i"])
.stdout(Stdio::piped())
.output()
.unwrap();
a.stdout
}
fn pipe(s: &String) -> bool {
let mut cmd_ls = Command::new("usb-devices")
.stdout(Stdio::piped())
.spawn()
.unwrap();
let mut cmd_grep = Command::new("grep")
.arg(s)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.unwrap();
if let Some(ref mut stdout) = cmd_ls.stdout {
if let Some(ref mut stdin) = cmd_grep.stdin {
let mut buf: Vec<u8> = Vec::new();
stdout.read_to_end(&mut buf).unwrap();
stdin.write_all(&buf).unwrap();
}
}
let res = cmd_grep.wait_with_output().unwrap().stdout;
let res = String::from_utf8(res).unwrap();
res.trim().len() != 0
}
pub fn list_devices(devices: &Vec<MyDevices>) {
for d in devices.iter().enumerate() {
d.1.list_device(d.0 + 1);
}
}
#[derive(Debug, Clone)]
pub struct MyDevices {
vendor: String,
model: String,
name: String,
serial_number: String,
mountpoint: Vec<String>,
}
impl MyDevices {
pub fn is_mounted(&self) -> bool {
self.mountpoint.len() > 0
}
pub fn write_pub_key(&self, key: &RsaPrivateKey) {
let pub_key = RsaPublicKey::from(key);
let serial_number = pub_key.encrypt(
&mut rand::thread_rng(),
Pkcs1v15Encrypt,
&self.serial_number.as_bytes(),
);
let mut path = PathBuf::new();
path.push(self.mountpoint[0].clone());
path.push(".etapkilit.key");
std::fs::write(path.as_path(), serial_number.unwrap());
println!("etap kilit oluşturuldu");
}
pub fn read_key(&self, priv_key: &rsa::RsaPrivateKey) -> bool {
//println!("okumaya başlandı");
let mut trusted_devices = get_trusted_devices();
let serial_number = &self.serial_number;
if is_device_trusted(serial_number, trusted_devices) {
log::info!("1 0");
return true;
}
for m in &self.mountpoint {
let mut path = PathBuf::new();
path.push(&m);
path.push(".etapkilit.key");
let enc_data = fs::read(path.as_path());
if let Ok(e_data) = enc_data {
if let Ok(dec_data) = priv_key.decrypt(Pkcs1v15Encrypt, &e_data) {
if dec_data == serial_number.as_bytes() {
add_trusted_device(serial_number);
log::info!("1 1");
return true;
}
}
} else {
let mut path = PathBuf::new();
path.push(&m);
path.push(".password.key");
let enc_data = fs::read(path.as_path());
println!("{enc_data:?}");
if let Ok(e_data) = enc_data {
if let Ok(dec_data) = priv_key.decrypt(Pkcs1v15Encrypt, &e_data) {
let passwd = get_passwd_key();
if let Ok(passwd) = priv_key.decrypt(Pkcs1v15Encrypt, &passwd) {
let dec_data = String::from_utf8(dec_data).unwrap();
let passwd = String::from_utf8(passwd).unwrap();
if dec_data == passwd || dec_data == passwd.trim() {
add_trusted_device(serial_number);
fs::remove_file(path.as_path());
log::info!("1 2");
return true;
}
}
}
}
}
}
false
}
fn list_device(&self, index: usize) {
println!(
"{}- {} {} {}",
index,
self.vendor.replace("\\x20", ""),
&self.model,
&self.serial_number
);
}
}