Clear stale sender certificates

This commit is contained in:
Scott Nonnenberg 2021-09-27 10:31:34 -07:00 committed by GitHub
parent 9888e6d38f
commit cf4c81b11c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 11 deletions

View file

@ -760,6 +760,11 @@ export async function startApp(): Promise<void> {
}); });
} }
if (window.isBeforeVersion(lastVersion, 'v5.18.0')) {
await window.storage.remove('senderCertificate');
await window.storage.remove('senderCertificateNoE164');
}
// This one should always be last - it could restart the app // This one should always be last - it could restart the app
if (window.isBeforeVersion(lastVersion, 'v1.15.0-beta.5')) { if (window.isBeforeVersion(lastVersion, 'v1.15.0-beta.5')) {
await deleteAllLogs(); await deleteAllLogs();
@ -3345,7 +3350,7 @@ export async function startApp(): Promise<void> {
); );
try { try {
log.info('unlinkAndDisconnect: removing configuration'); log.info(`unlinkAndDisconnect: removing configuration, mode ${mode}`);
await window.textsecure.storage.protocol.removeAllConfiguration(mode); await window.textsecure.storage.protocol.removeAllConfiguration(mode);
// This was already done in the database with removeAllConfiguration; this does it // This was already done in the database with removeAllConfiguration; this does it

View file

@ -75,6 +75,24 @@ export class SenderCertificateService {
return this.fetchCertificate(mode); return this.fetchCertificate(mode);
} }
// This is intended to be called when our credentials have been deleted, so any fetches
// made until this function is complete would fail anyway.
async clear(): Promise<void> {
log.info(
'Sender certificate service: Clearing in-progress fetches and ' +
'deleting cached certificates'
);
await Promise.all(this.fetchPromises.values());
const { storage } = this;
assert(
storage,
'Sender certificate service method was called before it was initialized'
);
await storage.remove('senderCertificate');
await storage.remove('senderCertificateNoE164');
}
private getStoredCertificate( private getStoredCertificate(
mode: SenderCertificateMode mode: SenderCertificateMode
): undefined | SerializedCertificateType { ): undefined | SerializedCertificateType {

View file

@ -218,5 +218,32 @@ describe('SenderCertificateService', () => {
assert.isUndefined(await service.get(SenderCertificateMode.WithE164)); assert.isUndefined(await service.get(SenderCertificateMode.WithE164));
}); });
it('clear waits for any outstanding requests then erases storage', async () => {
let count = 0;
fakeServer = {
getSenderCertificate: sinon.spy(async () => {
await new Promise(resolve => setTimeout(resolve, 500));
count += 1;
return {
certificate: Bytes.toBase64(fakeValidEncodedCertificate),
};
}),
};
const service = initializeTestService();
service.get(SenderCertificateMode.WithE164);
service.get(SenderCertificateMode.WithoutE164);
await service.clear();
assert.equal(count, 2);
assert.isUndefined(fakeStorage.get('senderCertificate'));
assert.isUndefined(fakeStorage.get('senderCertificateNoE164'));
});
}); });
}); });

View file

@ -17,6 +17,8 @@ import ProvisioningCipher from './ProvisioningCipher';
import { IncomingWebSocketRequest } from './WebsocketResources'; import { IncomingWebSocketRequest } from './WebsocketResources';
import createTaskWithTimeout from './TaskWithTimeout'; import createTaskWithTimeout from './TaskWithTimeout';
import * as Bytes from '../Bytes'; import * as Bytes from '../Bytes';
import { RemoveAllConfiguration } from '../types/RemoveAllConfiguration';
import { senderCertificateService } from '../services/senderCertificate';
import { import {
deriveAccessKey, deriveAccessKey,
generateRegistrationId, generateRegistrationId,
@ -499,33 +501,32 @@ export default class AccountManager extends EventTarget {
if (uuidChanged || numberChanged) { if (uuidChanged || numberChanged) {
if (uuidChanged) { if (uuidChanged) {
log.warn( log.warn(
'New uuid is different from old uuid; deleting all previous data' 'createAccount: New uuid is different from old uuid; deleting all previous data'
); );
} }
if (numberChanged) { if (numberChanged) {
log.warn( log.warn(
'New number is different from old number; deleting all previous data' 'createAccount: New number is different from old number; deleting all previous data'
); );
} }
try { try {
await storage.protocol.removeAllData(); await storage.protocol.removeAllData();
log.info('Successfully deleted previous data'); log.info('createAccount: Successfully deleted previous data');
} catch (error) { } catch (error) {
log.error( log.error(
'Something went wrong deleting data from previous number', 'Something went wrong deleting data from previous number',
error && error.stack ? error.stack : error error && error.stack ? error.stack : error
); );
} }
} else {
log.info('createAccount: Erasing configuration (soft)');
await storage.protocol.removeAllConfiguration(
RemoveAllConfiguration.Soft
);
} }
await Promise.all([ await senderCertificateService.clear();
storage.user.removeCredentials(),
storage.remove('regionCode'),
storage.remove('userAgent'),
storage.remove('profileKey'),
storage.remove('read-receipt-setting'),
]);
if (previousUuid) { if (previousUuid) {
await Promise.all([ await Promise.all([