Skip to content

Commit

Permalink
feat: kwallet decrypt
Browse files Browse the repository at this point in the history
  • Loading branch information
thewh1teagle committed Oct 5, 2023
1 parent 646260e commit e150ec4
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 58 deletions.
13 changes: 5 additions & 8 deletions rookie-rs/src/chromium.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,17 @@ fn get_keys(config: &BrowserConfig) -> Result<Vec<Vec<u8>>, Box<dyn std::error::

cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
if let Ok(password) = secrets::get_password(config.os_crypt_name.unwrap_or("")) {

let key = create_pbkdf2_key(password.as_str(), salt, iterations);
keys.push(key);
if let Ok(passwords) = secrets::get_passwords(config.os_crypt_name.unwrap_or("")) {
for password in passwords {
let key = create_pbkdf2_key(password.as_str(), salt, iterations);
keys.push(key);
}
}

// default keys
let key = create_pbkdf2_key("peanuts", salt, iterations);
keys.push(key);
let key = create_pbkdf2_key("", salt, iterations);
keys.push(key);



}
else if #[cfg(target_os = "macos")] {
let key_service = config.osx_key_service.ok_or("missing osx_key_service")?;
Expand Down
6 changes: 3 additions & 3 deletions rookie-rs/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::enums::BrowserConfig;
/*
*********** WINDOWS **********
*/

pub const APP_ID: &str = "rookie";

