Draft 290423

This commit is contained in:
varjolintu 2023-04-29 10:45:28 +03:00
parent 098b2af2ab
commit 4f082dda84
8 changed files with 87 additions and 51 deletions

View file

@ -87,6 +87,7 @@
"assertSearchField": true,
"assertSearchForm": true,
"assertTOTPField": true,
"AddCredentials": true,
"AssociatedAction": true,
"Autocomplete": true,
"bootstrap": true,

View file

@ -16,6 +16,17 @@ kpxcEvent.getColorTheme = async function(tab) {
};
kpxcEvent.getConnectedDatabase = async function() {
/*let hash = keepass.associated.hash;
// Check if one database is open but not active
// TODO: Does not work if two are open and active one is closed and non-associated
const associatedDatabases = keepass.databaseStatuses.statuses.filter(ds => ds.associated);
if (associatedDatabases.length === 1
&& keepass.databaseAssociationStatuses.isAnyAssociated
&& !keepass.associated.value) {
hash = associatedDatabases[0].hash;
}*/
return Promise.resolve({
count: Object.keys(keepass.keyRing).length,
identifier: (keepass.keyRing[keepass.associated.hash]) ? keepass.keyRing[keepass.associated.hash].id : null
@ -49,7 +60,7 @@ kpxcEvent.getStatus = async function(tab, args = []) {
configured = response.isAnyAssociated;
} else {
// TODO: This does not update when db is locked or just opened
configured = keepass.databaseAssosiationStatuses?.isAnyAssociated; // ?
configured = keepass.databaseAssociationStatuses?.isAnyAssociated; // ?
}
} else {
if (!internalPoll) {
@ -238,7 +249,7 @@ kpxcEvent.showStatus = async function(tab, configured, internalPoll) {
associated: keepass.isAssociated(),
configured: configured,
databaseClosed: keepass.isDatabaseClosed,
databaseAssociationStatuses: keepass.databaseAssosiationStatuses,
databaseAssociationStatuses: keepass.databaseAssociationStatuses,
encryptionKeyUnrecognized: keepass.isEncryptionKeyUnrecognized,
error: errorMessage || null,
identifier: keyId,

View file

@ -1,8 +1,9 @@
'use strict';
const keepass = {};
keepass.associated = { 'value': false, 'hash': null };
keepass.databaseAssosiationStatuses = {};
keepass.associated = { value: false, hash: null };
keepass.databaseAssociationStatuses = {};
keepass.databaseStatuses = [];
keepass.keyPair = { publicKey: null, secretKey: null };
keepass.serverPublicKey = '';
keepass.clientID = '';
@ -104,6 +105,10 @@ keepass.createNewGroup = async function(tab, args = []) {
return keepass.protocolV2 ? await protocol.createNewGroup(tab, args) : await keepassProtocol.createNewGroup(tab, args);
};
keepass.generatePassword = async function(tab, args = []) {
return keepass.protocolV2 ? await protocol.generatePassword(tab, args) : await keepassProtocol.generatePassword(tab, args);
};
keepass.getCredentials = async function(tab, args = []) {
return keepass.protocolV2 ? await protocol.getCredentials(tab, args) : await keepassProtocol.retrieveCredentials(tab, args);
};

View file

@ -239,16 +239,15 @@ keepassProtocol.getDatabaseHash = async function(tab, args = []) {
connectedKeys: Object.keys(keepass.keyRing) // This will be removed in the future
};
// Why is this here?
/*const encrypted = protocolClient.encrypt(messageData, nonce);
const encrypted = protocolClient.encrypt(messageData, nonce);
if (encrypted.length <= 0) {
keepass.handleError(tab, kpErrors.PUBLIC_KEY_NOT_FOUND);
keepass.updateDatabaseHashToContent();
return keepass.databaseHash;
}*/
}
try {
const request = keepassClient.buildRequest(kpAction, protocolClient.encrypt(messageData, nonce), nonce, keepass.clientID, triggerUnlock);
const request = keepassClient.buildRequest(kpAction, encrypted, nonce, keepass.clientID, triggerUnlock);
const response = await keepassClient.sendNativeMessage(request, enableTimeout);
if (response.message && response.nonce) {
const res = protocolClient.decrypt(response.message, response.nonce);
@ -562,12 +561,12 @@ keepassProtocol.updateCredentials = async function(tab, args = []) {
// KeePassXC versions lower than 2.5.0 will have an empty parsed.error
let successMessage = response.error;
if (response.error === 'success' || response.error === '') {
successMessage = entryId ? 'updated' : 'created';
successMessage = entryId ? AddCredentials.UPDATED : AddCredentials.CREATED;
}
return successMessage;
} else {
return 'error';
return AddCredentials.ERROR;
}
} catch (err) {
logError(`updateCredentials failed: ${err}`);

View file

@ -100,12 +100,14 @@ protocol.createNewGroup = async function(tab, args = []) {
keepass.clearErrorMessage(tab);
const [ groupName ] = args;
const [ dbid ] = keepass.getCryptoKey();
//const [ dbid ] = keepass.getCryptoKey();
const messageData = {
action: kpActions.CREATE_NEW_GROUP,
id: dbid,
//id: dbid,
groupName: groupName,
keys: protocol.getKeys(), // Added
hash: keepass.databaseHash // Added
};
try {
@ -128,25 +130,27 @@ protocol.createNewGroup = async function(tab, args = []) {
protocol.generatePassword = async function(tab, args = []) {
if (!keepass.isConnected) {
return [];
return undefined;
}
if (!keepass.compareVersion(keepass.requiredKeePassXC, keepass.currentKeePassXC)) {
return [];
return undefined;
}
// TODO: Return '' or [] ..?
let password;
const messageData = {
action: kpActions.GENERATE_PASSWORD,
clientID: keepass.clientID,
requestID: protocolClient.getRequestId() // Needed?
};
try {
const response = await protocolClient.sendMessage(tab, messageData);
if (response) {
if (response.error && response.errorCode) {
keepass.handleError(tab, response.errorCode);
return undefined;
}
password = response.entries ?? response.password;
keepass.updateLastUsed(keepass.databaseHash); // ?
} else {
@ -156,7 +160,7 @@ protocol.generatePassword = async function(tab, args = []) {
return password;
} catch (err) {
logError(`generatePassword failed: ${err}`);
return [];
return undefined;
}
};
@ -220,18 +224,24 @@ protocol.getDatabaseGroups = async function(tab, args = []) {
keepass.clearErrorMessage(tab);
const [ dbid ] = keepass.getCryptoKey();
//const [ dbid ] = keepass.getCryptoKey();
let groups = [];
const messageData = {
action: kpActions.GET_DATABASE_GROUPS,
id: dbid
//id: dbid,
keys: protocol.getKeys(), // Added
hash: keepass.databaseHash // Added
};
try {
// TODO: Handle errors
const response = await protocolClient.sendMessage(tab, messageData);
if (response) {
if (response.error && response.errorCode) {
keepass.handleError(tab, response.errorCode);
return [];
}
groups = response.groups;
groups.defaultGroup = page.settings.defaultGroup;
groups.defaultGroupAlwaysAsk = page.settings.defaultGroupAlwaysAsk;
@ -300,7 +310,9 @@ protocol.getTotp = async function(tab, args = []) {
const messageData = {
action: kpActions.GET_TOTP,
uuid: uuid
uuid: uuid,
keys: protocol.getKeys(), // Added
hash: keepass.databaseHash // Added
};
try {
@ -405,6 +417,10 @@ protocol.testAssociationFromDatabaseStatuses = async function(tab, args = []) {
console.log('Current one is not associated');
}
// Current association status
keepass.associated.hash = currentDatabaseStatus[0]?.hash;
keepass.associated.value = isCurrentAssociated;
// This should be true only if all databases are locked
keepass.isDatabaseClosed = areAllLocked; // ?
@ -413,7 +429,8 @@ protocol.testAssociationFromDatabaseStatuses = async function(tab, args = []) {
result.databaseHash = databaseStatuses.hash;
result.isAnyAssociated = isAnyAssociated;
keepass.databaseAssosiationStatuses = result;
keepass.databaseStatuses = databaseStatuses;
keepass.databaseAssociationStatuses = result;
return result;
};
@ -427,11 +444,13 @@ protocol.updateCredentials = async function(tab, args = []) {
const messageData = {
action: kpActions.CREATE_CREDENTIALS,
id: dbid,
hash: keepass.databaseHash, // Added
keys: protocol.getKeys(), // Added
//id: dbid, // Needed?
login: username,
password: password,
url: url,
submitUrl: url
submitUrl: url,
};
if (entryId) {
@ -448,18 +467,15 @@ protocol.updateCredentials = async function(tab, args = []) {
}
try {
// TODO: Check response messages
const response = await protocolClient.sendMessage(tab, messageData);
if (response) {
// KeePassXC versions lower than 2.5.0 will have an empty parsed.error
let successMessage = response.error;
if (response?.result === true || response.error === '') {
successMessage = entryId ? 'updated' : 'created';
if (response?.result === true) {
return entryId ? AddCredentials.UPDATED : AddCredentials.CREATED;
}
return successMessage;
return AddCredentials.CANCELED;
} else {
return 'error';
return AddCredentials.ERROR;
}
} catch (err) {
logError(`updateCredentials failed: ${err}`);

View file

@ -56,6 +56,13 @@ const ManualFill = {
BOTH: 2
};
const AddCredentials = {
CANCELED: 0,
CREATED: 1,
ERROR: 2,
UPDATED: 3
};
// Match hostname or path with wildcards
const matchWithRegex = function(firstUrlPart, secondUrlPart, hostnameUsed = false) {
if (firstUrlPart === secondUrlPart) {

View file

@ -281,7 +281,7 @@ kpxcBanner.updateCredentials = async function(credentials = {}) {
args: [ url, '', true ] // Sets triggerUnlock to true
}).then(async creds => {
if (!creds || creds.length !== credentials.list.length) {
kpxcBanner.verifyResult('error');
kpxcBanner.verifyResult(AddCredentials.ERROR);
return;
}
@ -302,15 +302,15 @@ kpxcBanner.updateCredentials = async function(credentials = {}) {
};
kpxcBanner.verifyResult = async function(code) {
if (code === 'error') {
if (code === AddCredentials.ERROR) {
kpxcUI.createNotification('error', tr('rememberErrorCannotSaveCredentials'));
} else if (code === 'created') {
} else if (code === AddCredentials.CREATED) {
kpxcUI.createNotification('success', tr('rememberCredentialsSaved', kpxcBanner.credentials.username || tr('rememberEmptyUsername')));
await kpxc.retrieveCredentials(true); // Forced reload
} else if (code === 'updated') {
} else if (code === AddCredentials.UPDATED) {
kpxcUI.createNotification('success', tr('rememberCredentialsUpdated', kpxcBanner.credentials.username || tr('rememberEmptyUsername')));
await kpxc.retrieveCredentials(true); // Forced reload
} else if (code === 'canceled') {
} else if (code === AddCredentials.CANCELED) {
kpxcUI.createNotification('warning', tr('rememberCredentialsNotSaved'));
} else {
kpxcUI.createNotification('error', tr('rememberErrorDatabaseClosed'));

View file

@ -303,18 +303,9 @@ kpxcPasswordDialog.fill = function(e) {
}
}
kpxcPasswordDialog.input.value = password.value;
kpxcPasswordDialog.input.dispatchEvent(new Event('keydown', { bubbles: true }));
kpxcPasswordDialog.input.dispatchEvent(new Event('keyup', { bubbles: true }));
kpxcPasswordDialog.input.dispatchEvent(new Event('input', { bubbles: true }));
kpxcPasswordDialog.input.dispatchEvent(new Event('change', { bubbles: true }));
fillPassword(kpxcPasswordDialog.input, password.value);
if (kpxcPasswordDialog.nextField) {
kpxcPasswordDialog.nextField.value = password.value;
kpxcPasswordDialog.nextField.dispatchEvent(new Event('keydown', { bubbles: true }));
kpxcPasswordDialog.nextField.dispatchEvent(new Event('keyup', { bubbles: true }));
kpxcPasswordDialog.nextField.dispatchEvent(new Event('input', { bubbles: true }));
kpxcPasswordDialog.nextField.dispatchEvent(new Event('change', { bubbles: true }));
fillPassword(kpxcPasswordDialog.nextField, password.value);
}
};
@ -339,9 +330,7 @@ kpxcPasswordDialog.newFill = function(elem, password) {
}
}
elem.value = password;
elem.dispatchEvent(new Event('input', { bubbles: true }));
elem.dispatchEvent(new Event('change', { bubbles: true }));
fillPassword(elem, password);
};
kpxcPasswordDialog.copyPasswordToClipboard = function() {
@ -405,3 +394,11 @@ const useKeePassXCPasswordGenerator = async function() {
return result;
};
const fillPassword = function(elem, password) {
elem.value = password;
elem.dispatchEvent(new Event('keydown', { bubbles: true }));
elem.dispatchEvent(new Event('keyup', { bubbles: true }));
elem.dispatchEvent(new Event('input', { bubbles: true }));
elem.dispatchEvent(new Event('change', { bubbles: true }));
};