Skip to content

Commit 39deb06

Browse files
authored
fix: macos chrome cookie plugin (#217)
1 parent 6b35293 commit 39deb06

File tree

3 files changed

+8
-114
lines changed

3 files changed

+8
-114
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ clap = { version = "4.5", features = ["cargo", "derive"] }
2222
colored = "3.1.1"
2323
dirs = "6.0.0"
2424
env_logger = "0.11.6"
25-
keyring = "3.6.3"
2625
log = "0.4.29"
2726
openssl = "0.10"
2827
pyo3 = { version = "0.27", optional = true }
@@ -37,9 +36,10 @@ clap_complete = "4.5"
3736
thiserror = "2.0.18"
3837
unicode-width = "0.2"
3938
notify = "8.2.0"
39+
rookie = "0.5.6"
4040

4141
[dependencies.diesel]
42-
version = "2.2.12"
42+
version = "2.3.6"
4343
features = ["sqlite"]
4444

4545
[dependencies.reqwest]

src/err.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ pub enum Error {
6767
#[error(transparent)]
6868
Anyhow(#[from] anyhow::Error),
6969
#[error(transparent)]
70-
Keyring(#[from] keyring::Error),
71-
#[error(transparent)]
7270
OpenSSL(#[from] openssl::error::ErrorStack),
7371
#[cfg(feature = "pym")]
7472
#[error(transparent)]

src/plugins/chrome.rs

Lines changed: 6 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,6 @@
1-
use crate::{Error, Result, cache};
2-
use anyhow::anyhow;
3-
use diesel::prelude::*;
4-
use keyring::Entry;
5-
use openssl::{hash, pkcs5, symm};
1+
use crate::{Error, Result};
62
use std::{collections::HashMap, fmt::Display};
73

8-
/// LeetCode Cookies Schema
9-
mod schema {
10-
table! {
11-
cookies (host_key) {
12-
encrypted_value -> Binary,
13-
host_key -> Text,
14-
name -> Text,
15-
}
16-
}
17-
}
18-
19-
/// Please make sure the order
20-
///
21-
/// The order between table and struct must be same.
22-
#[derive(Queryable, Debug, Clone)]
23-
struct Cookies {
24-
pub encrypted_value: Vec<u8>,
25-
#[allow(dead_code)]
26-
pub host_key: String,
27-
pub name: String,
28-
}
29-
304
/// Spawn cookies to cookie format
315
#[derive(Debug)]
326
pub struct Ident {
@@ -54,38 +28,13 @@ pub fn cookies() -> Result<Ident> {
5428
});
5529
}
5630

57-
// If doesn't config SESSION and csrftoken
58-
use self::schema::cookies::dsl::*;
59-
trace!("Derive cookies from google chrome...");
60-
61-
let home = dirs::home_dir().ok_or(Error::NoneError)?;
62-
let p = match std::env::consts::OS {
63-
"macos" => home.join("Library/Application Support/Google/Chrome/Default/Cookies"),
64-
"linux" => home.join(".config/google-chrome/Default/Cookies"),
65-
_ => panic!("Opps...only works on OSX or Linux now..."),
66-
};
67-
68-
debug!("Chrome Cookies path is {:?}", &p);
69-
let mut conn = cache::conn(p.to_string_lossy().to_string());
70-
let res = cookies
71-
.filter(host_key.like(format!("#{}", ccfg.site)))
72-
.load::<Cookies>(&mut conn)
73-
.expect("Loading cookies from google chrome failed.");
74-
75-
debug!("res {:?}", &res);
76-
if res.is_empty() {
77-
return Err(Error::CookieError);
78-
}
79-
80-
// Get system password
81-
let ring = Entry::new("Chrome Safe Storage", "Chrome")?;
82-
let pass = ring.get_password().expect("Get Password failed");
83-
84-
// Decode cookies
8531
let mut m: HashMap<String, String> = HashMap::new();
86-
for c in res {
32+
33+
let domains = vec![format!("{}", ccfg.site)];
34+
let cookies = rookie::chrome(Some(domains)).unwrap();
35+
for c in cookies {
8736
if (c.name == "csrftoken") || (c.name == "LEETCODE_SESSION") {
88-
m.insert(c.name, decode_cookies(&pass, c.encrypted_value)?);
37+
m.insert(c.name, c.value);
8938
}
9039
}
9140

@@ -98,56 +47,3 @@ pub fn cookies() -> Result<Ident> {
9847
})
9948
}
10049

101-
/// Decode cookies from chrome
102-
fn decode_cookies(pass: &str, v: Vec<u8>) -> Result<String> {
103-
let mut key = [0_u8; 16];
104-
match std::env::consts::OS {
105-
"macos" => {
106-
pkcs5::pbkdf2_hmac(
107-
pass.as_bytes(),
108-
b"saltysalt",
109-
1003,
110-
hash::MessageDigest::sha1(),
111-
&mut key,
112-
)
113-
.expect("pbkdf2 hmac went error.");
114-
}
115-
"linux" => {
116-
pkcs5::pbkdf2_hmac(
117-
b"peanuts",
118-
b"saltysalt",
119-
1,
120-
hash::MessageDigest::sha1(),
121-
&mut key,
122-
)
123-
.expect("pbkdf2 hmac went error.");
124-
}
125-
_ => return Err(anyhow!("only supports OSX or Linux for now").into()),
126-
}
127-
128-
chrome_decrypt(v, key)
129-
}
130-
131-
/// Decrypt chrome cookie value with aes-128-cbc
132-
fn chrome_decrypt(v: Vec<u8>, key: [u8; 16]) -> Result<String> {
133-
// <space>: \u16
134-
let iv = vec![32_u8; 16];
135-
let mut decrypter = symm::Crypter::new(
136-
symm::Cipher::aes_128_cbc(),
137-
symm::Mode::Decrypt,
138-
&key,
139-
Some(&iv),
140-
)?;
141-
142-
let data_len = v.len() - 3;
143-
let block_size = symm::Cipher::aes_128_cbc().block_size();
144-
let mut plaintext = vec![0; data_len + block_size];
145-
146-
decrypter.pad(false);
147-
148-
let count = decrypter.update(&v[3..], &mut plaintext)?;
149-
decrypter.finalize(&mut plaintext[count..])?;
150-
plaintext.retain(|x| x >= &20_u8);
151-
152-
Ok(String::from_utf8_lossy(&plaintext.to_vec()).to_string())
153-
}

0 commit comments

Comments
 (0)