From 34362ff08ed60506298326935e90c8b72d88162b Mon Sep 17 00:00:00 2001
From: varjolintu
Date: Tue, 5 Feb 2019 10:22:00 +0200
Subject: [PATCH] Select group when adding new credentials
---
keepassxc-browser/_locales/en/messages.json | 36 ++
keepassxc-browser/background/browserAction.js | 10 +-
keepassxc-browser/background/event.js | 2 +
keepassxc-browser/background/keepass.js | 144 +++++++-
keepassxc-browser/background/page.js | 12 +-
keepassxc-browser/options/options.css | 4 +
keepassxc-browser/options/options.html | 24 ++
keepassxc-browser/options/options.js | 35 +-
keepassxc-browser/popups/popup.css | 25 +-
keepassxc-browser/popups/popup_remember.html | 18 +-
keepassxc-browser/popups/popup_remember.js | 138 +++++++-
keepassxc-protocol.md | 321 ++++++++++++------
12 files changed, 623 insertions(+), 146 deletions(-)
diff --git a/keepassxc-browser/_locales/en/messages.json b/keepassxc-browser/_locales/en/messages.json
index 9bd0fcf..8637bf5 100644
--- a/keepassxc-browser/_locales/en/messages.json
+++ b/keepassxc-browser/_locales/en/messages.json
@@ -307,6 +307,26 @@
"message": "Please choose the credentials you want to update.",
"description": "A popup message shown choosing what credentials user wants to update."
},
+ "popupRememberChooseGroup": {
+ "message": "Please choose the group you want to add the new credentials.",
+ "description": "A popup message shown choosing what group user wants to use for new credentials."
+ },
+ "popupRememberErrorDefaultGroupNotFound": {
+ "message": "Error: Specified default group not found. Creating all necessary groups.",
+ "description": "Error message shown when default group set cannot be found."
+ },
+ "popupRememberErrorCreatingNewGroup": {
+ "message": "New group(s) cannot be created.",
+ "description": "Error message shown when new groups cannot be created."
+ },
+ "popupRememberErrorPasswordNotChanged": {
+ "message": "Error: Credentials not updated. The password has not been changed.",
+ "description": "Error message shown when credential password is not changed."
+ },
+ "popupRememberErrorCannotSaveCredentials": {
+ "message": "Error: Credentials cannot be saved or updated.",
+ "description": "Error message shown when credentials cannot be saved or updated."
+ },
"popupLoginText": {
"message": "Select the login information you would like to get entered into the page.",
"description": "A popup message shown when one or multiple credentials are present."
@@ -447,6 +467,22 @@
"message": "Maximum (Number of) Redirects:",
"description": "RMaximum (Number of) Redirects options text."
},
+ "optionsLabelDefaultGroup": {
+ "message": "Default group for saving new passwords:",
+ "description": "Default group options text."
+ },
+ "optionsDefaultGroupHelpText": {
+ "message": "Separate the group with slashes, for example: Group/ChildGroup.",
+ "description": "Default group help text."
+ },
+ "optionsLabelDefaultGroupCheckboxText": {
+ "message": "Always ask where to save new credentials",
+ "description": "Default group checkbox help text."
+ },
+ "optionsLabelDefaultGroupCheckboxHelpText": {
+ "message": "When enabled, the popup shows a group listing.",
+ "description": "Default checkbox explanation help text."
+ },
"optionsCheckboxUsePasswordGenerator": {
"message": "Activate password generator.",
"description": "Activate password generator checkbox text."
diff --git a/keepassxc-browser/background/browserAction.js b/keepassxc-browser/background/browserAction.js
index 4f6835d..c3e8b1b 100755
--- a/keepassxc-browser/background/browserAction.js
+++ b/keepassxc-browser/background/browserAction.js
@@ -167,13 +167,13 @@ browserAction.stackPop = function(tabId) {
browserAction.stackPush = function(data, tabId) {
const id = tabId || page.currentTabId;
- browserAction.removeLevelFromStack(null, {'id': id}, data.level, '<=', true);
+ browserAction.removeLevelFromStack(null, { 'id': id }, data.level, '<=', true);
page.tabs[id].stack.push(data);
};
browserAction.stackUnshift = function(data, tabId) {
const id = tabId || page.currentTabId;
- browserAction.removeLevelFromStack(null, {'id': id}, data.level, '<=', true);
+ browserAction.removeLevelFromStack(null, { 'id': id }, data.level, '<=', true);
page.tabs[id].stack.unshift(data);
};
@@ -193,7 +193,7 @@ browserAction.removeRememberPopup = function(callback, tab, removeImmediately) {
const currentMS = Date.now();
if (removeImmediately || (data.visibleForPageUpdates <= 0 && data.redirectOffset > 0)) {
browserAction.stackPop(tab.id);
- browserAction.show(null, {"id": tab.id});
+ browserAction.show(null, { 'id': tab.id });
page.clearCredentials(tab.id);
} else if (!isNaN(data.visibleForPageUpdates) && data.redirectOffset > 0 && currentMS >= data.redirectOffset) {
data.visibleForPageUpdates -= 1;
@@ -202,7 +202,7 @@ browserAction.removeRememberPopup = function(callback, tab, removeImmediately) {
};
browserAction.setRememberPopup = function(tabId, username, password, url, usernameExists, credentialsList) {
- browser.storage.local.get({'settings': {}}).then(function(item) {
+ browser.storage.local.get({ 'settings': {} }).then(function(item) {
const settings = item.settings;
// Don't show anything if the site is in the ignore
@@ -233,7 +233,7 @@ browserAction.setRememberPopup = function(tabId, username, password, url, userna
index: 0,
counter: 0,
max: 2,
- icons: ['icon_remember_red_background_19x19.png', 'icon_remember_red_lock_19x19.png']
+ icons: [ 'icon_remember_red_background_19x19.png', 'icon_remember_red_lock_19x19.png' ]
},
icon: 'icon_remember_red_background_19x19.png',
popup: 'popup_remember.html'
diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js
index 921374f..3414888 100755
--- a/keepassxc-browser/background/event.js
+++ b/keepassxc-browser/background/event.js
@@ -284,8 +284,10 @@ kpxcEvent.messageHandlers = {
'add_credentials': keepass.addCredentials,
'associate': keepass.associate,
'check_update_keepassxc': kpxcEvent.onCheckUpdateKeePassXC,
+ 'create_new_group': keepass.createNewGroup,
'generate_password': keepass.generatePassword,
'get_connected_database': kpxcEvent.onGetConnectedDatabase,
+ 'get_database_groups': keepass.getDatabaseGroups,
'get_keepassxc_versions': kpxcEvent.onGetKeePassXCVersions,
'get_status': kpxcEvent.onGetStatus,
'get_tab_information': kpxcEvent.onGetTabInformation,
diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js
index 8549fbc..4b18c4d 100755
--- a/keepassxc-browser/background/keepass.js
+++ b/keepassxc-browser/background/keepass.js
@@ -33,7 +33,9 @@ const kpActions = {
CHANGE_PUBLIC_KEYS: 'change-public-keys',
LOCK_DATABASE: 'lock-database',
DATABASE_LOCKED: 'database-locked',
- DATABASE_UNLOCKED: 'database-unlocked'
+ DATABASE_UNLOCKED: 'database-unlocked',
+ GET_DATABASE_GROUPS: 'get-database-groups',
+ CREATE_NEW_GROUP: 'create-new-group'
};
const kpErrors = {
@@ -127,11 +129,11 @@ keepass.sendNativeMessage = function(request, enableTimeout = false) {
});
};
-keepass.addCredentials = function(callback, tab, username, password, url) {
- keepass.updateCredentials(callback, tab, null, username, password, url);
+keepass.addCredentials = function(callback, tab, username, password, url, group, groupUuid) {
+ keepass.updateCredentials(callback, tab, null, username, password, url, group, groupUuid);
};
-keepass.updateCredentials = function(callback, tab, entryId, username, password, url) {
+keepass.updateCredentials = function(callback, tab, entryId, username, password, url, group, groupUuid) {
page.debug('keepass.updateCredentials(callback, {1}, {2}, {3}, [password], {4})', tab.id, entryId, username, url);
if (tab && page.tabs[tab.id]) {
page.tabs[tab.id].errorMessage = null;
@@ -162,6 +164,11 @@ keepass.updateCredentials = function(callback, tab, entryId, username, password,
messageData.uuid = entryId;
}
+ if (group && groupUuid) {
+ messageData.group = group;
+ messageData.groupUuid = groupUuid;
+ }
+
const request = {
action: kpAction,
message: keepass.encrypt(messageData, nonce),
@@ -678,6 +685,135 @@ keepass.lockDatabase = function(tab) {
});
};
+keepass.getDatabaseGroups = function(callback, tab) {
+ keepass.testAssociation((taResponse) => {
+ if (!taResponse) {
+ browserAction.showDefault(null, tab);
+ callback([]);
+ return;
+ }
+
+ if (tab && page.tabs[tab.id]) {
+ page.tabs[tab.id].errorMessage = null;
+ }
+
+ if (!keepass.isConnected) {
+ callback([]);
+ return;
+ }
+
+ let groups = [];
+ const kpAction = kpActions.GET_DATABASE_GROUPS;
+ const nonce = keepass.getNonce();
+ const incrementedNonce = keepass.incrementedNonce(nonce);
+
+ const messageData = {
+ action: kpAction
+ };
+
+ const request = {
+ action: kpAction,
+ message: keepass.encrypt(messageData, nonce),
+ nonce: nonce,
+ clientID: keepass.clientID
+ };
+
+ keepass.sendNativeMessage(request).then((response) => {
+ if (response.message && response.nonce) {
+ const res = keepass.decrypt(response.message, response.nonce);
+ if (!res) {
+ keepass.handleError(tab, kpErrors.CANNOT_DECRYPT_MESSAGE);
+ callback([]);
+ return;
+ }
+
+ const message = nacl.util.encodeUTF8(res);
+ const parsed = JSON.parse(message);
+
+ if (keepass.verifyResponse(parsed, incrementedNonce)) {
+ groups = parsed.groups;
+ groups.defaultGroup = page.settings.defaultGroup;
+ groups.defaultGroupAlwaysAsk = page.settings.defaultGroupAlwaysAsk;
+ keepass.updateLastUsed(keepass.databaseHash);
+ callback(groups);
+ } else {
+ console.log('getDatabaseGroups rejected');
+ callback([]);
+ }
+ } else if (response.error && response.errorCode) {
+ keepass.handleError(tab, response.errorCode, response.error);
+ callback([]);
+ } else {
+ browserAction.showDefault(null, tab);
+ callback([]);
+ }
+ });
+ }, tab, false);
+};
+
+keepass.createNewGroup = function(callback, tab, groupName) {
+ keepass.testAssociation((taResponse) => {
+ if (!taResponse) {
+ browserAction.showDefault(null, tab);
+ callback([]);
+ return;
+ }
+
+ if (tab && page.tabs[tab.id]) {
+ page.tabs[tab.id].errorMessage = null;
+ }
+
+ if (!keepass.isConnected) {
+ callback([]);
+ return;
+ }
+
+ const kpAction = kpActions.CREATE_NEW_GROUP;
+ const nonce = keepass.getNonce();
+ const incrementedNonce = keepass.incrementedNonce(nonce);
+
+ const messageData = {
+ action: kpAction,
+ groupName: groupName
+ };
+
+ const request = {
+ action: kpAction,
+ message: keepass.encrypt(messageData, nonce),
+ nonce: nonce,
+ clientID: keepass.clientID
+ };
+
+ keepass.sendNativeMessage(request).then((response) => {
+ if (response.message && response.nonce) {
+ const res = keepass.decrypt(response.message, response.nonce);
+ if (!res) {
+ keepass.handleError(tab, kpErrors.CANNOT_DECRYPT_MESSAGE);
+ callback([]);
+ return;
+ }
+
+ const message = nacl.util.encodeUTF8(res);
+ const parsed = JSON.parse(message);
+
+ if (keepass.verifyResponse(parsed, incrementedNonce)) {
+ keepass.updateLastUsed(keepass.databaseHash);
+ callback(parsed);
+ } else {
+ console.log('getDatabaseGroups rejected');
+ callback([]);
+ }
+ } else if (response.error && response.errorCode) {
+ keepass.handleError(tab, response.errorCode, response.error);
+ callback([]);
+ } else {
+ browserAction.showDefault(null, tab);
+ callback([]);
+ }
+ });
+ }, tab, false);
+};
+
keepass.generateNewKeyPair = function() {
keepass.keyPair = nacl.box.keyPair();
//console.log(nacl.util.encodeBase64(keepass.keyPair.publicKey) + ' ' + nacl.util.encodeBase64(keepass.keyPair.secretKey));
diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js
index 95c8884..4db0bc4 100755
--- a/keepassxc-browser/background/page.js
+++ b/keepassxc-browser/background/page.js
@@ -9,7 +9,9 @@ const defaultSettings = {
autoRetrieveCredentials: true,
showNotifications: true,
showLoginNotifications: true,
- saveDomainOnly: true
+ saveDomainOnly: true,
+ defaultGroup: '',
+ defaultGroupAlwaysAsk: false
};
var page = {};
@@ -49,7 +51,13 @@ page.initSettings = function() {
if (!('saveDomainOnly' in page.settings)) {
page.settings.saveDomainOnly = defaultSettings.saveDomainOnly;
}
- browser.storage.local.set({'settings': page.settings});
+ if (!('defaultGroup' in page.settings)) {
+ page.settings.defaultGroup = defaultSettings.defaultGroup;
+ }
+ if (!('defaultGroupAlwaysAsk' in page.settings)) {
+ page.settings.defaultGroupAlwaysAsk = defaultSettings.defaultGroupAlwaysAsk;
+ }
+ browser.storage.local.set({ 'settings': page.settings });
resolve(page.settings);
});
});
diff --git a/keepassxc-browser/options/options.css b/keepassxc-browser/options/options.css
index 59fcdcc..735a9f2 100644
--- a/keepassxc-browser/options/options.css
+++ b/keepassxc-browser/options/options.css
@@ -119,6 +119,10 @@ h2+hr {
width: 75%;
}
+#defaultGroup {
+ width: 50%;
+}
+
tr.clone {
display: none;
}
diff --git a/keepassxc-browser/options/options.html b/keepassxc-browser/options/options.html
index e364619..fe617df 100644
--- a/keepassxc-browser/options/options.html
+++ b/keepassxc-browser/options/options.html
@@ -87,6 +87,30 @@
+
+
+
+