From 4b0420d27d693e7ec00cba6f84b78d1b760795cd Mon Sep 17 00:00:00 2001 From: varjolintu Date: Wed, 8 Nov 2017 12:28:44 +0200 Subject: [PATCH 1/4] Fixed XML display error, context menu on password fields with Firefox, changed fill-password keyboard shortcuts --- keepassxc-browser/background/init.js | 16 +++++++++++----- keepassxc-browser/manifest.json | 9 ++++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index a57cad3..4d58c68 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -92,17 +92,23 @@ if (browser.webRequest.onAuthRequired) { browser.runtime.onMessage.addListener(kpxcEvent.onMessage); const contextMenuItems = [ - {title: 'Fill &User + Pass', action: 'fill_user_pass'}, - {title: 'Fill &Pass Only', action: 'fill_pass_only'}, - {title: 'Show Password &Generator Icons', action: 'activate_password_generator'}, - {title: '&Save credentials', action: 'remember_credentials'} + {title: 'Fill User + Pass', action: 'fill_user_pass'}, + {title: 'Fill Pass Only', action: 'fill_pass_only'}, + {title: 'Show Password Generator Icons', action: 'activate_password_generator'}, + {title: 'Save credentials', action: 'remember_credentials'} ]; +let menuContexts = ['editable']; + +if (isFirefox()) { + menuContexts.push('password'); +} + // Create context menu items for (const item of contextMenuItems) { browser.contextMenus.create({ title: item.title, - contexts: [ 'editable' ], + contexts: menuContexts, onclick: (info, tab) => { browser.tabs.sendMessage(tab.id, { action: item.action diff --git a/keepassxc-browser/manifest.json b/keepassxc-browser/manifest.json index 98bec40..9ca67fd 100644 --- a/keepassxc-browser/manifest.json +++ b/keepassxc-browser/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "keepassxc-browser", - "version": "0.3.9", + "version": "0.4.0", "description": "KeePassXC integration for modern web browsers", "author": "Sami Vänttinen", "icons": { @@ -41,6 +41,9 @@ "matches": [ "" ], + "exclude_matches": [ + "*://*/*.xml" + ], "js": [ "browser-polyfill.min.js", "global.js", @@ -67,8 +70,8 @@ "fill-password": { "description": "Insert a password", "suggested_key": { - "default": "Ctrl+Shift+P", - "mac": "Command+Shift+P" + "default": "Alt+Shift+P", + "mac": "Alt+Shift+P" } } }, From 74031b6bec3d0f5a6300d4933b22d49ff239a890 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Thu, 9 Nov 2017 13:25:42 +0200 Subject: [PATCH 2/4] Removed UDP settings --- keepassxc-browser/background/keepass.js | 49 +++++++++++-------------- keepassxc-browser/background/page.js | 6 +-- keepassxc-browser/options/options.html | 18 --------- keepassxc-browser/options/options.js | 14 ------- keepassxc-protocol.md | 3 +- 5 files changed, 23 insertions(+), 67 deletions(-) diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index 0134883..a7252a8 100644 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -160,7 +160,7 @@ keepass.updateCredentials = function(callback, tab, entryId, username, password, const request = { action: kpAction, message: keepass.encrypt(messageData, nonce), - nonce: keepass.b64e(nonce), + nonce: nacl.util.encodeBase64(nonce), clientID: keepass.clientID }; @@ -221,7 +221,7 @@ keepass.retrieveCredentials = function(callback, tab, url, submiturl, forceCallb const request = { action: kpAction, message: keepass.encrypt(messageData, nonce), - nonce: keepass.b64e(nonce), + nonce: nacl.util.encodeBase64(nonce), clientID: keepass.clientID }; @@ -285,7 +285,7 @@ keepass.generatePassword = function(callback, tab, forceCallback) { const request = { action: kpAction, - nonce: keepass.b64e(nonce), + nonce: nacl.util.encodeBase64(nonce), clientID: keepass.clientID }; @@ -334,7 +334,7 @@ keepass.associate = function(callback, tab) { page.tabs[tab.id].errorMessage = null; const kpAction = kpActions.ASSOCIATE; - const key = keepass.b64e(keepass.keyPair.publicKey); + const key = nacl.util.encodeBase64(keepass.keyPair.publicKey); const nonce = nacl.randomBytes(keepass.keySize); const messageData = { @@ -345,7 +345,7 @@ keepass.associate = function(callback, tab) { const request = { action: kpAction, message: keepass.encrypt(messageData, nonce), - nonce: keepass.b64e(nonce), + nonce: nacl.util.encodeBase64(nonce), clientID: keepass.clientID }; @@ -427,7 +427,7 @@ keepass.testAssociation = function(callback, tab, enableTimeout = false) { const request = { action: kpAction, message: keepass.encrypt(messageData, nonce), - nonce: keepass.b64e(nonce), + nonce: nacl.util.encodeBase64(nonce), clientID: keepass.clientID }; @@ -494,7 +494,7 @@ keepass.getDatabaseHash = function(callback, tab, enableTimeout = false) { const request = { action: kpAction, message: encrypted, - nonce: keepass.b64e(nonce), + nonce: nacl.util.encodeBase64(nonce), clientID: keepass.clientID }; @@ -549,15 +549,14 @@ keepass.changePublicKeys = function(tab, enableTimeout = false) { } const kpAction = kpActions.CHANGE_PUBLIC_KEYS; - const key = keepass.b64e(keepass.keyPair.publicKey); + const key = nacl.util.encodeBase64(keepass.keyPair.publicKey); let nonce = nacl.randomBytes(keepass.keySize); - nonce = keepass.b64e(nonce); - keepass.clientID = keepass.b64e(nacl.randomBytes(keepass.keySize)); + nonce = nacl.util.encodeBase64(nonce); + keepass.clientID = nacl.util.encodeBase64(nacl.randomBytes(keepass.keySize)); const request = { action: kpAction, publicKey: key, - proxyPort: (page.settings.port ? page.settings.port : 19700), nonce: nonce, clientID: keepass.clientID }; @@ -573,7 +572,7 @@ keepass.changePublicKeys = function(tab, enableTimeout = false) { } else { keepass.isKeePassXCAvailable = true; - console.log('Server public key: ' + keepass.b64e(keepass.serverPublicKey)); + console.log('Server public key: ' + nacl.util.encodeBase64(keepass.serverPublicKey)); } resolve(true); }); @@ -597,7 +596,7 @@ keepass.lockDatabase = function(tab) { const request = { action: kpAction, message: keepass.encrypt(messageData, nonce), - nonce: keepass.b64e(nonce), + nonce: nacl.util.encodeBase64(nonce), clientID: keepass.clientID }; @@ -627,7 +626,7 @@ keepass.lockDatabase = function(tab) { keepass.generateNewKeyPair = function() { keepass.keyPair = nacl.box.keyPair(); - //console.log(keepass.b64e(keepass.keyPair.publicKey) + ' ' + keepass.b64e(keepass.keyPair.secretKey)); + //console.log(nacl.util.encodeBase64(keepass.keyPair.publicKey) + ' ' + nacl.util.encodeBase64(keepass.keyPair.secretKey)); }; keepass.isConfigured = function() { @@ -810,13 +809,14 @@ keepass.verifyKeyResponse = function(response, key, nonce) { } let reply = false; - if (keepass.b64d(nonce).length !== nacl.secretbox.nonceLength) + if (nacl.util.decodeBase64(nonce).length !== nacl.secretbox.nonceLength) { return false; + } reply = (response.nonce === nonce); if (response.publicKey) { - keepass.serverPublicKey = keepass.b64d(response.publicKey); + keepass.serverPublicKey = nacl.util.decodeBase64(response.publicKey); reply = true; } @@ -832,8 +832,9 @@ keepass.verifyResponse = function(response, nonce, id) { keepass.associated.hash = keepass.databaseHash; - if (keepass.b64d(response.nonce).length !== nacl.secretbox.nonceLength) + if (nacl.util.decodeBase64(response.nonce).length !== nacl.secretbox.nonceLength) { return false; + } keepass.associated.value = (response.nonce === nonce); @@ -856,14 +857,6 @@ keepass.handleError = function(tab, errorCode, errorMessage = '') { } }; -keepass.b64e = function(d) { - return nacl.util.encodeBase64(d); -}; - -keepass.b64d = function(d) { - return nacl.util.decodeBase64(d); -}; - keepass.getCryptoKey = function() { let dbkey = null; let dbid = null; @@ -890,15 +883,15 @@ keepass.encrypt = function(input, nonce) { if (keepass.serverPublicKey) { const message = nacl.box(messageData, nonce, keepass.serverPublicKey, keepass.keyPair.secretKey); if (message) { - return keepass.b64e(message); + return nacl.util.encodeBase64(message); } } return ''; }; keepass.decrypt = function(input, nonce, toStr) { - const m = keepass.b64d(input); - const n = keepass.b64d(nonce); + const m = nacl.util.decodeBase64(input); + const n = nacl.util.decodeBase64(nonce); const res = nacl.box.open(m, n, keepass.serverPublicKey, keepass.keyPair.secretKey); return res; }; diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index 7aba064..5b9c525 100644 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -4,8 +4,7 @@ const defaultSettings = { autoFillAndSend: true, usePasswordGenerator: true, autoFillSingleEntry: false, - autoRetrieveCredentials: true, - proxyPort: '19700' + autoRetrieveCredentials: true }; var page = {}; @@ -35,9 +34,6 @@ page.initSettings = function() { if (!('autoRetrieveCredentials' in page.settings)) { page.settings.autoRetrieveCredentials = defaultSettings.autoRetrieveCredentials; } - if (!('port' in page.settings)) { - page.settings.port = defaultSettings.proxyPort; - } browser.storage.local.set({'settings': page.settings}); resolve(); }); diff --git a/keepassxc-browser/options/options.html b/keepassxc-browser/options/options.html index 9da6052..1a24336 100644 --- a/keepassxc-browser/options/options.html +++ b/keepassxc-browser/options/options.html @@ -84,24 +84,6 @@

-

-

- -
-
- - -
- - Change the port if you have trouble with running KeePassXC on the default port. -
- You have to set the same port number in KeePassXC options. -
- Default: 19700 -
-
-
-


diff --git a/keepassxc-browser/options/options.js b/keepassxc-browser/options/options.js index 6328a29..47b29d4 100644 --- a/keepassxc-browser/options/options.js +++ b/keepassxc-browser/options/options.js @@ -88,24 +88,10 @@ options.initGeneralSettings = function() { }).then(options.showKeePassXCVersions); }); - $('#port').val(options.settings['port']); $('#blinkTimeout').val(options.settings['blinkTimeout']); $('#blinkMinTimeout').val(options.settings['blinkMinTimeout']); $('#allowedRedirect').val(options.settings['allowedRedirect']); - $('#portButton').click(function() { - const port = $.trim($('#port').val()); - const portNumber = Number(port); - if (isNaN(port) || portNumber < 1025 || portNumber > 99999) { - $('#port').closest('.control-group').addClass('error'); - alert('The port number has to be in range 1025 - 99999.\nNothing saved!'); - return; - } - - options.settings['port'] = String(portNumber); - options.saveSetting('port'); - }); - $('#blinkTimeoutButton').click(function(){ const blinkTimeout = $.trim($('#blinkTimeout').val()); const blinkTimeoutval = Number(blinkTimeout); diff --git a/keepassxc-protocol.md b/keepassxc-protocol.md index 872bd08..703d627 100644 --- a/keepassxc-protocol.md +++ b/keepassxc-protocol.md @@ -34,7 +34,6 @@ Request: { "action": "change-public-keys", "publicKey": "", - "proxyPort": "", "nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q", "clientID": "" } @@ -250,4 +249,4 @@ Response message data (success always returns an error, decrypted): "error": "Database not opened", "nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q" } -``` \ No newline at end of file +``` From d0244adefa054909f16bb9b2b3337a3c95887c87 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Fri, 10 Nov 2017 14:48:10 +0200 Subject: [PATCH 3/4] Removed some unnecessary polling --- keepassxc-browser/background/event.js | 21 +++++++++++++------- keepassxc-browser/background/keepass.js | 2 +- keepassxc-browser/keepassxc-browser.js | 26 ++++++++++--------------- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js index 264a70a..275a360 100644 --- a/keepassxc-browser/background/event.js +++ b/keepassxc-browser/background/event.js @@ -128,17 +128,24 @@ kpxcEvent.onSaveSettings = function(callback, tab, settings) { }); }; -kpxcEvent.onGetStatus = function(callback, tab) { - keepass.testAssociation((response) => { - if (!response) { - kpxcEvent.showStatus(false, tab, callback); - return; - } +kpxcEvent.onGetStatus = function(callback, tab, internalPoll = false) { + // When internalPoll is true the event is triggered from content script in intervals -> don't poll KeePassXC + if (!internalPoll) { + keepass.testAssociation((response) => { + if (!response) { + kpxcEvent.showStatus(false, tab, callback); + return; + } + keepass.isConfigured().then((configured) => { + kpxcEvent.showStatus(configured, tab, callback); + }); + }, tab, true); + } else { keepass.isConfigured().then((configured) => { kpxcEvent.showStatus(configured, tab, callback); }); - }, tab, true); + } }; kpxcEvent.onReconnect = function(callback, tab) { diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index a7252a8..6f2244d 100644 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -631,7 +631,7 @@ keepass.generateNewKeyPair = function() { keepass.isConfigured = function() { return new Promise((resolve, reject) => { - if (typeof(keepass.databaseHash) === 'undefined' || keepass.databaseHash === 'no-hash') { + if (typeof(keepass.databaseHash) === 'undefined') { keepass.getDatabaseHash((hash) => { resolve(hash in keepass.keyRing); }); diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index 41962ac..1b4b5ca 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -396,7 +396,6 @@ cipPassword.callbackPasswordCopied = function(bool) { cipPassword.callbackGeneratedPassword = function(entries) { if (entries && entries.length >= 1) { - console.log(entries[0]); jQuery('#cip-genpw-btn-clipboard:first').removeClass('btn-success'); jQuery('input#cip-genpw-textfield-password:first').val(entries[0].password); if (isNaN(entries[0].login)) { @@ -408,7 +407,7 @@ cipPassword.callbackGeneratedPassword = function(entries) { } else { if (jQuery('div#cip-genpw-error:first').length === 0) { - jQuery('button#cip-genpw-btn-generate:first').after('
Cannot receive generated password.
Is your version of KeePassXC up-to-date?

Please visit the KeePassXC homepage
'); + jQuery('button#cip-genpw-btn-generate:first').after('
Cannot receive generated password.
Is KeePassXC opened?
'); jQuery('input#cip-genpw-textfield-password:first').parent().hide(); jQuery('input#cip-genpw-checkbox-next-field:first').parent('label').hide(); jQuery('button#cip-genpw-btn-generate').hide(); @@ -1117,21 +1116,15 @@ cip.init = function() { }; cip.detectNewActiveFields = function() { - const hiddenFields = cipFields.getHiddenFieldCount(); - - // If hidden fields aren't detected, setInterval is being looped in each frame of the page - //if (hiddenFields > 0) { - const divDetect = setInterval(function() { - const fields = cipFields.getAllFields(); - if (fields.length > 1) { - cip.initCredentialFields(true); - clearInterval(divDetect); - } - }, 1000); - //} + const divDetect = setInterval(function() { + const fields = cipFields.getAllFields(); + if (fields.length > 1) { + cip.initCredentialFields(true); + clearInterval(divDetect); + } + }, 1000); }; -// Try to do this in a way that database value if checked without polling the KeePassXC.. too many messages jumping around // Switch credentials if database is changed or closed cip.detectDatabaseChange = function() { let dbDetectInterval = setInterval(function() { @@ -1148,7 +1141,8 @@ cip.detectDatabaseChange = function() { // Switch back to default popup browser.runtime.sendMessage({ - action: 'get_status' + action: 'get_status', + args: [ true ] // Set polling to true, this is an internal function call }); } else { if (response.new !== 'no-hash' && response.new !== response.old) { From d8556fc958bc3d497e06199bb0e6ef1c03e4081e Mon Sep 17 00:00:00 2001 From: varjolintu Date: Mon, 13 Nov 2017 15:45:06 +0200 Subject: [PATCH 4/4] Updated the README. Added an error handling --- CHANGELOG | 6 ++++++ README.md | 13 +++++++------ keepassxc-browser/background/keepass.js | 1 + 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6b1927b..c21b0b8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +0.4.0 (13-11-2017) +========================= +- Fixed showing context menu on password fields with Firefox +- Ignore XML files on content scripts (Firefox shows them incorrectly) +- UDP features removed as KeePassXC switched them to Unix domain sockets and named pipes + 0.3.9 (04-11-2017) ========================= - Removed incorrect timeout waiting on init diff --git a/README.md b/README.md index 8f72920..04a9c7b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # keepassxc-browser -Chrome extension for [KeePassXC](https://keepassxc.org/) with Native Messaging. +Browser extension for [KeePassXC](https://keepassxc.org/) with Native Messaging. This is a heavily forked version of [pfn](https://github.com/pfn)'s [chromeIPass](https://github.com/pfn/passifox). Some changes merged also from [smorks'](https://github.com/smorks/keepasshttp-connector) KeePassHttp-Connector fork. -For testing purposes, please use following unofficial KeePassXC [release's](https://github.com/varjolintu/keepassxc/releases). +For testing purposes, please use only the following unofficial KeePassXC [release's](https://github.com/varjolintu/keepassxc/releases). Get the extension for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) or [Chrome/Chromium](https://chrome.google.com/webstore/detail/keepassxc-browser/iopaggbpplllidnfmcghoonnokmjoicf). -The extension is supported with Firefox 55 and newer. If you want to load it as a temporary plugin with Firefox 54 you can just change the minimum version from the manifest file before loading it. +The extension is supported with Firefox 55 and newer. If you want to load it as a temporary plugin with Firefox 54 or ESR you can just change the minimum version from the manifest file before loading it. Please thee this [wiki page](hhttps://github.com/varjolintu/keepassxc-browser/wiki/Connecting-the-database-with-keepassxc-browser) for instructions how to configure this KeePassXC fork in order to connect the database correctly. @@ -17,10 +17,11 @@ There are two methods which you can use keepassxc-browser to connect to KeePassX 1. keepassxc-browser communicates directly with KeePassXC via stdin/stdout. This method launches KeePassXC every time you start the browser and closes when you exit. This can cause unsaved changes not to be saved. If you use this method it's important to enable `Automatically save after every change` from KeePassXC's preferences. -2. keepassxc-browser communicated with KeePassXC through [keepassxc-proxy](https://github.com/varjolintu/keepassxc-proxy) or [keepassxc-proxy-rust](https://github.com/varjolintu/keepassxc-proxy-rust). The proxy handles listening stdin/stdout +2. keepassxc-browser communicated with KeePassXC through [keepassxc-proxy](https://github.com/varjolintu/keepassxc-proxy). The proxy handles listening stdin/stdout and transfers these messages through Unix domain sockets / named pipes to KeePassXC. This means KeePassXC can be used and started normally without inteference from Native Messaging API. keepassxc-browser starts only the proxy application and there's no risk of shutting down KeePassXC or losing any unsaved changes. keepassxc-proxy -is still under development. If you want, you are free to write your own proxy that handles the traffic. +is still under development. If you want, you are free to write your own proxy that handles the traffic. You don't need to install keepassxc-proxy separately. It is +included in the latest KeePassXC fork. Use it if you want to make your own proxy or improve/extend it. ## Improvements The following improvements and features have been made after the fork. At this point some features are only available with the KeePassXC fork: @@ -77,4 +78,4 @@ Feel free to support this project: - Donate via [PayPal](https://paypal.me/varjolintu) - Donate via Bitcoin: 1LHbD69CcmpLW5hjUXs2MGJhw3GxwqLdw3 -Also consider donating to [KeePassXC](https://flattr.com/submit/auto?fid=x7yqz0&url=https%3A%2F%2Fkeepassxc.org) and passifox teams [(1)](https://github.com/smorks/passifox),[(2)](https://github.com/projectgus/passifox),[(3)](https://github.com/pfn/passifox). They are doing great job. +Also consider donating to [KeePassXC](https://flattr.com/submit/auto?fid=x7yqz0&url=https%3A%2F%2Fkeepassxc.org) and passifox teams [(1)](https://github.com/smorks/passifox),[(2)](https://github.com/pfn/passifox). They are doing great job. diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index 6f2244d..d457ba2 100644 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -545,6 +545,7 @@ keepass.getDatabaseHash = function(callback, tab, enableTimeout = false) { keepass.changePublicKeys = function(tab, enableTimeout = false) { return new Promise((resolve, reject) => { if (!keepass.isConnected) { + keepass.handleError(tab, kpErrors.TIMEOUT_OR_NOT_CONNECTED); reject(false); }