diff --git a/CHANGELOG b/CHANGELOG index 5f83946..348c786 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +0.4.4 (17-12-2017) +========================= +- Added support for OTP codes via context menu +- Fixed HTTP auth +- General content script code cleaning + 0.4.3 (9-12-2017) ========================= - Create password generator dialog only when clicking the icon diff --git a/README.md b/README.md index 058538e..ec93d9b 100644 --- a/README.md +++ b/README.md @@ -7,35 +7,34 @@ For testing purposes, please use only the following unofficial KeePassXC [releas 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 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. ## How it works There are two methods which you can use keepassxc-browser to connect to KeePassXC: -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. The proxy handles listening stdin/stdout +1. keepassxc-browser communicated with KeePassXC through 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. 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. Alternatively you can use -[keepassxc-proxy-rust](https://github.com/varjolintu/keepassxc-proxy-rust) as a proxy if you prefer a non-Qt solution. There's also Python and C++ versions available at +Native Messaging API. keepassxc-browser starts only the proxy application and there's no risk of shutting down KeePassXC or losing any unsaved changes. You don't need to install keepassxc-proxy separately. It is included in the latest KeePassXC fork. Alternatively you can use +[keepassxc-proxy-rust](https://github.com/varjolintu/keepassxc-proxy-rust) as a proxy if you prefer a non-Qt solution. There's also Python and C++ versions available at [keepassxc-proxy](https://github.com/varjolintu/keepassxc-proxy). +2. keepassxc-browser communicates directly with KeePassXC via stdin/stdout. Using native messaging directly is a more secure as it ensures the traffic between KeePassXC and keepassxc-browser is direct. 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. Because this option is not preferred as default it's good to test this feature with your OS and ensure KeePassXC asks to confirm any unsaved changes before exit. + ## Improvements The following improvements and features have been made after the fork. At this point some features are only available with the KeePassXC fork: - Real-time detection of database status (locked/unlocked) - Credentials on a page are cleared or received automatically again if database is locked or changed to another - It is possible to lock the active database from the popup (using the red lock icon) - Input forms are detected even if the login div has been hidden or is created after the page was loaded -- It is possible to use the active database from multiple browsers at the same time with [keepassxc-proxy](https://github.com/varjolintu/keepassxc-proxy) application. +- It is possible to use the active database from multiple browsers at the same time with keepassxc-proxy option - Deprecated JavaScript functions are removed and everything is asynchronous - Updated Bootstrap to version 3.3.7 and jQuery to version 3.2.1 - New buttons, icons and settings page graphics - Redesigned password generator dialog - Password generator supports diceware passphrases and extended ASCII characters - Autocomplete works also when only password fields are visible +- Supports TOTP with custom KHP placeholders (`KPH: {TOPT}`) ## Protocol @@ -79,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/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 [KeePassHttp-Connector](https://github.com/smorks/keepasshttp-connector) teams. They are doing great job. diff --git a/com.varjolintu.keepassxc-browser-chrome-win.json b/com.varjolintu.keepassxc-browser-chrome-win.json deleted file mode 100644 index acf8450..0000000 --- a/com.varjolintu.keepassxc-browser-chrome-win.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "com.varjolintu.keepassxc_browser", - "description": "KeepassXC integration with Chrome with Native Messaging support", - "path" : "keepassxc-proxy.bat", - "type": "stdio", - "allowed_origins": [ - "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/", - "chrome-extension://fhakpkpdnjecjfceboihdjpfmgajebii/", - "chrome-extension://jaikbblhommnkeialomogohhdlndpfbi/" - ] -} \ No newline at end of file diff --git a/com.varjolintu.keepassxc-browser-chrome.json b/com.varjolintu.keepassxc-browser-chrome.json deleted file mode 100644 index 0fb2adb..0000000 --- a/com.varjolintu.keepassxc-browser-chrome.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "com.varjolintu.keepassxc_browser", - "description": "KeepassXC integration with Chrome with Native Messaging support", - "path" : "%%replace%%", - "type": "stdio", - "allowed_origins": [ - "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/", - "chrome-extension://fhakpkpdnjecjfceboihdjpfmgajebii/", - "chrome-extension://jaikbblhommnkeialomogohhdlndpfbi/" - ] -} \ No newline at end of file diff --git a/com.varjolintu.keepassxc-browser-firefox-win.json b/com.varjolintu.keepassxc-browser-firefox-win.json deleted file mode 100644 index 6c4b9c4..0000000 --- a/com.varjolintu.keepassxc-browser-firefox-win.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "com.varjolintu.keepassxc_browser", - "description": "KeepassXC integration with Firefox with Native Messaging support", - "path" : "keepassxc-proxy.bat", - "type": "stdio", - "allowed_extensions": [ - "keepassxc-browser@sami.vanttinen" - ] -} \ No newline at end of file diff --git a/com.varjolintu.keepassxc-browser-firefox.json b/com.varjolintu.keepassxc-browser-firefox.json deleted file mode 100644 index b98e59d..0000000 --- a/com.varjolintu.keepassxc-browser-firefox.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "com.varjolintu.keepassxc_browser", - "description": "KeepassXC integration with Firefox with Native Messaging support", - "path" : "%%replace%%", - "type": "stdio", - "allowed_extensions": [ - "keepassxc-browser@sami.vanttinen" - ] -} \ No newline at end of file diff --git a/install.bat b/install.bat deleted file mode 100644 index 954957b..0000000 --- a/install.bat +++ /dev/null @@ -1,34 +0,0 @@ -:: Copyright 2014 The Chromium Authors. All rights reserved. -:: Copyright 2017 Sami Vänttinen -:: Use of this source code is governed by a BSD-style license that can be -:: found in the LICENSE file. -:: Change HKCU to HKLM if you want to install globally. -:: %~dp0 is the directory containing this bat script and ends with a backslash. -@echo off -echo. -echo Select your browser: -echo ==================== -echo 1) Chrome -echo 2) Chromium -echo 3) Firefox -echo 4) Vivaldi -set choice= -set /p choice=1-4: -if '%choice%'=='1' goto chrome -if '%choice%'=='2' goto chromium -if '%choice%'=='3' goto firefox -if '%choice%'=='3' goto vivaldi -goto end -:chrome -REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.varjolintu.keepassxc_browser" /ve /t REG_SZ /d "%~dp0com.varjolintu.keepassxc-browser-chrome.win.json" /f -goto end -:chromium -REG ADD "HKCU\Software\Chromium\NativeMessagingHosts\com.varjolintu.keepassxc_browser" /ve /t REG_SZ /d "%~dp0com.varjolintu.keepassxc-browser-chrome.win.json" /f -goto end -:firefox -REG ADD "HKCU\Software\Mozilla\NativeMessagingHosts\com.varjolintu.keepassxc_browser" /ve /t REG_SZ /d "%~dp0com.varjolintu.keepassxc-browser-firefox.win.json" /f -goto end -:vivaldi -REG ADD "HKCU\Software\Vivaldi\NativeMessagingHosts\com.varjolintu.keepassxc_browser" /ve /t REG_SZ /d "%~dp0com.varjolintu.keepassxc-browser-chrome.win.json" /f -goto end -:end \ No newline at end of file diff --git a/install.sh b/install.sh deleted file mode 100755 index c0bf959..0000000 --- a/install.sh +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env bash - -# The MIT License (MIT) -# Copyright (c) 2016 Danny van Kooten -# Modifications (c) 2017 Sami Vänttinen - -# Permission is hereby granted, free of charge, to any person obtaining a copy of this software -# and associated documentation files (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -set -e - -DIR="$( cd "$( dirname "$0" )" && pwd )" -APP_NAME="com.varjolintu.keepassxc_browser" -HOST_FILE="$DIR" -KEEPASSXC_PATH="" - -# Find target dirs for various browsers & OS'es -# https://developer.chrome.com/extensions/nativeMessaging#native-messaging-host-location -# https://wiki.mozilla.org/WebExtensions/Native_Messaging -if [ $(uname -s) == 'Darwin' ]; then - if [ "$(whoami)" == "root" ]; then - TARGET_DIR_CHROME="/Library/Google/Chrome/NativeMessagingHosts" - TARGET_DIR_CHROMIUM="/Library/Application Support/Chromium/NativeMessagingHosts" - TARGET_DIR_FIREFOX="/Library/Application Support/Mozilla/NativeMessagingHosts" - TARGET_DIR_VIVALDI="/Library/Application Support/Vivaldi/NativeMessagingHosts" - else - TARGET_DIR_CHROME="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts" - TARGET_DIR_CHROMIUM="$HOME/Library/Application Support/Chromium/NativeMessagingHosts" - TARGET_DIR_FIREFOX="$HOME/Library/Application Support/Mozilla/NativeMessagingHosts" - TARGET_DIR_VIVALDI="$HOME/Library/Application Support/Vivaldi/NativeMessagingHosts" - fi -else - if [ "$(whoami)" == "root" ]; then - TARGET_DIR_CHROME="/etc/opt/chrome/native-messaging-hosts" - TARGET_DIR_CHROMIUM="/etc/chromium/native-messaging-hosts" - TARGET_DIR_FIREFOX="/usr/lib/mozilla/native-messaging-hosts" - TARGET_DIR_VIVALDI="/etc/chromium/native-messaging-hosts" - else - TARGET_DIR_CHROME="$HOME/.config/google-chrome/NativeMessagingHosts" - TARGET_DIR_CHROMIUM="$HOME/.config/chromium/NativeMessagingHosts" - TARGET_DIR_FIREFOX="$HOME/.mozilla/native-messaging-hosts" - TARGET_DIR_VIVALDI="$HOME/.config/vivaldi/NativeMessagingHosts" - fi -fi - -if [ -e "$DIR/keepassxc-browser" ]; then - echo "Detected development binary" - HOST_FILE="$DIR/keepassxc-browser" -fi - -echo "" -echo "Select your browser:" -echo "====================" -echo "1) Chrome" -echo "2) Chromium" -echo "3) Firefox" -echo "4) Vivaldi" -echo -n "1-4: " -read BROWSER -echo "" - -# Set target dir from user input -if [[ "$BROWSER" == "1" ]]; then - BROWSER_NAME="Chrome" - TARGET_DIR="$TARGET_DIR_CHROME" -fi - -if [[ "$BROWSER" == "2" ]]; then - BROWSER_NAME="Chromium" - TARGET_DIR="$TARGET_DIR_CHROMIUM" -fi - -if [[ "$BROWSER" == "3" ]]; then - BROWSER_NAME="Firefox" - TARGET_DIR="$TARGET_DIR_FIREFOX" -fi - -if [[ "$BROWSER" == "4" ]]; then - BROWSER_NAME="Vivaldi" - TARGET_DIR="$TARGET_DIR_VIVALDI" -fi - -# Try to find the KeePassXC binary. -if [ $(uname -s) == 'Darwin' ]; then - KEEPASSXC_PATH="/Applications/KeePassXC.app" -else - KEEPASSXC_PATH="$(command -v keepassxc)" - if [ -z "$KEEPASSXC_PATH" ] ; then - echo "" - echo -n "KeePassXC binary not found. Give the location of KeePassXC binary: " - read KEEPASSXC_PATH - echo "" - fi -fi -echo "KeePassXC binary location set to $KEEPASSXC_PATH" -echo "Installing $BROWSER_NAME host config with path $KEEPASSXC_PATH" -echo "Press (ENTER) or give a new path to binary if it's not correct: " -read NEW_PATH - -if [ "$NEW_PATH" ]; then - KEEPASSXC_PATH="$NEW_PATH" - echo "New path set to: $KEEPASSXC_PATH" -fi - -# Add /Contents/MacOS/KeePassXC to darwin for exact binary path -if [ $(uname -s) == 'Darwin' ]; then - KEEPASSXC_PATH="$KEEPASSXC_PATH/Contents/MacOS/KeePassXC" -fi - -ESCAPED_PATH=${KEEPASSXC_PATH////\\/} - -# Create config dir if not existing -mkdir -p "$TARGET_DIR" - -# Copy manifest host config file -if [ "$BROWSER" == "1" ] || [ "$BROWSER" == "2" ] || [ "$BROWSER" == "4" ]; then - cp "$DIR/com.varjolintu.keepassxc-browser-chrome.json" "$TARGET_DIR/$APP_NAME.json" -else - cp "$DIR/com.varjolintu.keepassxc-browser-firefox.json" "$TARGET_DIR//$APP_NAME.json" -fi - -# Replace path to host -if [ $(uname -s) == 'Darwin' ]; then - sed -i "" -e "s/%%replace%%/$ESCAPED_PATH/g" "$TARGET_DIR/$APP_NAME.json" -else - sed -i -e "s/%%replace%%/$ESCAPED_PATH/g" "$TARGET_DIR/$APP_NAME.json" -fi - -# Set permissions for the manifest so that all users can read it. -chmod o+r "$TARGET_DIR/$APP_NAME.json" - -echo "Native messaging host for $BROWSER_NAME has been installed to $TARGET_DIR." \ No newline at end of file diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js index 9b42ca3..a2c9f90 100644 --- a/keepassxc-browser/background/event.js +++ b/keepassxc-browser/background/event.js @@ -100,8 +100,8 @@ kpxcEvent.showStatus = function(configured, tab, callback) { }; kpxcEvent.onLoadSettings = function(callback, tab) { - browser.storage.local.get({'settings': {}}).then((item) => { - callback(item.settings); + page.initSettings().then((settings) => { + callback(settings); }, (err) => { console.log('error loading settings: ' + err); }); @@ -230,6 +230,11 @@ kpxcEvent.onLoginPopup = function(callback, tab, logins) { browserAction.show(null, tab); }; +kpxcEvent.initHttpAuth = function(callback) { + httpAuth.init(); + callback(); +} + kpxcEvent.onHTTPAuthPopup = function(callback, tab, data) { let stackData = { level: 1, @@ -274,6 +279,7 @@ kpxcEvent.messageHandlers = { 'get_keepassxc_versions': kpxcEvent.onGetKeePassXCVersions, 'get_status': kpxcEvent.onGetStatus, 'get_tab_information': kpxcEvent.onGetTabInformation, + 'init_http_auth': kpxcEvent.initHttpAuth, 'load_keyring': kpxcEvent.onLoadKeyRing, 'load_settings': kpxcEvent.onLoadSettings, 'page_clear_logins': kpxcEvent.pageClearLogins, diff --git a/keepassxc-browser/background/httpauth.js b/keepassxc-browser/background/httpauth.js index f74277d..7a53fdd 100644 --- a/keepassxc-browser/background/httpauth.js +++ b/keepassxc-browser/background/httpauth.js @@ -3,6 +3,31 @@ const httpAuth = {}; httpAuth.requests = []; httpAuth.pendingCallbacks = []; +httpAuth.init = function() { + let handleReq = httpAuth.handleRequestPromise; + let reqType = 'blocking'; + + if (!isFirefox()) { + handleReq = httpAuth.handleRequestCallback; + reqType = 'asyncBlocking'; + } + + if (browser.webRequest.onAuthRequired.hasListener(handleReq)) { + browser.webRequest.onAuthRequired.removeListener(handleReq); + browser.webRequest.onCompleted.removeListener(httpAuth.requestCompleted); + browser.webRequest.onErrorOccurred.removeListener(httpAuth.requestCompleted); + } + + // only intercept http auth requests if the option is turned on. + if (page.settings.autoFillAndSend) { + const opts = { urls: [''] }; + + browser.webRequest.onAuthRequired.addListener(handleReq, opts, [reqType]); + browser.webRequest.onCompleted.addListener(httpAuth.requestCompleted, opts); + browser.webRequest.onErrorOccurred.addListener(httpAuth.requestCompleted, opts); + } +}; + httpAuth.requestCompleted = function(details) { let index = httpAuth.requests.indexOf(details.requestId); if (index >= 0) { @@ -41,8 +66,8 @@ httpAuth.processPendingCallbacks = function(details, resolve, reject) { httpAuth.loginOrShowCredentials = function(logins, details, resolve, reject) { // at least one login found --> use first to login - if (logins.length > 0) { - if (logins.length == 1 && page.settings.autoFillAndSend) { + if (logins.length > 0 && page.settings.autoFillAndSend) { + if (logins.length === 1) { resolve({ authCredentials: { username: logins[0].login, diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index 149328a..4279020 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -1,6 +1,7 @@ keepass.migrateKeyRing().then(() => { page.initSettings().then(() => { page.initOpenedTabs().then(() => { + httpAuth.init(); keepass.connectToNative(); keepass.generateNewKeyPair(); keepass.changePublicKeys(null).then((pkRes) => { @@ -73,27 +74,12 @@ browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { } }); -// Retrieve Credentials and try auto-login for HTTPAuth requests -if (browser.webRequest.onAuthRequired) { - let handleReq = httpAuth.handleRequestPromise; - let reqType = 'blocking'; - let opts = { urls: [''] }; - - if (!isFirefox()) { - handleReq = httpAuth.handleRequestCallback; - reqType = 'asyncBlocking'; - } - - browser.webRequest.onAuthRequired.addListener(handleReq, opts, [reqType]); - browser.webRequest.onCompleted.addListener(httpAuth.requestCompleted, opts); - browser.webRequest.onErrorOccurred.addListener(httpAuth.requestCompleted, opts); -} - 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: 'Fill TOTP', action: 'fill_totp'}, {title: 'Show Password Generator Icons', action: 'activate_password_generator'}, {title: 'Save credentials', action: 'remember_credentials'} ]; diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index ae435ac..b924fe7 100644 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -131,7 +131,9 @@ keepass.addCredentials = function(callback, tab, username, password, url) { keepass.updateCredentials = function(callback, tab, entryId, username, password, url) { page.debug('keepass.updateCredentials(callback, {1}, {2}, {3}, [password], {4})', tab.id, entryId, username, url); - page.tabs[tab.id].errorMessage = null; + if (tab && page.tabs[tab.id]) { + page.tabs[tab.id].errorMessage = null; + } keepass.testAssociation((response) => { if (!response) { @@ -200,7 +202,9 @@ keepass.retrieveCredentials = function(callback, tab, url, submiturl, forceCallb return; } - page.tabs[tab.id].errorMessage = null; + if (tab && page.tabs[tab.id]) { + page.tabs[tab.id].errorMessage = null; + } if (!keepass.isConnected) { callback([]); @@ -344,7 +348,9 @@ keepass.associate = function(callback, tab) { return; } - page.tabs[tab.id].errorMessage = null; + if (tab && page.tabs[tab.id]) { + page.tabs[tab.id].errorMessage = null; + } const kpAction = kpActions.ASSOCIATE; const key = nacl.util.encodeBase64(keepass.keyPair.publicKey); diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index 8a9d5c2..a806ed1 100644 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -14,8 +14,8 @@ page.blockedTabs = {}; page.initSettings = function() { return new Promise((resolve, reject) => { - kpxcEvent.onLoadSettings((settings) => { - page.settings = settings; + browser.storage.local.get({'settings': {}}).then((item) => { + page.settings = item.settings; if (!('checkUpdateKeePassXC' in page.settings)) { page.settings.checkUpdateKeePassXC = defaultSettings.checkUpdateKeePassXC; } @@ -35,7 +35,7 @@ page.initSettings = function() { page.settings.autoRetrieveCredentials = defaultSettings.autoRetrieveCredentials; } browser.storage.local.set({'settings': page.settings}); - resolve(); + resolve(page.settings); }); }); }; diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index e74d3e5..b1a0101 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -22,7 +22,7 @@ browser.runtime.onMessage.addListener(function(req, sender, callback) { combination = cipFields.getCombination('password', cip.p); } - let list = {}; + let list = []; if (cip.fillInStringFields(combination.fields, cip.credentials[req.id].stringFields, list)) { cipForm.destroy(false, {'password': list.list[0], 'username': list.list[1]}); } @@ -36,7 +36,11 @@ browser.runtime.onMessage.addListener(function(req, sender, callback) { } else if (req.action === 'fill_pass_only') { cip.receiveCredentialsIfNecessary(); - cip.fillInFromActiveElementPassOnly(false); + cip.fillInFromActiveElement(false, true); + } + else if (req.action === 'fill_totp') { + cip.receiveCredentialsIfNecessary(); + cip.fillInFromActiveElementTOTPOnly(false); } else if (req.action === 'activate_password_generator') { cip.initPasswordGenerator(cipFields.getAllFields()); @@ -530,7 +534,7 @@ var cipDefine = {}; cipDefine.selection = { username: null, password: null, - fields: {} + fields: [] }; cipDefine.eventFieldClick = null; @@ -667,7 +671,7 @@ cipDefine.resetSelection = function() { cipDefine.selection = { username: null, password: null, - fields: {} + fields: [] }; }; @@ -710,10 +714,8 @@ cipDefine.markAllStringFields = function($chooser) { }; cipDefine.markFields = function ($chooser, $pattern) { - //var $found = false; jQuery($pattern).each(function() { if (cipDefine.isFieldSelected(jQuery(this).data('cip-id'))) { - //continue return true; } @@ -727,16 +729,8 @@ cipDefine.markFields = function ($chooser, $pattern) { .click(cipDefine.eventFieldClick) .hover(function() {jQuery(this).addClass('b2c-fixed-hover-field');}, function() {jQuery(this).removeClass('b2c-fixed-hover-field');}); $chooser.append($field); - //$found = true; } }); - - /* skip step if no entry was found - if(!$found) { - alert('No username field found.\nContinue with choosing a password field.''); - jQuery('button#b2c-btn-skip').click(); - } - */ }; cipDefine.prepareStep1 = function() { @@ -759,14 +753,6 @@ cipDefine.prepareStep2 = function() { }; cipDefine.prepareStep3 = function() { - /* skip step if no entry was found - if(!jQuery('div#b2c-cipDefine-fields').data('username') && !jQuery('div#b2c-cipDefine-fields').data('password')) { - alert('Neither an username field nor a password field were selected.\nNothing will be changed and chooser will be closed now.''); - jQuery('button#b2c-btn-dismiss').click(); - return; - } - */ - if (!cipDefine.selection.username && !cipDefine.selection.password) { jQuery('button#b2c-btn-confirm:first').removeClass('b2c-btn-primary').attr('disabled', true); } @@ -1268,7 +1254,7 @@ cip.prepareFieldsForCredentials = function(autoFillInForSingle) { } if (combination) { - let list = {}; + let list = []; if (cip.fillInStringFields(combination.fields, cip.credentials[0].stringFields, list)) { cipForm.destroy(false, {'password': list.list[0], 'username': list.list[1]}); } @@ -1389,7 +1375,7 @@ cip.fillInCredentials = function(combination, onlyPassword, suppressWarnings) { } }; -cip.fillInFromActiveElement = function(suppressWarnings) { +cip.fillInFromActiveElement = function(suppressWarnings, passOnly = false) { const el = document.activeElement; if (el.tagName.toLowerCase() !== 'input') { if (cipFields.combinations.length > 0) { @@ -1407,42 +1393,41 @@ cip.fillInFromActiveElement = function(suppressWarnings) { else { combination = cipFields.getCombination('username', fieldId); } + + if (passOnly) { + if (!_f(combination.password)) { + const message = 'Unable to find a password field'; + browser.runtime.sendMessage({ + action: 'alert', + args: [message] + }); + return; + } + } + delete combination.loginId; cip.fillInCredentials(combination, false, suppressWarnings); }; -cip.fillInFromActiveElementPassOnly = function(suppressWarnings) { +cip.fillInFromActiveElementTOTPOnly = function(suppressWarnings) { const el = document.activeElement; - if (el.tagName.toLowerCase() !== 'input') { - if (cipFields.combinations.length > 0) { - cip.fillInCredentials(cipFields.combinations[0], false, suppressWarnings); - } - return; - } - cipFields.setUniqueId(jQuery(el)); const fieldId = cipFields.prepareId(jQuery(el).attr('data-cip-id')); - let combination = null; - if (el.type && el.type.toLowerCase() === 'password') { - combination = cipFields.getCombination('password', fieldId); - } - else { - combination = cipFields.getCombination('username', fieldId); - } - if (!_f(combination.password)) { - const message = 'Unable to find a password field'; - browser.runtime.sendMessage({ - action: 'alert', - args: [message] - }); - return; + + if (cip.credentials[0]) { + const $sf = _fs(fieldId); + if (cip.credentials[0].stringFields && cip.credentials[0].stringFields.length > 0) { + const sFields = cip.credentials[0].stringFields; + for (const s of sFields) { + const val = s["KPH: {TOTP}"]; + if (val) { + cip.setValue($sf, val); + } + } + } } - - delete combination.loginId; - - cip.fillInCredentials(combination, true, suppressWarnings); }; cip.setValue = function(field, value) { @@ -1469,7 +1454,6 @@ cip.fillInStringFields = function(fields, StringFields, filledInFields) { for (let i = 0; i < fields.length; i++) { const $sf = _fs(fields[i]); if ($sf && StringFields[i]) { - //$sf.val(StringFields[i].Value); cip.setValue($sf, StringFields[i].Value); filledInFields.list.push(fields[i]); $filledIn = true; @@ -1525,7 +1509,7 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { filledIn = true; } - let list = {}; + let list = []; if (cip.fillInStringFields(combination.fields, cip.credentials[0].stringFields, list)) { cipForm.destroy(false, {'password': list.list[0], 'username': list.list[1]}); filledIn = true; @@ -1555,7 +1539,7 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { filledIn = true; } - let list = {}; + let list = []; if (cip.fillInStringFields(combination.fields, cip.credentials[combination.loginId].stringFields, list)) { cipForm.destroy(false, {'password': list.list[0], 'username': list.list[1]}); filledIn = true; @@ -1608,7 +1592,7 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { pField.data('unchanged', true); } - let list = {}; + let list = []; if (cip.fillInStringFields(combination.fields, valStringFields, list)) { cipForm.destroy(false, {'password': list.list[0], 'username': list.list[1]}); } diff --git a/keepassxc-browser/manifest.json b/keepassxc-browser/manifest.json index e43a67e..be1c515 100644 --- a/keepassxc-browser/manifest.json +++ b/keepassxc-browser/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "keepassxc-browser", - "version": "0.4.3", + "version": "0.4.4", "description": "KeePassXC integration for modern web browsers", "author": "Sami Vänttinen", "icons": { diff --git a/keepassxc-browser/options/options.html b/keepassxc-browser/options/options.html index 1a24336..81c57da 100644 --- a/keepassxc-browser/options/options.html +++ b/keepassxc-browser/options/options.html @@ -200,10 +200,10 @@