From cc8cfaa12602e099fcf295908753be7078c97a9f Mon Sep 17 00:00:00 2001 From: Andrew Kaiser Date: Thu, 27 Sep 2018 22:03:40 -0400 Subject: [PATCH] rely on spawnSync to escape characters --- package.json | 2 +- src/exec-bitwarden-cli.js | 8 ++++---- src/exec-dmenu.js | 4 ++-- src/index.js | 21 ++++++++++----------- src/util/obfuscate/bitwarden-cli.js | 4 ++-- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index d33a821..58bbd92 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bitwarden-dmenu", - "version": "1.2.2", + "version": "1.2.3", "description": "dmenu for bitwarden password manager.", "keywords": [ "bitwarden", diff --git a/src/exec-bitwarden-cli.js b/src/exec-bitwarden-cli.js index a963da2..6bb8041 100644 --- a/src/exec-bitwarden-cli.js +++ b/src/exec-bitwarden-cli.js @@ -1,13 +1,13 @@ const path = require('path') -const { execSync } = require('child_process') +const { spawnSync } = require('child_process') const obfuscate = require('./util/obfuscate/bitwarden-cli') const bwExecutable = path.resolve(__dirname, '../node_modules/.bin/bw') -module.exports = args => { - const execCommand = `${bwExecutable} ${args}` +module.exports = (...args) => { + const execCommand = `${bwExecutable} ${args.join(' ')}` console.debug('$', obfuscate(execCommand)) try { - const stdout = execSync(execCommand) + const { stdout } = spawnSync(bwExecutable, args) return stdout.toString().replace(/\n$/, '') } catch (e) { throw new Error(e.stdout.toString().trim()) diff --git a/src/exec-dmenu.js b/src/exec-dmenu.js index a8a7800..18e669c 100644 --- a/src/exec-dmenu.js +++ b/src/exec-dmenu.js @@ -1,6 +1,6 @@ -const { exec, execSync, spawn } = require('child_process') +const { exec } = require('child_process') -module.exports = (choices = '\n', args = '') => +module.exports = (...args) => choices => new Promise((resolve, reject) => { let choice = '' const error = [] diff --git a/src/index.js b/src/index.js index d0cf1d1..a67539a 100644 --- a/src/index.js +++ b/src/index.js @@ -19,19 +19,17 @@ const getSessionVar = async ({ saveSession, sessionFile }) => { } else { console.debug('no session file found.') // prompt for password in dmenu - const password = await dmenuRun('\n', '-p Password: -nf black -nb black') + const password = await dmenuRun('-p Password: -nf black -nb black')('\n') if (!password) throw new Error('no password given!') - const escapedPw = password.replace(/'/g, String.raw`'\''`) - const session = bwRun(`unlock '${escapedPw}' --raw`) + const session = bwRun('unlock', password, '--raw') writeFileSync(sessionFile, session) console.debug('saved new session file.') return session } } else { - const password = await dmenuRun('\n', '-p Password: -nf black -nb black') + const password = await dmenuRun('-p Password: -nf black -nb black')('\n') if (!password) throw new Error('no password given!') - const escapedPw = password.replace(/'/g, String.raw`'\''`) - const session = bwRun(`unlock '${escapedPw}' --raw`) + const session = bwRun('unlock', password, '--raw') return session } } @@ -39,18 +37,18 @@ const getSessionVar = async ({ saveSession, sessionFile }) => { // sync the password accounts with the remote server // if --sync-vault-after < time since the last sync const syncIfNecessary = ({ session, oldestAllowedVaultSync }) => { - const last = bwRun(`sync --last --session=${session}`) + const last = bwRun('sync', '--last', `--session=${session}`) const timeSinceSync = (new Date().getTime() - new Date(last).getTime()) / 1000 if (timeSinceSync > oldestAllowedVaultSync) { console.debug('syncing vault...') - bwRun(`sync --session=${session}`) + bwRun('sync', `--session=${session}`) console.debug(`sync complete, last sync was ${last}`) } } // get the list all password accounts in the vault const getAccounts = ({ session }) => { - const listStr = bwRun(`list items --session=${session}`) + const listStr = bwRun('list', 'items', `--session=${session}`) const list = JSON.parse(listStr) return list } @@ -62,7 +60,7 @@ const chooseAccount = async ({ list }) => { .filter(a => a.type === LOGIN_TYPE) .map(a => `${a.name}: ${a.login.username}`) // -i allows case insensitive matching - const selected = await dmenuRun(accountNames.join('\n'), '-i') + const selected = await dmenuRun('-i')(accountNames.join('\n')) const index = accountNames.indexOf(selected) const selectedAccount = list[index] console.debug('selected account:\n', obfuscate(selectedAccount)) @@ -71,6 +69,7 @@ const chooseAccount = async ({ list }) => { // choose one field with dmenu const chooseField = async ({ selectedAccount }) => { + if (!selectedAccount) throw new Error('no account selected!') const copyable = { password: selectedAccount.login.password, username: selectedAccount.login.username, @@ -83,7 +82,7 @@ const chooseField = async ({ selectedAccount }) => { {} ) } - const field = await dmenuRun(Object.keys(copyable).join('\n')) + const field = await dmenuRun()(Object.keys(copyable).join('\n')) console.debug(`selected field '${field}'`) const valueToCopy = copyable[field] return valueToCopy diff --git a/src/util/obfuscate/bitwarden-cli.js b/src/util/obfuscate/bitwarden-cli.js index 5db1d89..f3bf149 100644 --- a/src/util/obfuscate/bitwarden-cli.js +++ b/src/util/obfuscate/bitwarden-cli.js @@ -1,4 +1,4 @@ module.exports = command => command - .replace(/unlock\s'.*'/, `unlock '******'`) - .replace(/session=.*/, 'session=****** ') + .replace(/unlock\s.*--raw$/, `unlock ****** --raw`) + .replace(/session=.*/, 'session=******')