mod dao;
mod entities;
mod path;
use miette::{IntoDiagnostic, Result};
use secret_service::{EncryptionType, SecretService};
use tokio::task;
use tracing::debug;
use self::entities::cookies;
use crate::{Browser, Cookies};
pub async fn get_session_csrf(browser: Browser, host: &str) -> Result<Cookies> {
let mut cookies = dao::query_cookie(browser, host).await?;
let pass = get_pass(browser).await?;
task::spawn_blocking(move || {
let mut res = Cookies::default();
for cookie in &mut cookies {
if cookie.name == "csrftoken" {
decrypt_cookies(&mut cookie.encrypted_value, &pass)?;
res.csrf = String::from_utf8_lossy(&cookie.encrypted_value[3..]).to_string();
}
else if cookie.name == "LEETCODE_SESSION" {
decrypt_cookies(&mut cookie.encrypted_value, &pass)?;
res.session = String::from_utf8_lossy(&cookie.encrypted_value[3..]).to_string();
}
}
Ok(res)
})
.await
.into_diagnostic()?
}
pub async fn get_all_cookies(browser: Browser, host: &str) -> Result<Vec<cookies::Model>> {
let mut cookies = dao::query_cookie(browser, host).await?;
let pass = get_pass(browser).await?;
task::spawn_blocking(move || {
for cookie in &mut cookies {
decrypt_cookies(&mut cookie.encrypted_value, &pass)?;
}
Ok(cookies)
})
.await
.into_diagnostic()?
}
pub fn decrypt_cookies(be_decrypte: &mut Vec<u8>, pass: &[u8]) -> Result<()> {
use aes::cipher::{block_padding, BlockDecryptMut, KeyIvInit};
use pbkdf2::pbkdf2_hmac;
type Aes128CbcDec = cbc::Decryptor<aes::Aes128>;
let mut key = [0_u8; 16];
pbkdf2_hmac::<sha1::Sha1>(pass, b"saltysalt", 1, &mut key);
let iv = [32_u8; 16];
let decrypter = Aes128CbcDec::new(&key.into(), &iv.into());
decrypter
.decrypt_padded_mut::<block_padding::NoPadding>(&mut be_decrypte[3..])
.expect("decrypt failed");
be_decrypte.retain(|v| v >= &32);
Ok(())
}
const CHROME_STORAGE_NAME: &str = "Chrome Safe Storage";
const EDGE_STORAGE_NAME: &str = "Chrome Safe Storage";
pub async fn get_pass(browser: Browser) -> Result<Vec<u8>> {
let default_pass = Ok(b"peanuts".to_vec());
let Ok(ss) = SecretService::connect(EncryptionType::Dh).await
else {
return default_pass;
};
let Ok(collection) = ss.get_default_collection().await
else {
return default_pass;
};
let coll = collection
.get_all_items()
.await
.into_diagnostic()?;
let label = match browser {
Browser::Edge => EDGE_STORAGE_NAME,
Browser::Chrome => CHROME_STORAGE_NAME,
_ => CHROME_STORAGE_NAME,
};
let mut res = vec![];
for i in coll {
if let Ok(l) = i.get_label().await {
if l == label {
res = i.get_secret().await.into_diagnostic()?;
}
}
}
debug!("res: {}", String::from_utf8_lossy(&res).to_string());
if res.is_empty() {
return default_pass;
}
Ok(res)
}