avoid no pubkey with guards, make sure primary and secondary authorization match

pull/539/head
Ryan Tharp 6 years ago
parent 9ba641c8c1
commit 206d29b033

@ -860,6 +860,7 @@ class LokiPublicChannelAPI {
if (pendingMessages.length) { if (pendingMessages.length) {
const newSlavePrimaryMap = {}; const newSlavePrimaryMap = {};
const checkSigs = {};
// console.log('premultiDeviceResults', pubKeys) // console.log('premultiDeviceResults', pubKeys)
if (pubKeys.length) { if (pubKeys.length) {
@ -878,6 +879,10 @@ class LokiPublicChannelAPI {
const { authorisations } = note.value; const { authorisations } = note.value;
if (Array.isArray(authorisations)) { if (Array.isArray(authorisations)) {
authorisations.forEach(auth => { authorisations.forEach(auth => {
if (auth.secondaryDevicePubKey !== user.username) {
// this is not the authorization we're looking for
return;
}
// console.log('auth', auth); // console.log('auth', auth);
try { try {
// request (secondary wants to be paired with this primary) // request (secondary wants to be paired with this primary)
@ -907,6 +912,7 @@ class LokiPublicChannelAPI {
); );
return; return;
} }
checkSigs[user.username] = auth;
newSlavePrimaryMap[user.username] = newSlavePrimaryMap[user.username] =
auth.primaryDevicePubKey; auth.primaryDevicePubKey;
} catch (e) { } catch (e) {
@ -956,68 +962,85 @@ class LokiPublicChannelAPI {
pendingMessages = []; // free memory pendingMessages = []; // free memory
const verifiedPrimaryPKs = []; const verifiedPrimaryPKs = [];
// get a list of all of primary pubKeys to verify the secondaryDevice if (primaryPubKeys.length) {
const primaryDeviceResults = await lokiFileServerAPI.getDeviceMappingForUsers( // get a list of all of primary pubKeys to verify the secondaryDevice
primaryPubKeys const primaryDeviceResults = await lokiFileServerAPI.getDeviceMappingForUsers(
); primaryPubKeys
// go through primaryDeviceResults );
primaryDeviceResults.forEach(user => { // go through primaryDeviceResults
let found = false; primaryDeviceResults.forEach(user => {
if (user.annotations) { let found = false;
user.annotations.forEach(note => { if (user.annotations) {
if (note.type === 'network.loki.messenger.devicemapping') { user.annotations.forEach(note => {
if (note.value.isPrimary) { if (note.type === 'network.loki.messenger.devicemapping') {
const { authorisations } = note.value; if (note.value.isPrimary) {
if (Array.isArray(authorisations)) { const { authorisations } = note.value;
authorisations.forEach(auth => { if (Array.isArray(authorisations)) {
try { authorisations.forEach(auth => {
// grant (primary approves this secondary) try {
window.libloki.crypto.verifyPairingSignature( // grant (primary approves this secondary)
auth.primaryDevicePubKey, window.libloki.crypto.verifyPairingSignature(
auth.secondaryDevicePubKey, auth.primaryDevicePubKey,
dcodeIO.ByteBuffer.wrap( auth.secondaryDevicePubKey,
auth.grantSignature, dcodeIO.ByteBuffer.wrap(
'base64' auth.grantSignature,
).toArrayBuffer(), 'base64'
textsecure.protobuf.PairingAuthorisationMessage.Type ).toArrayBuffer(),
.GRANT textsecure.protobuf.PairingAuthorisationMessage.Type
); .GRANT
if ( );
verifiedPrimaryPKs.indexOf( if (
`@${auth.primaryDevicePubKey}` verifiedPrimaryPKs.indexOf(
) === -1 `@${auth.primaryDevicePubKey}`
) { ) === -1
verifiedPrimaryPKs.push( ) {
`@${auth.primaryDevicePubKey}` verifiedPrimaryPKs.push(
`@${auth.primaryDevicePubKey}`
);
}
// assuming both are ordered
// make sure our secondary and primary authorization match
if (
JSON.stringify(
checkSigs[auth.secondaryDevicePubKey]
) !== JSON.stringify(auth)
) {
// should hopefully never happen
log.warn(
`Valid authorizations from ${
auth.secondaryDevicePubKey
} does not match ${auth.primaryDevicePubKey}`
);
return;
}
found = true;
} catch (e) {
log.warn(
`Invalid grant signature on PrimaryPubKey ${
auth.primaryDevicePubKey
}`
); );
} }
found = true; });
} catch (e) { }
log.warn(
`Invalid grant signature on PrimaryPubKey ${
auth.primaryDevicePubKey
}`
);
}
});
} }
} }
});
}
if (found) {
return;
}
// if not verified remove this user pubkey from newSlavePrimaryMap
Object.keys(newSlavePrimaryMap).forEach(slaveKey => {
if (newSlavePrimaryMap[slaveKey] === user.username) {
log.warn(
`removing unverifible ${slaveKey} to ${user.username} mapping`
);
delete newSlavePrimaryMap[slaveKey];
} }
}); });
}
if (found) {
return;
}
// if not verified remove this user pubkey from newSlavePrimaryMap
Object.keys(newSlavePrimaryMap).forEach(slaveKey => {
if (newSlavePrimaryMap[slaveKey] === user.username) {
log.warn(
`removing unverifible ${slaveKey} to ${user.username} mapping`
);
delete newSlavePrimaryMap[slaveKey];
}
}); });
}); }
// update this.slavePrimaryMap live with updated map // update this.slavePrimaryMap live with updated map
this.slavePrimaryMap = newSlavePrimaryMap; this.slavePrimaryMap = newSlavePrimaryMap;
@ -1025,19 +1048,22 @@ class LokiPublicChannelAPI {
`Updated device mappings ${JSON.stringify(this.slavePrimaryMap)}` `Updated device mappings ${JSON.stringify(this.slavePrimaryMap)}`
); );
// get final list of verified chat server profile names // if we have verified primaryKeys then update them
const verifiedDeviceResults = await this.serverAPI.getUsersAnnotations( if (verifiedPrimaryPKs.length) {
pubKeys // get final list of verified chat server profile names
); const verifiedDeviceResults = await this.serverAPI.getUsersAnnotations(
// console.log('verifiedDeviceResults', verifiedDeviceResults) verifiedPrimaryPKs
);
// go through verifiedDeviceResults // console.log('verifiedDeviceResults', verifiedDeviceResults)
const newPrimaryUserProfileName = {};
verifiedDeviceResults.forEach(user => { // go through verifiedDeviceResults
newPrimaryUserProfileName[user.username] = user.name; const newPrimaryUserProfileName = {};
}); verifiedDeviceResults.forEach(user => {
// replace whole newPrimaryUserProfileName[user.username] = user.name;
this.primaryUserProfileName = newPrimaryUserProfileName; });
// replace whole
this.primaryUserProfileName = newPrimaryUserProfileName;
}
// process remaining messages // process remaining messages
const ourNumber = textsecure.storage.user.getNumber(); const ourNumber = textsecure.storage.user.getNumber();

Loading…
Cancel
Save