cfg_if::cfg_if! {
if #[cfg(target_os = "windows")] {
// Initialize the CHROME_CONFIG as a static variable with specific values
Expand Down
80 changes: 33 additions & 47 deletions rookie-rs/src/secrets.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// const APP_ID: &str = "rookie";
use crate::{utils, config};



cfg_if::cfg_if! {
Expand All @@ -7,7 +8,7 @@ cfg_if::cfg_if! {
use zbus::{blocking::Connection, zvariant::Value, zvariant::ObjectPath, Message};


fn libsecret_getmethod<'a, T>(
fn libsecret_call<'a, T>(
connection: &Connection,
method: &str,
args: T,
Expand All @@ -25,7 +26,7 @@ cfg_if::cfg_if! {
}


fn kde_getmethod<'a, T>(
fn kwallet_call<'a, T>(
connection: &Connection,
method: &str,
args: T,
Expand All @@ -43,22 +44,20 @@ cfg_if::cfg_if! {
}


pub fn get_password(os_crypt_name: &str) -> Result<String, Box<dyn std::error::Error>> {
pub fn get_passwords(os_crypt_name: &str) -> Result<Vec<String>, Box<dyn std::error::Error>> {
// Attempt to get the password from libsecret
let mut passwords: Vec<String> = vec![];
for schema in ["chrome_libsecret_os_crypt_password_v2", "chrome_libsecret_os_crypt_password_v1"] {
if let Ok(libsecret_pass) = get_password_libsecret(schema, os_crypt_name) {
return Ok(libsecret_pass);
passwords.push(libsecret_pass);
}
}


// Attempt to get the password from kdewallet
if let Ok(kdewallet_pass) = get_password_kdewallet(os_crypt_name) {
return Ok(kdewallet_pass.to_string());
if let Ok(password) = get_password_kdewallet(os_crypt_name) {
passwords.push(password);
}

// Both methods failed, return an error
Err("Password retrieval failed".into())
Ok(passwords)
}


Expand All @@ -67,67 +66,54 @@ cfg_if::cfg_if! {
let mut content = HashMap::<&str, &str>::new();
content.insert("xdg:schema", schema);
content.insert("application", crypt_name);
let m = libsecret_getmethod(&connection, "SearchItems", &content)?;
let m = libsecret_call(&connection, "SearchItems", &content)?;
let (reply_paths, _) : (Vec<ObjectPath>, Vec<ObjectPath>) = m.body()?;
let path = reply_paths.first().ok_or("search items empty")?;


let m = libsecret_getmethod(&connection, "Unlock", vec![path])?;
let m = libsecret_call(&connection, "Unlock", vec![path])?;
let reply: (Vec<ObjectPath>, ObjectPath) = m.body()?;
let object_path = reply.0.first().ok_or("Cant unlock")?;


let mut content = HashMap::<&str, &str>::new();
content.insert("plain", "");
let m = libsecret_getmethod(&connection, "OpenSession", &("plain", Value::new("")))?;
let m = libsecret_call(&connection, "OpenSession", &("plain", Value::new("")))?;


let reply: (Value, ObjectPath) = m.body()?;
let reply: (Value, ObjectPath) = m.body()?;
let session = reply.1;

let m = libsecret_getmethod(&connection, "GetSecrets", &(vec![object_path], session))?;
let m = libsecret_call(&connection, "GetSecrets", &(vec![object_path], session))?;
type Response<'a> = (ObjectPath<'a>, Vec<u8>, Vec<u8>, String);
let reply: HashMap::<ObjectPath, Response> = m.body()?;
let inner = reply.get(object_path).ok_or("Cant get secrets")?;
let secret = &inner.2;

Ok(String::from_utf8(secret.clone())?)
}



fn get_password_kdewallet(crypt_name: &str)-> Result<String, Box<dyn std::error::Error>> {
// let connection = Connection::session()?;
// let folder = format!("{} Keys", crypt_name.to_uppercase());
// let key = format!("{} Safe Storage", crypt_name.to_uppercase());
let connection = Connection::session()?;
let folder = format!("{} Keys", utils::capitalize(crypt_name));
let key = format!("{} Safe Storage", utils::capitalize(crypt_name));

// let mut content = HashMap::<&str, &str>::new();
// content.insert("xdg:schema", schema);
// content.insert("application", crypt_name);
// let m = kde_getmethod(&connection, "SearchItems", &content)?;
// let (reply_paths, _) : (Vec<ObjectPath>, Vec<ObjectPath>) = m.body()?;
// let path = reply_paths.first().ok_or("search items empty")?;


// let m = libsecret_getmethod(&connection, "Unlock", vec![path])?;
// let reply: (Vec<ObjectPath>, ObjectPath) = m.body()?;
// let object_path = reply.0.first().ok_or("Cant unlock")?;


// let mut content = HashMap::<&str, &str>::new();
// content.insert("plain", "");
// let m = libsecret_getmethod(&connection, "OpenSession", &("plain", Value::new("")))?;


// let reply: (Value, ObjectPath) = m.body()?;
// let session = reply.1;

// let m = libsecret_getmethod(&connection, "GetSecrets", &(vec![object_path], session))?;
// type Response<'a> = (ObjectPath<'a>, Vec<u8>, Vec<u8>, String);
// let reply: HashMap::<ObjectPath, Response> = m.body()?;
// let inner = reply.get(object_path).ok_or("Cant get secrets")?;
// let secret = &inner.2;
let m = kwallet_call(&connection, "networkWallet", ())?;
let network_wallet: String = m.body()?;

let m = kwallet_call(&connection, "open", (network_wallet.clone(), 0 as i64, config::APP_ID))?;
let handle: i32 = m.body()?;
let m = kwallet_call(&connection, "readPassword", (handle, folder, key, config::APP_ID))?;
let password: String = m.body()?;
let m = kwallet_call(&connection, "close", (network_wallet, false))?;
let close_ok: i32 = m.body()?;
if close_ok != 1 {
return Err("Close failed".into());
}

// Ok(String::from_utf8(secret.clone())?)
Err("not implemented".into())
Ok(password)
}


Expand Down
8 changes: 8 additions & 0 deletions rookie-rs/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@ pub fn epoch_to_systemtime_micros(timestamp: i64) -> SystemTime {
#[cfg(target_os = "macos")]
pub fn unix_timestamp_to_system_time(timestamp: i64) -> SystemTime {
UNIX_EPOCH + Duration::from_secs(timestamp as u64)
}

pub fn capitalize(s: &str) -> String {
let mut c = s.chars();
match c.next() {
None => String::new(),
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
}
}

0 comments on commit e150ec4

Please sign in to comment.