@mherod/get-cookie 2.0.0-rc.2 → 2.0.0-rc.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/runConfigurations/build.xml +12 -0
- package/.prettierignore +5 -0
- package/README.md +2 -2
- package/dist/cli.js +1110 -2
- package/dist/index.js +642 -231
- package/dist/index.js.map +1 -1
- package/dist/module.js +634 -224
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +246 -34
- package/dist/types.d.ts.map +1 -1
- package/package-lock.json +7539 -0
- package/package.json +24 -22
- package/src/CookieRow.ts +2 -1
- package/src/CookieSpec.ts +4 -2
- package/src/CookieStore.ts +27 -0
- package/src/ExportedCookie.ts +2 -1
- package/src/FetchResponse.ts +2 -0
- package/src/FileCookieStore.ts +170 -0
- package/src/IsCookieRow.ts +1 -1
- package/src/IsExportedCookie.ts +1 -1
- package/src/SpecialCases.ts +1 -1
- package/src/StringToRegex.ts +6 -0
- package/src/argv.ts +19 -0
- package/src/browsers/ChromeCookieQueryStrategy.ts +106 -24
- package/src/browsers/CompositeCookieQueryStrategy.ts +32 -8
- package/src/browsers/CookieQueryStrategy.ts +3 -1
- package/src/browsers/CookieStoreQueryStrategy.ts +99 -0
- package/src/browsers/FirefoxCookieQueryStrategy.ts +57 -9
- package/src/browsers/SafariCookieQueryStrategy.ts +4 -1
- package/src/cli.ts +101 -93
- package/src/comboQueryCookieSpec.ts +24 -0
- package/src/cookieSpecsFromUrl.ts +26 -0
- package/src/doSqliteQuery1Params.ts +8 -0
- package/src/fetchWithCookies.ts +131 -40
- package/src/findAllFiles.ts +5 -9
- package/src/getChromeCookie.ts +19 -0
- package/src/getCookie.ts +19 -0
- package/src/getFirefoxCookie.ts +19 -0
- package/src/getGroupedRenderedCookies.ts +12 -25
- package/src/getMergedRenderedCookies.ts +14 -0
- package/src/index.ts +13 -52
- package/src/isValidJwt.ts +2 -2
- package/src/queryCookies.ts +16 -12
- package/src/resultsRendered.ts +7 -4
- package/src/unpackHeaders.ts +7 -4
- package/src/utils.ts +0 -25
- package/tsconfig.json +11 -15
- package/.github/dependabot.yml +0 -6
- package/dist/cli.js.map +0 -1
- package/src/doSqliteQuery1.ts +0 -51
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mherod/get-cookie",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.21",
|
|
4
4
|
"description": "Node.js module for querying a local user's Chrome cookie",
|
|
5
5
|
"source": "src/index.ts",
|
|
6
6
|
"bin": "dist/cli.js",
|
|
@@ -11,38 +11,37 @@
|
|
|
11
11
|
"access": "public"
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
|
-
"clean": "git clean -
|
|
15
|
-
"build": "parcel build",
|
|
14
|
+
"clean": "git clean -fdX && rm -rf node_modules dist && yarn install",
|
|
15
|
+
"build": "tsc && parcel build",
|
|
16
16
|
"prepare": "npm run build && npm run prettier",
|
|
17
|
+
"postinstall": "npm run build",
|
|
17
18
|
"test": "jest",
|
|
18
|
-
"postbuild": "npm run check",
|
|
19
19
|
"prepublish": "npm run build",
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"postinstall:global": "find $NVM_BIN -exec chmod +x {} \\; || true",
|
|
23
|
-
"prettier": "prettier --write 'src/{**/*,*}.{js,json,ts}'",
|
|
24
|
-
"check": "tsc --noEmit"
|
|
20
|
+
"install:global": "npm run build && npm install --global .",
|
|
21
|
+
"prettier": "prettier --write ."
|
|
25
22
|
},
|
|
26
23
|
"targets": {
|
|
27
|
-
"main": {},
|
|
28
24
|
"types": {},
|
|
25
|
+
"main": {},
|
|
29
26
|
"library": {
|
|
30
|
-
"source":
|
|
31
|
-
"src/index.ts"
|
|
32
|
-
],
|
|
27
|
+
"source": "src/index.ts",
|
|
33
28
|
"distDir": "dist",
|
|
34
29
|
"isLibrary": true,
|
|
35
30
|
"engines": {
|
|
36
|
-
"node": "16"
|
|
37
|
-
}
|
|
31
|
+
"node": ">= 16"
|
|
32
|
+
},
|
|
33
|
+
"sourceMap": true,
|
|
34
|
+
"includeNodeModules": false
|
|
38
35
|
},
|
|
39
36
|
"cli": {
|
|
40
37
|
"source": "src/cli.ts",
|
|
41
38
|
"distDir": "dist",
|
|
42
39
|
"isLibrary": false,
|
|
43
40
|
"engines": {
|
|
44
|
-
"node": "16"
|
|
41
|
+
"node": ">= 16"
|
|
45
42
|
},
|
|
43
|
+
"sourceMap": false,
|
|
44
|
+
"optimize": false,
|
|
46
45
|
"includeNodeModules": [
|
|
47
46
|
"colorette"
|
|
48
47
|
]
|
|
@@ -53,7 +52,7 @@
|
|
|
53
52
|
"inlineEnvironment": true
|
|
54
53
|
},
|
|
55
54
|
"engines": {
|
|
56
|
-
"node": "16"
|
|
55
|
+
"node": ">= 16"
|
|
57
56
|
},
|
|
58
57
|
"keywords": [],
|
|
59
58
|
"author": "Matthew Herod",
|
|
@@ -61,12 +60,15 @@
|
|
|
61
60
|
"dependencies": {
|
|
62
61
|
"colorette": "^2.0.19",
|
|
63
62
|
"cross-fetch": "^3.1.5",
|
|
64
|
-
"destr": "^1.
|
|
63
|
+
"destr": "^1.2.0",
|
|
65
64
|
"jsonwebtoken": "^8.5.1",
|
|
66
65
|
"lodash": "^4.17.21",
|
|
66
|
+
"lodash-es": "^4.17.21",
|
|
67
67
|
"lru-cache": "^7.14.0",
|
|
68
|
-
"minimist": "^1.2.
|
|
69
|
-
"sqlite3": "^5.1.
|
|
68
|
+
"minimist": "^1.2.7",
|
|
69
|
+
"sqlite3": "^5.1.2",
|
|
70
|
+
"tough-cookie": "^4.1.2",
|
|
71
|
+
"user-agents": "^1.0.1178"
|
|
70
72
|
},
|
|
71
73
|
"devDependencies": {
|
|
72
74
|
"@parcel/packager-ts": "^2.7.0",
|
|
@@ -74,9 +76,9 @@
|
|
|
74
76
|
"@types/jsonwebtoken": "^8.5.9",
|
|
75
77
|
"@types/lodash": "^4.14.186",
|
|
76
78
|
"@types/minimist": "^1.2.2",
|
|
77
|
-
"@types/node": "^18.
|
|
79
|
+
"@types/node": "^18.11.4",
|
|
80
|
+
"@types/tough-cookie": "^4.0.2",
|
|
78
81
|
"@types/user-agents": "^1.0.2",
|
|
79
|
-
"jest": "^29.0.3",
|
|
80
82
|
"parcel": "^2.7.0",
|
|
81
83
|
"prettier": "^2.7.1",
|
|
82
84
|
"ts-node": "^10.9.1",
|
package/src/CookieRow.ts
CHANGED
package/src/CookieSpec.ts
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { env } from "./global";
|
|
2
|
+
import { parsedArgs } from "./argv";
|
|
3
|
+
import { CookieJar, MemoryCookieStore, Store } from "tough-cookie";
|
|
4
|
+
|
|
5
|
+
import { FileCookieStore } from "./FileCookieStore";
|
|
6
|
+
|
|
7
|
+
const memoryCookieStore = new MemoryCookieStore();
|
|
8
|
+
|
|
9
|
+
async function getCookieStore(): Promise<Store> {
|
|
10
|
+
if (parsedArgs["cs"] == "memory") {
|
|
11
|
+
return memoryCookieStore;
|
|
12
|
+
}
|
|
13
|
+
const fileCookieStore = new FileCookieStore(
|
|
14
|
+
`${env["HOME"]}/cookie-star.json`,
|
|
15
|
+
memoryCookieStore
|
|
16
|
+
);
|
|
17
|
+
await fileCookieStore.waitUntilIdle();
|
|
18
|
+
return fileCookieStore;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const cookieStorePromise: Promise<Store> = new Promise((resolve) => {
|
|
22
|
+
getCookieStore().then(resolve);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const cookieJarPromise: Promise<CookieJar> = new Promise((resolve) => {
|
|
26
|
+
cookieStorePromise.then((store) => new CookieJar(store)).then(resolve);
|
|
27
|
+
});
|
package/src/ExportedCookie.ts
CHANGED
package/src/FetchResponse.ts
CHANGED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { Cookie, MemoryCookieStore, Store } from "tough-cookie";
|
|
2
|
+
import { existsSync, readFileSync, writeFile } from "fs";
|
|
3
|
+
import destr from "destr";
|
|
4
|
+
import { merge } from "lodash";
|
|
5
|
+
|
|
6
|
+
export class FileCookieStore extends Store {
|
|
7
|
+
private readonly internalStore: Store;
|
|
8
|
+
|
|
9
|
+
synchronous: boolean = false;
|
|
10
|
+
filePath: string;
|
|
11
|
+
|
|
12
|
+
private tasks: Promise<any>[] = [];
|
|
13
|
+
|
|
14
|
+
constructor(
|
|
15
|
+
filePath: string,
|
|
16
|
+
internalStore: Store = new MemoryCookieStore()
|
|
17
|
+
) {
|
|
18
|
+
super();
|
|
19
|
+
|
|
20
|
+
this.filePath = filePath;
|
|
21
|
+
this.internalStore = internalStore ?? new MemoryCookieStore();
|
|
22
|
+
|
|
23
|
+
console.log("Importing cookies from", filePath, internalStore);
|
|
24
|
+
|
|
25
|
+
this.tasks.push(
|
|
26
|
+
this.importSaved(filePath, internalStore).then(console.log, console.error)
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private async importSaved(filePath: string, store: Store): Promise<Cookie[]> {
|
|
31
|
+
const cookies: Cookie[] = [];
|
|
32
|
+
if (existsSync(filePath)) {
|
|
33
|
+
const data = readFileSync(filePath, "utf8");
|
|
34
|
+
const cookies: any[] = Object.values(destr(data))
|
|
35
|
+
.flatMap((domainCookies: any) => Object.values(domainCookies))
|
|
36
|
+
.flatMap((domainCookies: any) => Object.values(domainCookies));
|
|
37
|
+
console.log("Importing", cookies.length, "cookies");
|
|
38
|
+
const array = Array.isArray(cookies) ? cookies : Object.values(cookies);
|
|
39
|
+
const put = await Promise.all(
|
|
40
|
+
array.map((cookie) => {
|
|
41
|
+
const fromJSON = Cookie.fromJSON(cookie);
|
|
42
|
+
if (fromJSON) {
|
|
43
|
+
return this.putCookieInternal(fromJSON, store);
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
cookies.push(...put);
|
|
48
|
+
}
|
|
49
|
+
return cookies;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
findCookie(
|
|
53
|
+
domain: string,
|
|
54
|
+
path: string,
|
|
55
|
+
key: string,
|
|
56
|
+
cb: (err: Error | null, cookie: Cookie | null) => void
|
|
57
|
+
) {
|
|
58
|
+
this.waitUntilIdle().finally(() => {
|
|
59
|
+
this.internalStore.findCookie(domain, path, key, cb);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
findCookies(
|
|
64
|
+
domain: string,
|
|
65
|
+
path: string,
|
|
66
|
+
allowSpecialUseDomain: boolean,
|
|
67
|
+
cb: (err: Error | null, cookie: Cookie[]) => void
|
|
68
|
+
) {
|
|
69
|
+
this.waitUntilIdle().finally(() => {
|
|
70
|
+
this.internalStore.findCookies(domain, path, allowSpecialUseDomain, cb);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
putCookie(cookie: Cookie, cb: (err: Error | null) => void) {
|
|
75
|
+
this.internalStore.putCookie(cookie, cb);
|
|
76
|
+
this.internalStore.getAllCookies((err, cookies) => {
|
|
77
|
+
this.serializeCallback(err, cookies);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
updateCookie(
|
|
82
|
+
oldCookie: Cookie,
|
|
83
|
+
newCookie: Cookie,
|
|
84
|
+
cb: (err: Error | null) => void
|
|
85
|
+
) {
|
|
86
|
+
this.internalStore.updateCookie(oldCookie, newCookie, cb);
|
|
87
|
+
this.internalStore.getAllCookies((err, cookies) => {
|
|
88
|
+
this.serializeCallback(err, cookies);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
removeCookie(
|
|
93
|
+
domain: string,
|
|
94
|
+
path: string,
|
|
95
|
+
key: string,
|
|
96
|
+
cb: (err: Error | null) => void
|
|
97
|
+
) {
|
|
98
|
+
this.internalStore.removeCookie(domain, path, key, cb);
|
|
99
|
+
this.internalStore.getAllCookies((err, cookies) => {
|
|
100
|
+
this.serializeCallback(err, cookies);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
removeCookies(domain: string, path: string, cb: (err: Error | null) => void) {
|
|
105
|
+
this.internalStore.removeCookies(domain, path, cb);
|
|
106
|
+
this.internalStore.getAllCookies((err, cookies) => {
|
|
107
|
+
this.serializeCallback(err, cookies);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getAllCookies(cb: (err: Error | null, cookie: Cookie[]) => void) {
|
|
112
|
+
this.waitUntilIdle().finally(() => {
|
|
113
|
+
this.internalStore.getAllCookies(cb);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
waitUntilIdle() {
|
|
118
|
+
return Promise.allSettled(this.tasks).catch(console.error);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private async putCookieInternal(
|
|
122
|
+
cookie: Cookie,
|
|
123
|
+
store: Store
|
|
124
|
+
): Promise<Cookie> {
|
|
125
|
+
await this.waitUntilIdle();
|
|
126
|
+
return await new Promise<Cookie>(
|
|
127
|
+
(
|
|
128
|
+
resolve: (value: PromiseLike<Cookie> | Cookie) => void,
|
|
129
|
+
reject: (reason?: any) => void
|
|
130
|
+
) => {
|
|
131
|
+
store.putCookie(cookie, (err: Error | null) => {
|
|
132
|
+
if (err) {
|
|
133
|
+
reject(err);
|
|
134
|
+
} else {
|
|
135
|
+
resolve(cookie);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private serializeCallback(err: Error | null, cookies: Cookie[]) {
|
|
143
|
+
if (err) {
|
|
144
|
+
console.error(err);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const cookieObjs = cookies.map((cookie: Cookie) => cookie);
|
|
148
|
+
const idx: any = {};
|
|
149
|
+
for (const cookie of cookieObjs) {
|
|
150
|
+
const domain = cookie.domain;
|
|
151
|
+
if (typeof domain === "string") {
|
|
152
|
+
const path: string = cookie.path ?? "/";
|
|
153
|
+
const key: string = cookie.key;
|
|
154
|
+
merge(idx, {
|
|
155
|
+
[domain]: {
|
|
156
|
+
[path]: {
|
|
157
|
+
[key]: cookie.toJSON(),
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const stringify = JSON.stringify(idx, null, 2);
|
|
164
|
+
writeFile(this.filePath, stringify, (err) => {
|
|
165
|
+
if (err) {
|
|
166
|
+
console.error(err);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
package/src/IsCookieRow.ts
CHANGED
package/src/IsExportedCookie.ts
CHANGED
package/src/SpecialCases.ts
CHANGED
package/src/argv.ts
CHANGED
|
@@ -1 +1,20 @@
|
|
|
1
|
+
import minimist from "minimist";
|
|
2
|
+
import { merge } from "lodash";
|
|
3
|
+
|
|
4
|
+
export interface MyParsedArgs extends minimist.ParsedArgs {
|
|
5
|
+
verbose: boolean;
|
|
6
|
+
render?: string;
|
|
7
|
+
fetch?: string;
|
|
8
|
+
cs?: string;
|
|
9
|
+
dump?: string;
|
|
10
|
+
"dump-request-headers"?: string;
|
|
11
|
+
"dump-response-headers"?: string;
|
|
12
|
+
"dump-response-body"?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
1
15
|
export const argv: string[] = process.argv ?? [];
|
|
16
|
+
const minimistArgs: minimist.ParsedArgs = minimist(argv.slice(2));
|
|
17
|
+
const defaultOptions = {
|
|
18
|
+
verbose: false,
|
|
19
|
+
};
|
|
20
|
+
export const parsedArgs: MyParsedArgs = merge(defaultOptions, minimistArgs);
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import CookieQueryStrategy from "./CookieQueryStrategy";
|
|
2
2
|
import { execSimple } from "../utils";
|
|
3
3
|
import { env, HOME } from "../global";
|
|
4
|
-
import { existsSync } from "fs";
|
|
4
|
+
import fs, { existsSync } from "fs";
|
|
5
5
|
import { findAllFiles } from "../findAllFiles";
|
|
6
6
|
import * as crypto from "crypto";
|
|
7
7
|
import * as path from "path";
|
|
8
|
-
import { doSqliteQuery1 } from "../doSqliteQuery1";
|
|
9
8
|
import { merge } from "lodash";
|
|
10
9
|
import { isCookieRow } from "../IsCookieRow";
|
|
11
10
|
import { isExportedCookie } from "../IsExportedCookie";
|
|
12
|
-
import
|
|
13
|
-
import
|
|
11
|
+
import CookieRow from "../CookieRow";
|
|
12
|
+
import ExportedCookie from "../ExportedCookie";
|
|
13
|
+
import { stringToRegex } from "../StringToRegex";
|
|
14
|
+
import { parsedArgs } from "../argv";
|
|
15
|
+
import * as sqlite3 from "sqlite3";
|
|
16
|
+
import { DoSqliteQuery1Params } from "../doSqliteQuery1Params";
|
|
14
17
|
|
|
15
18
|
export default class ChromeCookieQueryStrategy implements CookieQueryStrategy {
|
|
19
|
+
browserName = "Chrome";
|
|
20
|
+
|
|
16
21
|
async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
|
|
17
22
|
if (process.platform !== "darwin") {
|
|
18
23
|
throw new Error("This only works on macOS");
|
|
@@ -40,7 +45,7 @@ async function getPromise1(
|
|
|
40
45
|
file: file,
|
|
41
46
|
});
|
|
42
47
|
} catch (e) {
|
|
43
|
-
if (
|
|
48
|
+
if (parsedArgs.verbose) {
|
|
44
49
|
console.log("Error getting encrypted cookie", e);
|
|
45
50
|
}
|
|
46
51
|
return [];
|
|
@@ -56,10 +61,10 @@ async function getPromise(name: string, domain: string): Promise<CookieRow[]> {
|
|
|
56
61
|
const promises: Promise<CookieRow[]>[] = files.map((file) =>
|
|
57
62
|
getPromise1(name, domain, file)
|
|
58
63
|
);
|
|
59
|
-
const results1:
|
|
64
|
+
const results1: CookieRow[][] = await Promise.all(promises);
|
|
60
65
|
return results1.flat().filter(isCookieRow);
|
|
61
66
|
} catch (error) {
|
|
62
|
-
if (
|
|
67
|
+
if (parsedArgs.verbose) {
|
|
63
68
|
console.log("error", error);
|
|
64
69
|
}
|
|
65
70
|
return [];
|
|
@@ -71,7 +76,7 @@ async function decryptValue(password: string, encryptedValue: Buffer) {
|
|
|
71
76
|
try {
|
|
72
77
|
d = await decrypt(password, encryptedValue);
|
|
73
78
|
} catch (e) {
|
|
74
|
-
if (
|
|
79
|
+
if (parsedArgs.verbose) {
|
|
75
80
|
console.log("Error decrypting cookie", e);
|
|
76
81
|
}
|
|
77
82
|
d = null;
|
|
@@ -99,17 +104,28 @@ Promise<ExportedCookie[]> {
|
|
|
99
104
|
const decryptedValue = await decryptValue(password, encryptedValue);
|
|
100
105
|
const meta = {};
|
|
101
106
|
merge(meta, cookieRow.meta ?? {});
|
|
102
|
-
|
|
107
|
+
const exportedCookie: ExportedCookie = {
|
|
103
108
|
domain: cookieRow.domain,
|
|
104
109
|
name: cookieRow.name,
|
|
105
110
|
value: decryptedValue,
|
|
106
111
|
meta: meta,
|
|
107
112
|
};
|
|
113
|
+
const expiry = cookieRow.expiry;
|
|
114
|
+
const mergeExpiry =
|
|
115
|
+
expiry != null && expiry > 0
|
|
116
|
+
? {
|
|
117
|
+
expiry: new Date(expiry),
|
|
118
|
+
}
|
|
119
|
+
: {
|
|
120
|
+
expiry: "Infinity",
|
|
121
|
+
};
|
|
122
|
+
merge(exportedCookie, mergeExpiry);
|
|
123
|
+
return exportedCookie;
|
|
108
124
|
});
|
|
109
125
|
const results: ExportedCookie[] = (await Promise.all(decrypted)).filter(
|
|
110
126
|
isExportedCookie
|
|
111
127
|
);
|
|
112
|
-
if (
|
|
128
|
+
if (parsedArgs.verbose) {
|
|
113
129
|
console.log("results", results);
|
|
114
130
|
}
|
|
115
131
|
return results;
|
|
@@ -136,39 +152,61 @@ async function getEncryptedChromeCookie({
|
|
|
136
152
|
if (!existsSync(file)) {
|
|
137
153
|
throw new Error(`File ${file} does not exist`);
|
|
138
154
|
}
|
|
139
|
-
if (
|
|
155
|
+
if (parsedArgs.verbose) {
|
|
140
156
|
const s = file.split("/").slice(-3).join("/");
|
|
141
157
|
console.log(`Trying Chrome (at ${s}) cookie ${name} for domain ${domain}`);
|
|
142
158
|
}
|
|
143
159
|
let sql;
|
|
144
160
|
//language=SQL
|
|
145
|
-
sql = "SELECT
|
|
161
|
+
sql = "SELECT * FROM cookies";
|
|
162
|
+
// sql = "SELECT encrypted_value, name, host_key FROM cookies";
|
|
163
|
+
|
|
146
164
|
const wildcardRegexp = /^([*%])$/i;
|
|
147
165
|
const specifiedName = name.match(wildcardRegexp) == null;
|
|
148
166
|
const specifiedDomain = domain.match(wildcardRegexp) == null;
|
|
149
|
-
|
|
167
|
+
const wildcardDomain = domain.match(/[%*]/) != null;
|
|
168
|
+
const queryDomain = specifiedDomain && !wildcardDomain;
|
|
169
|
+
// if we have a wildcard domain, we need to use a regexp
|
|
170
|
+
if (specifiedName || queryDomain) {
|
|
150
171
|
sql += ` WHERE `;
|
|
151
172
|
if (specifiedName) {
|
|
152
173
|
sql += `name = '${name}'`;
|
|
153
|
-
if (
|
|
174
|
+
if (queryDomain) {
|
|
154
175
|
sql += ` AND `;
|
|
155
176
|
}
|
|
156
177
|
}
|
|
157
|
-
if (
|
|
158
|
-
|
|
178
|
+
if (queryDomain) {
|
|
179
|
+
// leading dot replaced with % to match subdomains
|
|
180
|
+
const sqlEmbedDomain = domain.replace(/^[.%]?/, "%");
|
|
181
|
+
sql += `host_key LIKE '${sqlEmbedDomain}';`;
|
|
159
182
|
}
|
|
160
183
|
}
|
|
161
|
-
|
|
184
|
+
if (parsedArgs.verbose) {
|
|
185
|
+
console.log("sql", sql);
|
|
186
|
+
}
|
|
187
|
+
const domainRegexp: RegExp = stringToRegex(domain);
|
|
188
|
+
const sqliteQuery1: CookieRow[] = await doChromeSqliteQuery1({
|
|
162
189
|
file: file,
|
|
163
190
|
sql: sql,
|
|
191
|
+
rowFilter: (row) => {
|
|
192
|
+
return row["host_key"].match(domainRegexp) != null;
|
|
193
|
+
},
|
|
164
194
|
rowTransform: (row) => {
|
|
165
|
-
|
|
195
|
+
const cookieRow = {
|
|
196
|
+
expiry: (row["expires_utc"] / 1000000 - 11644473600) * 1000,
|
|
166
197
|
domain: row["host_key"],
|
|
167
198
|
name: row["name"],
|
|
168
199
|
value: row["encrypted_value"],
|
|
169
200
|
};
|
|
201
|
+
if (parsedArgs.verbose) {
|
|
202
|
+
console.log("CookieRow", cookieRow);
|
|
203
|
+
}
|
|
204
|
+
return cookieRow;
|
|
170
205
|
},
|
|
171
206
|
});
|
|
207
|
+
return sqliteQuery1.filter((row) => {
|
|
208
|
+
return row.domain.match(domainRegexp) != null;
|
|
209
|
+
});
|
|
172
210
|
}
|
|
173
211
|
|
|
174
212
|
async function getChromePassword(): Promise<string> {
|
|
@@ -192,7 +230,7 @@ async function decrypt(
|
|
|
192
230
|
if (!(encryptedData1 instanceof Buffer)) {
|
|
193
231
|
if (Array.isArray(encryptedData1) && encryptedData1[0] instanceof Buffer) {
|
|
194
232
|
[encryptedData1] = encryptedData1;
|
|
195
|
-
if (
|
|
233
|
+
if (parsedArgs.verbose) {
|
|
196
234
|
console.log(
|
|
197
235
|
`encryptedData is an array of buffers, selected first: ${encryptedData1}`
|
|
198
236
|
);
|
|
@@ -202,14 +240,14 @@ async function decrypt(
|
|
|
202
240
|
}
|
|
203
241
|
encryptedData1 = Buffer.from(encryptedData1);
|
|
204
242
|
}
|
|
205
|
-
if (
|
|
243
|
+
if (parsedArgs.verbose) {
|
|
206
244
|
console.log(`Trying to decrypt with password ${password}`);
|
|
207
245
|
}
|
|
208
246
|
return new Promise((resolve, reject) => {
|
|
209
247
|
crypto.pbkdf2(password, "saltysalt", 1003, 16, "sha1", (error, buffer) => {
|
|
210
248
|
try {
|
|
211
249
|
if (error) {
|
|
212
|
-
if (
|
|
250
|
+
if (parsedArgs.verbose) {
|
|
213
251
|
console.log("Error doing pbkdf2", error);
|
|
214
252
|
}
|
|
215
253
|
reject(error);
|
|
@@ -217,7 +255,7 @@ async function decrypt(
|
|
|
217
255
|
}
|
|
218
256
|
|
|
219
257
|
if (buffer.length !== 16) {
|
|
220
|
-
if (
|
|
258
|
+
if (parsedArgs.verbose) {
|
|
221
259
|
console.log(
|
|
222
260
|
"Error doing pbkdf2, buffer length is not 16",
|
|
223
261
|
buffer.length
|
|
@@ -237,7 +275,7 @@ async function decrypt(
|
|
|
237
275
|
}
|
|
238
276
|
|
|
239
277
|
if (encryptedData1.length % 16 !== 0) {
|
|
240
|
-
if (
|
|
278
|
+
if (parsedArgs.verbose) {
|
|
241
279
|
console.log(
|
|
242
280
|
"Error doing pbkdf2, encryptedData length is not a multiple of 16",
|
|
243
281
|
encryptedData1.length
|
|
@@ -251,7 +289,7 @@ async function decrypt(
|
|
|
251
289
|
try {
|
|
252
290
|
decipher.final("utf-8");
|
|
253
291
|
} catch (e) {
|
|
254
|
-
if (
|
|
292
|
+
if (parsedArgs.verbose) {
|
|
255
293
|
console.log("Error doing decipher.final()", e);
|
|
256
294
|
}
|
|
257
295
|
reject(e);
|
|
@@ -271,3 +309,47 @@ async function decrypt(
|
|
|
271
309
|
});
|
|
272
310
|
});
|
|
273
311
|
}
|
|
312
|
+
|
|
313
|
+
export async function doChromeSqliteQuery1({
|
|
314
|
+
file,
|
|
315
|
+
sql,
|
|
316
|
+
rowFilter = () => true,
|
|
317
|
+
rowTransform,
|
|
318
|
+
}: DoSqliteQuery1Params): Promise<CookieRow[]> {
|
|
319
|
+
if (!file || (file && !fs.existsSync(file))) {
|
|
320
|
+
throw new Error(`doSqliteQuery1: file ${file} does not exist`);
|
|
321
|
+
}
|
|
322
|
+
const db = new sqlite3.Database(file);
|
|
323
|
+
return new Promise((resolve, reject) => {
|
|
324
|
+
db.all(sql, (err: Error, rows: any[]) => {
|
|
325
|
+
if (err) {
|
|
326
|
+
reject(err);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const rows1: any[] = rows;
|
|
330
|
+
if (rows1 == null || rows1.length === 0) {
|
|
331
|
+
resolve([]);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (Array.isArray(rows1)) {
|
|
335
|
+
const cookieRows: CookieRow[] = rows1
|
|
336
|
+
.filter(rowFilter)
|
|
337
|
+
.map((row: any) => {
|
|
338
|
+
const newVar = {
|
|
339
|
+
meta: {
|
|
340
|
+
file: file,
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
const cookieRow: CookieRow = rowTransform(row);
|
|
344
|
+
return merge(newVar, cookieRow);
|
|
345
|
+
});
|
|
346
|
+
resolve(cookieRows);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
if (parsedArgs.verbose) {
|
|
350
|
+
console.log(`doSqliteQuery1: rows ${JSON.stringify(rows1)}`);
|
|
351
|
+
}
|
|
352
|
+
resolve([rows1]);
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
}
|