diff --git a/CHANGELOG b/CHANGELOG index 80f4837..89ec817 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +0.3.4 (??-??-2017) +========================= +- Added support for Lock Database button + 0.3.3 (12-10-2017) ========================= - Fixed database reloading when KeePassXC has restarted and database is opened diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js index cf2df09..ef75bd4 100644 --- a/keepassxc-browser/background/event.js +++ b/keepassxc-browser/background/event.js @@ -135,7 +135,7 @@ event.onReconnect = function(callback, tab) { keepass.connectToNative(); // Add a small timeout after reconnecting. Just to make sure. It's not pretty, I know :( - setTimeout(() => { + setTimeout(() => { keepass.generateNewKeyPair(); keepass.changePublicKeys(tab, (pkRes) => { keepass.getDatabaseHash((gdRes) => { @@ -151,6 +151,12 @@ event.onReconnect = function(callback, tab) { }, 2000); }; +event.lockDatabase = function(callback, tab) { + keepass.lockDatabase((response) => { + event.showStatus(true, tab, callback); + }, tab); +}; + event.onPopStack = function(callback, tab) { browserAction.stackPop(tab.id); browserAction.show(null, tab); @@ -259,5 +265,6 @@ event.messageHandlers = { 'stack_add': browserAction.stackAdd, 'update_available_keepassxc': event.onUpdateAvailableKeePassXC, 'generate_password': keepass.generatePassword, - 'reconnect': event.onReconnect -}; \ No newline at end of file + 'reconnect': event.onReconnect, + 'lock-database': event.lockDatabase +}; diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index e6420f3..917a589 100644 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -29,22 +29,26 @@ const kpActions = { ASSOCIATE: 'associate', TEST_ASSOCIATE: 'test-associate', GET_DATABASE_HASH: 'get-databasehash', - CHANGE_PUBLIC_KEYS: 'change-public-keys' + CHANGE_PUBLIC_KEYS: 'change-public-keys', + LOCK_DATABASE: 'lock-database' }; const kpErrors = { UNKNOWN_ERROR: 0, DATABASE_NOT_OPENED: 1, - DATABASE_HASH_NOT_RECEIVED: 2, - CLIENT_PUBLIC_KEY_NOT_RECEIVED: 3, - CANNOT_DECRYPT_MESSAGE: 4, - TIMEOUT_OR_NOT_CONNECTED: 5, - ACTION_CANCELLED_OR_DENIED: 6, - PUBLIC_KEY_NOT_FOUND: 7, - ASSOCIATION_FAILED: 8, - KEY_CHANGE_FAILED: 9, - ENCRYPTION_KEY_UNRECOGNIZED: 10, - NO_SAVED_DATABASES_FOUND: 11, + DATABASE_HASH_NOT_RECEIVED: 2, + CLIENT_PUBLIC_KEY_NOT_RECEIVED: 3, + CANNOT_DECRYPT_MESSAGE: 4, + TIMEOUT_OR_NOT_CONNECTED: 5, + ACTION_CANCELLED_OR_DENIED: 6, + PUBLIC_KEY_NOT_FOUND: 7, + ASSOCIATION_FAILED: 8, + KEY_CHANGE_FAILED: 9, + ENCRYPTION_KEY_UNRECOGNIZED: 10, + NO_SAVED_DATABASES_FOUND: 11, + INCORRECT_ACTION: 12, + EMPTY_MESSAGE_RECEIVED: 13, + NO_URL_PROVIDED: 14, errorMessages : { 0: { msg: 'Unknown error' }, @@ -58,7 +62,10 @@ const kpErrors = { 8: { msg: 'KeePassXC association failed, try again.' }, 9: { msg: 'Key change was not successful.' }, 10: { msg: 'Encryption key is not recognized' }, - 11: { msg: 'No saved databases found.' } + 11: { msg: 'No saved databases found.' }, + 12: { msg: 'Incorrect action.' }, + 13: { msg: 'Empty message received.' }, + 14: { msg: 'No URL provided.' } }, getError(errorCode) { @@ -117,7 +124,7 @@ keepass.updateCredentials = function(callback, tab, entryId, username, password, } } else if (response.error && response.errorCode) { - keepass.handleError(tab, response.error, response.errorCode); + keepass.handleError(tab, response.errorCode, response.error); } else { browserAction.showDefault(null, tab); @@ -193,7 +200,7 @@ keepass.retrieveCredentials = function(callback, tab, url, submiturl, forceCallb } } else if (response.error && response.errorCode) { - keepass.handleError(tab, response.error, response.errorCode); + keepass.handleError(tab, response.errorCode, response.error); } else { browserAction.showDefault(null, tab); @@ -290,7 +297,7 @@ keepass.generatePassword = function(callback, tab, forceCallback) { } } else if (response.error && response.errorCode) { - keepass.handleError(tab, response.error, response.errorCode); + keepass.handleError(tab, response.errorCode, response.error); } }); keepass.nativePort.postMessage(request); @@ -349,7 +356,7 @@ keepass.associate = function(callback, tab) { } } else if (response.error && response.errorCode) { - keepass.handleError(tab, response.error, response.errorCode); + keepass.handleError(tab, response.errorCode, response.error); } }); keepass.nativePort.postMessage(request); @@ -438,7 +445,7 @@ keepass.testAssociation = function(callback, tab, enableTimeout = false) { } } else if (response.error && response.errorCode) { - keepass.handleError(tab, response.error, response.errorCode); + keepass.handleError(tab, response.errorCode, response.error); } callback(keepass.isAssociated()); }); @@ -561,6 +568,50 @@ keepass.changePublicKeys = function(tab, callback) { keepass.nativePort.postMessage(message); }; +keepass.lockDatabase = function(callback, tab, forceCallback) { + if (!keepass.isConnected) { + keepass.handleError(tab, kpErrors.TIMEOUT_OR_NOT_CONNECTED); + callback([]); + return; + } + + const kpAction = kpActions.LOCK_DATABASE; + const nonce = nacl.randomBytes(keepass.keySize); + + const messageData = { + action: kpAction + }; + + const request = { + action: kpAction, + message: keepass.encrypt(messageData, nonce), + nonce: keepass.b64e(nonce), + clientID: keepass.clientID + }; + + keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, tab, (response) => { + if (response.message && response.nonce) { + const res = keepass.decrypt(response.message, response.nonce); + if (res) { + const message = nacl.util.encodeUTF8(res); + const parsed = JSON.parse(message); + keepass.setcurrentKeePassXCVersion(parsed.version); + + if (keepass.verifyResponse(parsed, response.nonce)) { + keepass.isDatabaseClosed = true; + keepass.handleError(tab, kpErrors.DATABASE_NOT_OPENED); + callback(false); + } + } + } + else if (response.error && response.errorCode) { + keepass.handleError(tab, response.errorCode, response.error); + } + callback(false); + }); + keepass.nativePort.postMessage(request); +}; + keepass.generateNewKeyPair = function() { keepass.keyPair = nacl.box.keyPair(); //console.log(keepass.b64e(keepass.keyPair.publicKey) + ' ' + keepass.b64e(keepass.keyPair.secretKey)); diff --git a/keepassxc-browser/manifest.json b/keepassxc-browser/manifest.json index f3b1281..944d50f 100644 --- a/keepassxc-browser/manifest.json +++ b/keepassxc-browser/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "keepassxc-browser", - "version": "0.3.3", + "version": "0.3.4", "description": "KeePassXC integration for modern web browsers", "author": "Sami Vänttinen", "icons": { diff --git a/keepassxc-browser/popups/popup.css b/keepassxc-browser/popups/popup.css index 9eabf3b..0dd0120 100644 --- a/keepassxc-browser/popups/popup.css +++ b/keepassxc-browser/popups/popup.css @@ -1,7 +1,7 @@ body { font-family: sans-serif; - min-width: 400px; - max-width: 400px; + min-width: 440px; + max-width: 440px; overflow-x: hidden; background-color: #eee; font-size: 15px; @@ -69,3 +69,6 @@ body { #update-available a:active { text-decoration: underline; } +#lock-database-button { + float: right; +} diff --git a/keepassxc-browser/popups/popup.html b/keepassxc-browser/popups/popup.html index f8b288a..76647c9 100644 --- a/keepassxc-browser/popups/popup.html +++ b/keepassxc-browser/popups/popup.html @@ -16,6 +16,7 @@