@mherod/get-cookie 1.1.5 → 1.1.6
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/cli.js +89 -0
- package/index.js +49 -185
- package/package.json +2 -2
- package/utils.js +76 -0
package/cli.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const {getFirefoxCookie, getChromeCookie} = require("./index");
|
|
4
|
+
const {printStringValue} = require("./utils");
|
|
5
|
+
|
|
6
|
+
if (process.argv) {
|
|
7
|
+
if (process.argv.length > 2) {
|
|
8
|
+
const name = process.argv[2];
|
|
9
|
+
const domain = process.argv[3] ?? '%';
|
|
10
|
+
|
|
11
|
+
if (process.argv.includes('--verbose')) {
|
|
12
|
+
process.env.VERBOSE = "true";
|
|
13
|
+
}
|
|
14
|
+
if (process.argv.includes("--chrome-only")) {
|
|
15
|
+
process.env.CHROME_ONLY = "true";
|
|
16
|
+
}
|
|
17
|
+
if (process.argv.includes("--firefox-only")) {
|
|
18
|
+
process.env.FIREFOX_ONLY = "true";
|
|
19
|
+
}
|
|
20
|
+
if (process.argv.includes("--ignore-expired")) {
|
|
21
|
+
process.env.IGNORE_EXPIRED = "true";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (process.env.VERBOSE) {
|
|
25
|
+
console.log("Verbose mode", process.argv);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (process.env.CHROME_ONLY) {
|
|
29
|
+
if (process.env.VERBOSE) {
|
|
30
|
+
console.log('chrome only');
|
|
31
|
+
}
|
|
32
|
+
getChromeCookie({name, domain})
|
|
33
|
+
.then(cookie => {
|
|
34
|
+
if (cookie && cookie.length > 0) {
|
|
35
|
+
printStringValue(cookie);
|
|
36
|
+
} else {
|
|
37
|
+
console.log('No cookie found');
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
.catch(err => {
|
|
41
|
+
if (process.env.VERBOSE) {
|
|
42
|
+
console.error(err);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
} else if (process.env.FIREFOX_ONLY) {
|
|
46
|
+
if (process.env.VERBOSE) {
|
|
47
|
+
console.log('firefox only');
|
|
48
|
+
}
|
|
49
|
+
getFirefoxCookie({name, domain})
|
|
50
|
+
.then(cookie => {
|
|
51
|
+
if (cookie && cookie.length > 0) {
|
|
52
|
+
printStringValue(cookie);
|
|
53
|
+
} else {
|
|
54
|
+
console.log('No cookie found');
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
.catch(err => {
|
|
58
|
+
if (process.env.VERBOSE) {
|
|
59
|
+
console.error("Error getting Firefox cookie", err);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
} else {
|
|
63
|
+
getChromeCookie({name, domain})
|
|
64
|
+
.catch(err => {
|
|
65
|
+
if (process.env.VERBOSE) {
|
|
66
|
+
console.error("Error getting Chrome cookie", err);
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
.then(r => {
|
|
70
|
+
if (typeof r === 'string' && r.trim().length > 0) {
|
|
71
|
+
return r;
|
|
72
|
+
} else {
|
|
73
|
+
return getFirefoxCookie({name, domain})
|
|
74
|
+
.catch(err => {
|
|
75
|
+
if (process.env.VERBOSE) {
|
|
76
|
+
console.error("Error getting Firefox cookie", err);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
.catch((e) => {
|
|
82
|
+
if (process.env.VERBOSE) {
|
|
83
|
+
console.error("Error getting Chrome or Firefox cookie", e);
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
.then(printStringValue);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
package/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const crypto = require('crypto');
|
|
4
|
-
const {exec} = require("child_process");
|
|
5
4
|
const fs = require("fs");
|
|
5
|
+
const {execSimple} = require("./utils");
|
|
6
6
|
|
|
7
7
|
if (process.platform !== 'darwin') {
|
|
8
8
|
throw new Error('This script only works on macOS');
|
|
@@ -13,20 +13,7 @@ if (process.platform !== 'darwin') {
|
|
|
13
13
|
* @returns {Promise<string>}
|
|
14
14
|
*/
|
|
15
15
|
async function getChromePassword() {
|
|
16
|
-
return await
|
|
17
|
-
exec("security find-generic-password -w -s \"Chrome Safe Storage\"", (error, stdout, stderr) => {
|
|
18
|
-
if (error) {
|
|
19
|
-
reject(error);
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
if (stderr) {
|
|
23
|
-
reject(error);
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
let s = stdout.toString().trim();
|
|
27
|
-
resolve(s);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
16
|
+
return await execSimple("security find-generic-password -w -s \"Chrome Safe Storage\"");
|
|
30
17
|
}
|
|
31
18
|
|
|
32
19
|
async function getCookie(name, domain) {
|
|
@@ -46,8 +33,11 @@ async function getFirefoxCookie({name, domain}) {
|
|
|
46
33
|
if (domain && typeof domain !== 'string') {
|
|
47
34
|
throw new Error('domain must be a string');
|
|
48
35
|
}
|
|
49
|
-
const file = await
|
|
50
|
-
|
|
36
|
+
const [file] = await findAllFiles({
|
|
37
|
+
path: `${process.env.HOME}/Library/Application Support/Firefox/Profiles`,
|
|
38
|
+
name: "cookies.sqlite"
|
|
39
|
+
})
|
|
40
|
+
if (file && !fs.existsSync(file)) {
|
|
51
41
|
throw new Error(`File ${file} does not exist`);
|
|
52
42
|
}
|
|
53
43
|
if (process.env.VERBOSE) {
|
|
@@ -134,33 +124,6 @@ async function doSqliteQuery1(file, sql) {
|
|
|
134
124
|
});
|
|
135
125
|
}
|
|
136
126
|
|
|
137
|
-
async function doSqliteQuery(file, sql) {
|
|
138
|
-
const command = `sqlite3 "${file}" "${sql}"`;
|
|
139
|
-
if (process.env.VERBOSE) {
|
|
140
|
-
console.log(command);
|
|
141
|
-
}
|
|
142
|
-
return await new Promise((resolve, reject) => {
|
|
143
|
-
exec(command, {encoding: 'binary', maxBuffer: 5 * 1024}, (error, stdout, stderr) => {
|
|
144
|
-
if (error) {
|
|
145
|
-
reject(error);
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
if (stderr) {
|
|
149
|
-
reject(error);
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
let stdoutAsBuffer = stdout;
|
|
153
|
-
if (typeof stdoutAsBuffer === 'string' && stdoutAsBuffer.length > 0) {
|
|
154
|
-
// noinspection JSCheckFunctionSignatures
|
|
155
|
-
stdoutAsBuffer = Buffer.from(stdoutAsBuffer, 'binary').slice(0, -1);
|
|
156
|
-
}
|
|
157
|
-
if (stdoutAsBuffer && stdoutAsBuffer.length > 0) {
|
|
158
|
-
resolve(stdoutAsBuffer);
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
|
|
164
127
|
/**
|
|
165
128
|
*
|
|
166
129
|
* @param {string} password
|
|
@@ -213,8 +176,8 @@ async function decrypt(password, encryptedData) {
|
|
|
213
176
|
return;
|
|
214
177
|
}
|
|
215
178
|
|
|
216
|
-
let decoded = decipher.update(encryptedData1, 'binary', 'utf8');
|
|
217
|
-
|
|
179
|
+
// let decoded = decipher.update(encryptedData1, 'binary', 'utf8');
|
|
180
|
+
let decoded = decipher.update(encryptedData);
|
|
218
181
|
try {
|
|
219
182
|
decipher.final('utf-8');
|
|
220
183
|
} catch (e) {
|
|
@@ -242,28 +205,38 @@ async function decrypt(password, encryptedData) {
|
|
|
242
205
|
/**
|
|
243
206
|
*
|
|
244
207
|
* @param {string|undefined} name
|
|
245
|
-
* @param {string
|
|
208
|
+
* @param {string} domain
|
|
246
209
|
* @returns {Promise<string>}
|
|
247
210
|
*/
|
|
248
|
-
async function getChromeCookie({name, domain}) {
|
|
211
|
+
async function getChromeCookie({name, domain = '%'}) {
|
|
249
212
|
if (name && typeof name !== 'string') {
|
|
250
213
|
throw new Error('name must be a string');
|
|
251
214
|
}
|
|
252
|
-
if (
|
|
215
|
+
if (typeof domain !== 'string') {
|
|
253
216
|
throw new Error('domain must be a string');
|
|
254
217
|
}
|
|
255
218
|
const chromePasswordPromise = getChromePassword();
|
|
256
|
-
const
|
|
219
|
+
const encryptedDataItems = await findAllFiles({
|
|
257
220
|
path: defaultChromeRoot,
|
|
258
221
|
name: 'Cookies'
|
|
259
222
|
}).then(files => {
|
|
260
|
-
const
|
|
223
|
+
const promises = files.map(file => {
|
|
261
224
|
return getEncryptedChromeCookie({
|
|
262
225
|
name: name,
|
|
263
226
|
domain: domain,
|
|
264
227
|
file: file
|
|
228
|
+
}).catch(e => {
|
|
229
|
+
if (process.env.VERBOSE) {
|
|
230
|
+
console.log("Error getting encrypted cookie", e);
|
|
231
|
+
}
|
|
232
|
+
return null;
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
const promise = Promise.all(promises).then(results => {
|
|
236
|
+
return results.filter(result => {
|
|
237
|
+
return result;
|
|
265
238
|
});
|
|
266
|
-
})
|
|
239
|
+
});
|
|
267
240
|
if (process.env.VERBOSE) {
|
|
268
241
|
console.log('promise', promise);
|
|
269
242
|
}
|
|
@@ -275,22 +248,32 @@ async function getChromeCookie({name, domain}) {
|
|
|
275
248
|
return [];
|
|
276
249
|
});
|
|
277
250
|
const password = await chromePasswordPromise;
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
let s;
|
|
282
|
-
try {
|
|
283
|
-
s = await decrypt(password, encryptedData);
|
|
284
|
-
} catch (e) {
|
|
251
|
+
const decrypted = encryptedDataItems.filter(encryptedData => {
|
|
252
|
+
return encryptedData != null && encryptedData.length > 0;
|
|
253
|
+
}).map(async encryptedData => {
|
|
285
254
|
if (process.env.VERBOSE) {
|
|
286
|
-
console.
|
|
255
|
+
console.log("Received encrypted", encryptedData);
|
|
287
256
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
257
|
+
let decrypted;
|
|
258
|
+
try {
|
|
259
|
+
decrypted = await decrypt(password, encryptedData);
|
|
260
|
+
} catch (e) {
|
|
261
|
+
if (process.env.VERBOSE) {
|
|
262
|
+
console.log("Error decrypting cookie", e);
|
|
263
|
+
}
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
if (decrypted) {
|
|
267
|
+
if (process.env.VERBOSE) {
|
|
268
|
+
console.log("Decrypted", decrypted);
|
|
269
|
+
}
|
|
270
|
+
return decrypted;
|
|
271
|
+
}
|
|
272
|
+
return null;
|
|
273
|
+
});
|
|
274
|
+
return await Promise.all(decrypted).then(results => {
|
|
275
|
+
return results.find(result => typeof result === 'string' && result.length > 0);
|
|
276
|
+
});
|
|
294
277
|
}
|
|
295
278
|
|
|
296
279
|
/**
|
|
@@ -361,40 +344,6 @@ async function findAllFiles({path, name, rootSegments = path.split('/').length,
|
|
|
361
344
|
return files;
|
|
362
345
|
}
|
|
363
346
|
|
|
364
|
-
/**
|
|
365
|
-
*
|
|
366
|
-
* @param path
|
|
367
|
-
* @param name
|
|
368
|
-
* @returns {Promise<string>}
|
|
369
|
-
*/
|
|
370
|
-
async function findFile(path, name) {
|
|
371
|
-
return await new Promise((resolve, reject) => {
|
|
372
|
-
for (const file of fs.readdirSync(path)) {
|
|
373
|
-
const filePath = path + '/' + file;
|
|
374
|
-
const stat = fs.statSync(filePath);
|
|
375
|
-
if (stat.isDirectory()) {
|
|
376
|
-
findFile(filePath, name).then(resolve).catch(reject);
|
|
377
|
-
} else if (file === name) {
|
|
378
|
-
resolve(filePath);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
function printStringValue(r) {
|
|
385
|
-
if (process.env.VERBOSE) {
|
|
386
|
-
console.log("Printing value", r);
|
|
387
|
-
}
|
|
388
|
-
if (r) {
|
|
389
|
-
if (typeof r === 'string') {
|
|
390
|
-
console.log(r);
|
|
391
|
-
} else if (r.toString) {
|
|
392
|
-
// noinspection JSCheckFunctionSignatures
|
|
393
|
-
console.log(r.toString('utf8'));
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
347
|
// noinspection JSUnusedGlobalSymbols
|
|
399
348
|
module.exports = {
|
|
400
349
|
getDecryptedCookie: getChromeCookie,
|
|
@@ -402,88 +351,3 @@ module.exports = {
|
|
|
402
351
|
getFirefoxCookie,
|
|
403
352
|
getCookie
|
|
404
353
|
};
|
|
405
|
-
|
|
406
|
-
if (process.argv) {
|
|
407
|
-
if (process.argv.length > 2) {
|
|
408
|
-
const name = process.argv[2];
|
|
409
|
-
const domain = process.argv[3] ?? '%';
|
|
410
|
-
|
|
411
|
-
if (process.argv.includes('--verbose')) {
|
|
412
|
-
process.env.VERBOSE = "true";
|
|
413
|
-
}
|
|
414
|
-
if (process.argv.includes("--chrome-only")) {
|
|
415
|
-
process.env.CHROME_ONLY = "true";
|
|
416
|
-
}
|
|
417
|
-
if (process.argv.includes("--firefox-only")) {
|
|
418
|
-
process.env.FIREFOX_ONLY = "true";
|
|
419
|
-
}
|
|
420
|
-
if (process.argv.includes("--ignore-expired")) {
|
|
421
|
-
process.env.IGNORE_EXPIRED = "true";
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
if (process.env.VERBOSE) {
|
|
425
|
-
console.log("Verbose mode", process.argv);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if (process.env.CHROME_ONLY) {
|
|
429
|
-
if (process.env.VERBOSE) {
|
|
430
|
-
console.log('chrome only');
|
|
431
|
-
}
|
|
432
|
-
getChromeCookie({name, domain})
|
|
433
|
-
.then(cookie => {
|
|
434
|
-
if (cookie && cookie.length > 0) {
|
|
435
|
-
printStringValue(cookie);
|
|
436
|
-
} else {
|
|
437
|
-
console.log('No cookie found');
|
|
438
|
-
}
|
|
439
|
-
})
|
|
440
|
-
.catch(err => {
|
|
441
|
-
if (process.env.VERBOSE) {
|
|
442
|
-
console.error(err);
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
} else if (process.env.FIREFOX_ONLY) {
|
|
446
|
-
if (process.env.VERBOSE) {
|
|
447
|
-
console.log('firefox only');
|
|
448
|
-
}
|
|
449
|
-
getFirefoxCookie({name, domain})
|
|
450
|
-
.then(cookie => {
|
|
451
|
-
if (cookie && cookie.length > 0) {
|
|
452
|
-
printStringValue(cookie);
|
|
453
|
-
} else {
|
|
454
|
-
console.log('No cookie found');
|
|
455
|
-
}
|
|
456
|
-
})
|
|
457
|
-
.catch(err => {
|
|
458
|
-
if (process.env.VERBOSE) {
|
|
459
|
-
console.error("Error getting Firefox cookie", err);
|
|
460
|
-
}
|
|
461
|
-
});
|
|
462
|
-
} else {
|
|
463
|
-
getChromeCookie({name, domain})
|
|
464
|
-
.catch(err => {
|
|
465
|
-
if (process.env.VERBOSE) {
|
|
466
|
-
console.error("Error getting Chrome cookie", err);
|
|
467
|
-
}
|
|
468
|
-
})
|
|
469
|
-
.then(r => {
|
|
470
|
-
if (typeof r === 'string' && r.trim().length > 0) {
|
|
471
|
-
return r;
|
|
472
|
-
} else {
|
|
473
|
-
return getFirefoxCookie({name, domain})
|
|
474
|
-
.catch(err => {
|
|
475
|
-
if (process.env.VERBOSE) {
|
|
476
|
-
console.error("Error getting Firefox cookie", err);
|
|
477
|
-
}
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
})
|
|
481
|
-
.catch((e) => {
|
|
482
|
-
if (process.env.VERBOSE) {
|
|
483
|
-
console.error("Error getting Chrome or Firefox cookie", e);
|
|
484
|
-
}
|
|
485
|
-
})
|
|
486
|
-
.then(printStringValue);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mherod/get-cookie",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "Node.js module for querying a local user's Chrome cookie",
|
|
5
5
|
"main": "index.js",
|
|
6
|
-
"bin": "
|
|
6
|
+
"bin": "cli.js",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
package/utils.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// noinspection JSUnusedGlobalSymbols
|
|
2
|
+
|
|
3
|
+
const {exec} = require('child_process');
|
|
4
|
+
|
|
5
|
+
async function execSimple(command) {
|
|
6
|
+
if (typeof command !== 'string') {
|
|
7
|
+
throw new TypeError('execSimple: command must be a string');
|
|
8
|
+
}
|
|
9
|
+
if (process.env.VERBOSE) {
|
|
10
|
+
console.log(command);
|
|
11
|
+
}
|
|
12
|
+
return await new Promise((resolve, reject) => {
|
|
13
|
+
exec(command, {encoding: 'binary', maxBuffer: 5 * 1024}, (error, stdout, stderr) => {
|
|
14
|
+
if (error) {
|
|
15
|
+
reject(error);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (stderr) {
|
|
19
|
+
reject(error);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (stdout) {
|
|
23
|
+
resolve(stdout.toString('utf8').trim());
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function execAsBuffer(command) {
|
|
30
|
+
if (typeof command !== 'string') {
|
|
31
|
+
throw new TypeError('execAsBuffer: command must be a string');
|
|
32
|
+
}
|
|
33
|
+
if (process.env.VERBOSE) {
|
|
34
|
+
console.log(command);
|
|
35
|
+
}
|
|
36
|
+
return await new Promise((resolve, reject) => {
|
|
37
|
+
exec(command, {encoding: 'binary', maxBuffer: 5 * 1024}, (error, stdout, stderr) => {
|
|
38
|
+
if (error) {
|
|
39
|
+
reject(error);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (stderr) {
|
|
43
|
+
reject(error);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
let stdoutAsBuffer = stdout;
|
|
47
|
+
if (typeof stdoutAsBuffer === 'string' && stdoutAsBuffer.length > 0) {
|
|
48
|
+
// noinspection JSCheckFunctionSignatures
|
|
49
|
+
stdoutAsBuffer = Buffer.from(stdoutAsBuffer, 'binary').slice(0, -1);
|
|
50
|
+
}
|
|
51
|
+
if (stdoutAsBuffer && stdoutAsBuffer.length > 0) {
|
|
52
|
+
resolve(stdoutAsBuffer);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function printStringValue(r) {
|
|
59
|
+
if (process.env.VERBOSE) {
|
|
60
|
+
console.log("Printing value", r);
|
|
61
|
+
}
|
|
62
|
+
if (r) {
|
|
63
|
+
if (typeof r === 'string') {
|
|
64
|
+
console.log(r);
|
|
65
|
+
} else if (r.toString) {
|
|
66
|
+
// noinspection JSCheckFunctionSignatures
|
|
67
|
+
console.log(r.toString('utf8'));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
execSimple: execSimple,
|
|
74
|
+
execAsBuffer: execAsBuffer,
|
|
75
|
+
printStringValue: printStringValue
|
|
76
|
+
};
|