#![allow(unused)]
use std::env;
use std::fs;
use std::{
io::{BufRead, BufReader, Error, Read, Stdin, Stdout, Write},
path::{Path, PathBuf},
process::{Command, Stdio},
thread::{self, sleep},
time::{Duration, Instant},
};
use devices::get_devices;
use keys::create_password;
use rsa::Pkcs1v15Encrypt;
use rsa::RsaPrivateKey;
use crate::devices::list_devices;
use log::{debug, error, info, log_enabled, Level};
mod devices;
mod keys;
fn main() {
env_logger::init();
let mut priv_key = keys::get_priv_key();
let args: Vec<String> = env::args().collect();
if let Some(arg) = args.get(1) {
match arg.as_ref() {
"-a" => {
let mut devices = devices::get_devices();
devices.retain(|d| d.is_mounted());
list_devices(&devices);
println!("Bir disk seçin");
let mut buffer = String::new();
std::io::stdin().read_line(&mut buffer).unwrap();
let selected_disk = buffer.trim().parse::<usize>().unwrap();
if selected_disk <= devices.len() {
let d = devices[selected_disk - 1].clone();
d.write_pub_key(&priv_key);
}
return ();
}
"-c" => {
create_password(priv_key);
}
"-d" => {
get_devices();
}
_ => {
println!("invalid arg");
return ();
}
}
} else {
start_loop(priv_key);
}
}
fn start_loop(priv_key: rsa::RsaPrivateKey) {
let schoold_id = env::var("SCHOOL_ID").unwrap_or("1".to_string());
let mut lock_time = env::var("LOCK")
.unwrap_or("240".to_string())
.parse::<u64>()
.unwrap_or(240);
let mut rng = rand::thread_rng();
let mut est_time = Instant::now();
let mut lock_state = LockState::Locked;
loop {
if est_time.elapsed().as_secs() >= lock_time && lock_state == LockState::Locked {
shutdown();
}
match &lock_state {
LockState::Locked => {
log::info!("0 {}", lock_time - est_time.elapsed().as_secs());
if !check_usb(&priv_key, &mut lock_state) {
check_key(&mut lock_state);
}
}
LockState::Unlocked(unlock) => match unlock {
UnlockedState::Usb(serial) => {
log::info!("1 0");
let devices = get_devices();
if !devices.iter().any(|d| &d.get_serial() == serial) {
lock_state = LockState::Locked;
}
}
UnlockedState::Key => {
log::info!("1 1");
thread::sleep(Duration::from_secs(60 * 40));
lock_time = 240;
est_time = Instant::now();
}
},
}
thread::sleep(Duration::from_millis(1000));
}
}
fn check_usb(priv_key: &RsaPrivateKey, state: &mut LockState) -> bool {
let mut devices = devices::get_devices();
for device in &devices {
if device.read_key(&priv_key.clone()) {
*state = LockState::Unlocked(UnlockedState::Usb(device.get_serial()));
return true;
}
}
false
}
fn check_key(state: &mut LockState) -> bool {
if confirm_key() {
std::fs::remove_file("/tmp/kilit").unwrap_or_default();
*state = LockState::Unlocked(UnlockedState::Key);
return true;
}
false
}
fn confirm_key() -> bool {
let school_id = env::var("SCHOOL_ID").unwrap_or("1".to_string());
let key = std::fs::read_to_string("/tmp/kilit");
if let Ok(key) = key {
let agent: ureq::Agent = ureq::AgentBuilder::new()
.timeout_read(Duration::from_secs(5))
.timeout_write(Duration::from_secs(5))
.build();
let url = format!("https://etapkilit.libredu.org/confirm_key/{}", key);
let body: u16 = agent.get(&url).call().unwrap().status();
return body == 200;
}
false
}
fn shutdown() {
let a = Command::new("shutdown")
.arg("-h")
.arg("now")
.spawn()
.unwrap();
}
#[derive(Debug, Clone, PartialEq)]
enum LockState {
Locked,
Unlocked(UnlockedState),
}
#[derive(Debug, Clone, PartialEq)]
enum UnlockedState {
Usb(String),
Key,
}