@mherod/get-cookie 1.1.0 → 1.1.3

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.
Files changed (2) hide show
  1. package/index.js +84 -16
  2. package/package.json +2 -2
package/index.js CHANGED
@@ -70,19 +70,24 @@ async function getFirefoxCookie({name, domain}) {
70
70
  return await doSqliteQuery1(file, sql);
71
71
  }
72
72
 
73
- async function getEncryptedChromeCookie(name, domain) {
73
+ const defaultChromeRoot = `${process.env.HOME}/Library/Application Support/Google/Chrome`;
74
+ const defaultChromeCookies = `${defaultChromeRoot}/Default/Cookies`;
75
+
76
+ async function getEncryptedChromeCookie(name, domain, file = defaultChromeCookies) {
74
77
  if (name && typeof name !== 'string') {
75
78
  throw new Error('name must be a string');
76
79
  }
77
80
  if (domain && typeof domain !== 'string') {
78
81
  throw new Error('domain must be a string');
79
82
  }
80
- const file = `${process.env.HOME}/Library/Application Support/Google/Chrome/Default/Cookies`;
83
+ if (file && typeof file !== 'string') {
84
+ throw new Error('file must be a string');
85
+ }
81
86
  if (!fs.existsSync(file)) {
82
87
  throw new Error(`File ${file} does not exist`);
83
88
  }
84
89
  if (process.env.VERBOSE) {
85
- console.log(`Trying Chrome cookie ${name} for domain ${domain}`);
90
+ console.log(`Trying Chrome (at ${file}) cookie ${name} for domain ${domain}`);
86
91
  }
87
92
  let sql;
88
93
  sql = `SELECT encrypted_value FROM cookies`;
@@ -112,13 +117,16 @@ async function doSqliteQuery1(file, sql) {
112
117
  }
113
118
  const rows1 = rows;
114
119
  if (rows1.length === 0) {
120
+ if (process.env.VERBOSE) {
121
+ console.log(`No rows found`);
122
+ }
115
123
  resolve(null);
116
124
  return;
117
125
  }
118
126
  if (Array.isArray(rows1)) {
119
127
  // noinspection JSCheckFunctionSignatures
120
128
  const [value] = rows1.flatMap(row => Object.values(row));
121
- resolve(value);
129
+ resolve(Buffer.from(value));
122
130
  return;
123
131
  }
124
132
  resolve(rows1);
@@ -161,10 +169,11 @@ async function doSqliteQuery(file, sql) {
161
169
  */
162
170
  async function decrypt(password, encryptedData) {
163
171
  if (typeof password !== 'string') {
164
- throw new Error('password must be a string');
172
+ throw new Error('password must be a string: ' + password);
165
173
  }
166
- if (typeof encryptedData !== 'object') {
167
- throw new Error('encryptedData must be a object');
174
+ const encryptedData1 = encryptedData;
175
+ if (encryptedData1 == null || typeof encryptedData1 !== 'object') {
176
+ throw new Error('encryptedData must be a object: ' + encryptedData1);
168
177
  }
169
178
  if (process.env.VERBOSE) {
170
179
  console.log(`Trying to decrypt with password ${password}`);
@@ -172,7 +181,6 @@ async function decrypt(password, encryptedData) {
172
181
  return await new Promise((resolve, reject) => {
173
182
  crypto.pbkdf2(password, 'saltysalt', 1003, 16, 'sha1', (error, buffer) => {
174
183
  try {
175
-
176
184
  if (error) {
177
185
  if (process.env.VERBOSE) {
178
186
  console.log("Error doing pbkdf2", error);
@@ -180,6 +188,7 @@ async function decrypt(password, encryptedData) {
180
188
  reject(error);
181
189
  return;
182
190
  }
191
+
183
192
  if (buffer.length !== 16) {
184
193
  if (process.env.VERBOSE) {
185
194
  console.log("Error doing pbkdf2, buffer length is not 16", buffer.length);
@@ -191,17 +200,20 @@ async function decrypt(password, encryptedData) {
191
200
  const iv = new Buffer.from(new Array(17).join(' '), 'binary');
192
201
  const decipher = crypto.createDecipheriv('aes-128-cbc', buffer, iv);
193
202
  decipher.setAutoPadding(false);
194
- encryptedData = encryptedData.slice(3);
195
203
 
196
- if (encryptedData.length % 16 !== 0) {
204
+ if (encryptedData1 && encryptedData1.slice) {
205
+ encryptedData = encryptedData1.slice(3);
206
+ }
207
+
208
+ if (encryptedData1.length % 16 !== 0) {
197
209
  if (process.env.VERBOSE) {
198
- console.log("Error doing pbkdf2, encryptedData length is not a multiple of 16", encryptedData.length);
210
+ console.log("Error doing pbkdf2, encryptedData length is not a multiple of 16", encryptedData1.length);
199
211
  }
200
212
  reject(new Error('encryptedData length is not a multiple of 16'));
201
213
  return;
202
214
  }
203
215
 
204
- let decoded = decipher.update(encryptedData, 'binary', 'utf8');
216
+ let decoded = decipher.update(encryptedData1, 'binary', 'utf8');
205
217
  // let decoded = decipher.update(encryptedData);
206
218
  try {
207
219
  decipher.final('utf-8');
@@ -240,8 +252,11 @@ async function getChromeCookie({name, domain}) {
240
252
  if (domain && typeof domain !== 'string') {
241
253
  throw new Error('domain must be a string');
242
254
  }
243
- const password = await getChromePassword();
244
- const encryptedData = await getEncryptedChromeCookie(name, domain);
255
+ const chromePasswordPromise = getChromePassword();
256
+ const [encryptedData] = await findAllFiles({path: defaultChromeRoot, name: 'Cookies'}).then(files => {
257
+ return Promise.all(files.map(file => getEncryptedChromeCookie(name, domain, file)));
258
+ });
259
+ const password = await chromePasswordPromise;
245
260
  if (process.env.VERBOSE) {
246
261
  console.log("Received encrypted", encryptedData);
247
262
  }
@@ -249,7 +264,9 @@ async function getChromeCookie({name, domain}) {
249
264
  try {
250
265
  s = await decrypt(password, encryptedData);
251
266
  } catch (e) {
252
- console.error(e);
267
+ if (process.env.VERBOSE) {
268
+ console.error("Error decrypting", e);
269
+ }
253
270
  throw new Error('Failed to decrypt');
254
271
  }
255
272
  if (process.env.VERBOSE) {
@@ -258,6 +275,57 @@ async function getChromeCookie({name, domain}) {
258
275
  return s;
259
276
  }
260
277
 
278
+ /**
279
+ *
280
+ * @param path
281
+ * @param name
282
+ * @param rootSegments
283
+ * @param maxDepth
284
+ * @returns {Promise<[string]>}
285
+ */
286
+ async function findAllFiles({path, name, rootSegments = path.split('/').length, maxDepth = 2}) {
287
+ if (typeof path !== 'string') {
288
+ throw new Error('path must be a string');
289
+ }
290
+ if (typeof name !== 'string') {
291
+ throw new Error('name must be a string');
292
+ }
293
+ if (process.env.VERBOSE) {
294
+ console.log(`Searching for ${name} in ${path}`);
295
+ }
296
+ const files = [];
297
+ for (const file of fs.readdirSync(path)) {
298
+ const filePath = path + '/' + file;
299
+ const stat = fs.statSync(filePath);
300
+ if (stat.isDirectory()) {
301
+ if (filePath.split('/').length < rootSegments + maxDepth) {
302
+ try {
303
+ const subFiles = await findAllFiles({
304
+ path: filePath,
305
+ name: name,
306
+ rootSegments: rootSegments,
307
+ maxDepth: 2
308
+ });
309
+ files.push(...subFiles);
310
+ } catch (e) {
311
+ if (process.env.VERBOSE) {
312
+ console.error(e);
313
+ }
314
+ }
315
+ }
316
+ } else if (file === name) {
317
+ files.push(filePath);
318
+ }
319
+ }
320
+ if (process.env.VERBOSE) {
321
+ if (files.length > 0) {
322
+ console.log(`Found ${(files.length)} ${name} files`);
323
+ console.log(files);
324
+ }
325
+ }
326
+ return files;
327
+ }
328
+
261
329
  /**
262
330
  *
263
331
  * @param path
@@ -303,7 +371,7 @@ module.exports = {
303
371
  if (process.argv) {
304
372
  if (process.argv.length > 2) {
305
373
  const name = process.argv[2];
306
- const domain = process.argv[3];
374
+ const domain = process.argv[3] ?? '%';
307
375
 
308
376
  if (process.argv.includes('--verbose')) {
309
377
  process.env.VERBOSE = "true";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mherod/get-cookie",
3
- "version": "1.1.0",
3
+ "version": "1.1.3",
4
4
  "description": "Node.js module for querying a local user's Chrome cookie",
5
5
  "main": "index.js",
6
6
  "bin": "index.js",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "scripts": {
11
11
  "test": "echo \"Error: no test specified\" && exit 1",
12
- "install": "npm install --force --global ."
12
+ "installGlobal": "rm -rf /usr/local/bin/get-cookie ; npm install --force --global ."
13
13
  },
14
14
  "keywords": [],
15
15
  "author": "Matthew Herod",