Search in sources :

Example 16 with StorageId

use of org.whispersystems.signalservice.api.storage.StorageId in project Signal-Android by WhisperSystems.

the class StorageSyncValidations method validateManifestAndInserts.

private static void validateManifestAndInserts(@NonNull SignalStorageManifest manifest, @NonNull List<SignalStorageRecord> inserts, @NonNull Recipient self) {
    Set<StorageId> allSet = new HashSet<>(manifest.getStorageIds());
    Set<StorageId> insertSet = new HashSet<>(Stream.of(inserts).map(SignalStorageRecord::getId).toList());
    Set<ByteBuffer> rawIdSet = Stream.of(allSet).map(id -> ByteBuffer.wrap(id.getRaw())).collect(Collectors.toSet());
    if (allSet.size() != manifest.getStorageIds().size()) {
        throw new DuplicateStorageIdError();
    }
    if (rawIdSet.size() != allSet.size()) {
        throw new DuplicateRawIdError();
    }
    if (inserts.size() > insertSet.size()) {
        throw new DuplicateInsertInWriteError();
    }
    int accountCount = 0;
    for (StorageId id : manifest.getStorageIds()) {
        accountCount += id.getType() == ManifestRecord.Identifier.Type.ACCOUNT_VALUE ? 1 : 0;
    }
    if (accountCount > 1) {
        throw new MultipleAccountError();
    }
    if (accountCount == 0) {
        throw new MissingAccountError();
    }
    for (SignalStorageRecord insert : inserts) {
        if (!allSet.contains(insert.getId())) {
            throw new InsertNotPresentInFullIdSetError();
        }
        if (insert.isUnknown()) {
            throw new UnknownInsertError();
        }
        if (insert.getContact().isPresent()) {
            SignalServiceAddress address = insert.getContact().get().getAddress();
            if (self.requireE164().equals(address.getNumber().or("")) || self.requireServiceId().equals(address.getServiceId())) {
                throw new SelfAddedAsContactError();
            }
        }
    }
}
Also used : Collectors(com.annimon.stream.Collectors) Stream(com.annimon.stream.Stream) NonNull(androidx.annotation.NonNull) Base64(org.thoughtcrime.securesms.util.Base64) ManifestRecord(org.whispersystems.signalservice.internal.storage.protos.ManifestRecord) Set(java.util.Set) SetUtil(org.thoughtcrime.securesms.util.SetUtil) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) ByteBuffer(java.nio.ByteBuffer) HashSet(java.util.HashSet) Log(org.signal.core.util.logging.Log) List(java.util.List) Recipient(org.thoughtcrime.securesms.recipients.Recipient) SignalStorageRecord(org.whispersystems.signalservice.api.storage.SignalStorageRecord) SignalStorageManifest(org.whispersystems.signalservice.api.storage.SignalStorageManifest) StorageId(org.whispersystems.signalservice.api.storage.StorageId) SignalStorageRecord(org.whispersystems.signalservice.api.storage.SignalStorageRecord) StorageId(org.whispersystems.signalservice.api.storage.StorageId) ByteBuffer(java.nio.ByteBuffer) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) HashSet(java.util.HashSet)

Example 17 with StorageId

use of org.whispersystems.signalservice.api.storage.StorageId in project Signal-Android by WhisperSystems.

the class ApplyUnknownFieldsToSelfMigrationJob method performMigration.

@Override
public void performMigration() {
    if (!SignalStore.account().isRegistered() || SignalStore.account().getAci() == null) {
        Log.w(TAG, "Not registered!");
        return;
    }
    Recipient self;
    RecipientRecord settings;
    try {
        self = Recipient.self();
        settings = SignalDatabase.recipients().getRecordForSync(self.getId());
    } catch (RecipientDatabase.MissingRecipientException e) {
        Log.w(TAG, "Unable to find self");
        return;
    }
    if (settings == null || settings.getSyncExtras().getStorageProto() == null) {
        Log.d(TAG, "No unknowns to apply");
        return;
    }
    try {
        StorageId storageId = StorageId.forAccount(self.getStorageServiceId());
        AccountRecord accountRecord = AccountRecord.parseFrom(settings.getSyncExtras().getStorageProto());
        SignalAccountRecord signalAccountRecord = new SignalAccountRecord(storageId, accountRecord);
        Log.d(TAG, "Applying potentially now known unknowns");
        StorageSyncHelper.applyAccountStorageSyncUpdates(context, self, signalAccountRecord, false);
    } catch (InvalidProtocolBufferException e) {
        Log.w(TAG, e);
    }
}
Also used : RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) SignalAccountRecord(org.whispersystems.signalservice.api.storage.SignalAccountRecord) RecipientRecord(org.thoughtcrime.securesms.database.model.RecipientRecord) SignalAccountRecord(org.whispersystems.signalservice.api.storage.SignalAccountRecord) AccountRecord(org.whispersystems.signalservice.internal.storage.protos.AccountRecord) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) Recipient(org.thoughtcrime.securesms.recipients.Recipient) StorageId(org.whispersystems.signalservice.api.storage.StorageId)

Example 18 with StorageId

use of org.whispersystems.signalservice.api.storage.StorageId in project Signal-Android by WhisperSystems.

the class SignalServiceAccountManager method writeStorageRecords.

/**
 * @return If there was a conflict, the latest {@link SignalStorageManifest}. Otherwise absent.
 */
private Optional<SignalStorageManifest> writeStorageRecords(StorageKey storageKey, SignalStorageManifest manifest, List<SignalStorageRecord> inserts, List<byte[]> deletes, boolean clearAll) throws IOException, InvalidKeyException {
    ManifestRecord.Builder manifestRecordBuilder = ManifestRecord.newBuilder().setVersion(manifest.getVersion());
    for (StorageId id : manifest.getStorageIds()) {
        ManifestRecord.Identifier idProto = ManifestRecord.Identifier.newBuilder().setRaw(ByteString.copyFrom(id.getRaw())).setType(ManifestRecord.Identifier.Type.forNumber(id.getType())).build();
        manifestRecordBuilder.addIdentifiers(idProto);
    }
    String authToken = this.pushServiceSocket.getStorageAuth();
    StorageManifestKey manifestKey = storageKey.deriveManifestKey(manifest.getVersion());
    byte[] encryptedRecord = SignalStorageCipher.encrypt(manifestKey, manifestRecordBuilder.build().toByteArray());
    StorageManifest storageManifest = StorageManifest.newBuilder().setVersion(manifest.getVersion()).setValue(ByteString.copyFrom(encryptedRecord)).build();
    WriteOperation.Builder writeBuilder = WriteOperation.newBuilder().setManifest(storageManifest);
    for (SignalStorageRecord insert : inserts) {
        writeBuilder.addInsertItem(SignalStorageModels.localToRemoteStorageRecord(insert, storageKey));
    }
    if (clearAll) {
        writeBuilder.setClearAll(true);
    } else {
        for (byte[] delete : deletes) {
            writeBuilder.addDeleteKey(ByteString.copyFrom(delete));
        }
    }
    Optional<StorageManifest> conflict = this.pushServiceSocket.writeStorageContacts(authToken, writeBuilder.build());
    if (conflict.isPresent()) {
        StorageManifestKey conflictKey = storageKey.deriveManifestKey(conflict.get().getVersion());
        byte[] rawManifestRecord = SignalStorageCipher.decrypt(conflictKey, conflict.get().getValue().toByteArray());
        ManifestRecord record = ManifestRecord.parseFrom(rawManifestRecord);
        List<StorageId> ids = new ArrayList<>(record.getIdentifiersCount());
        for (ManifestRecord.Identifier id : record.getIdentifiersList()) {
            ids.add(StorageId.forType(id.getRaw().toByteArray(), id.getType().getNumber()));
        }
        SignalStorageManifest conflictManifest = new SignalStorageManifest(record.getVersion(), ids);
        return Optional.of(conflictManifest);
    } else {
        return Optional.absent();
    }
}
Also used : SignalStorageManifest(org.whispersystems.signalservice.api.storage.SignalStorageManifest) ManifestRecord(org.whispersystems.signalservice.internal.storage.protos.ManifestRecord) StorageManifestKey(org.whispersystems.signalservice.api.storage.StorageManifestKey) ArrayList(java.util.ArrayList) SignalStorageRecord(org.whispersystems.signalservice.api.storage.SignalStorageRecord) ByteString(com.google.protobuf.ByteString) StorageId(org.whispersystems.signalservice.api.storage.StorageId) StorageManifest(org.whispersystems.signalservice.internal.storage.protos.StorageManifest) SignalStorageManifest(org.whispersystems.signalservice.api.storage.SignalStorageManifest) WriteOperation(org.whispersystems.signalservice.internal.storage.protos.WriteOperation)

Example 19 with StorageId

use of org.whispersystems.signalservice.api.storage.StorageId in project Signal-Android by signalapp.

the class UnknownStorageIdDatabase method delete.

public void delete(@NonNull Collection<StorageId> deletes) {
    SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
    String deleteQuery = STORAGE_ID + " = ?";
    Preconditions.checkArgument(db.inTransaction(), "Must be in a transaction!");
    for (StorageId id : deletes) {
        String[] args = SqlUtil.buildArgs(Base64.encodeBytes(id.getRaw()));
        db.delete(TABLE_NAME, deleteQuery, args);
    }
}
Also used : StorageId(org.whispersystems.signalservice.api.storage.StorageId)

Example 20 with StorageId

use of org.whispersystems.signalservice.api.storage.StorageId in project Signal-Android by signalapp.

the class UnknownStorageIdDatabase method getAllUnknownIds.

public List<StorageId> getAllUnknownIds() {
    List<StorageId> keys = new ArrayList<>();
    String query = TYPE + " > ?";
    String[] args = SqlUtil.buildArgs(StorageId.largestKnownType());
    try (Cursor cursor = databaseHelper.getSignalReadableDatabase().query(TABLE_NAME, null, query, args, null, null, null)) {
        while (cursor != null && cursor.moveToNext()) {
            String keyEncoded = cursor.getString(cursor.getColumnIndexOrThrow(STORAGE_ID));
            int type = cursor.getInt(cursor.getColumnIndexOrThrow(TYPE));
            try {
                keys.add(StorageId.forType(Base64.decode(keyEncoded), type));
            } catch (IOException e) {
                throw new AssertionError(e);
            }
        }
    }
    return keys;
}
Also used : ArrayList(java.util.ArrayList) IOException(java.io.IOException) Cursor(android.database.Cursor) StorageId(org.whispersystems.signalservice.api.storage.StorageId)

Aggregations

StorageId (org.whispersystems.signalservice.api.storage.StorageId)22 SignalStorageRecord (org.whispersystems.signalservice.api.storage.SignalStorageRecord)16 SignalStorageManifest (org.whispersystems.signalservice.api.storage.SignalStorageManifest)12 ArrayList (java.util.ArrayList)10 Recipient (org.thoughtcrime.securesms.recipients.Recipient)10 NonNull (androidx.annotation.NonNull)8 RecipientDatabase (org.thoughtcrime.securesms.database.RecipientDatabase)8 SignalAccountRecord (org.whispersystems.signalservice.api.storage.SignalAccountRecord)8 Stream (com.annimon.stream.Stream)6 List (java.util.List)6 Log (org.signal.core.util.logging.Log)6 UnknownStorageIdDatabase (org.thoughtcrime.securesms.database.UnknownStorageIdDatabase)6 RecipientRecord (org.thoughtcrime.securesms.database.model.RecipientRecord)6 SignalServiceAccountManager (org.whispersystems.signalservice.api.SignalServiceAccountManager)6 StorageKey (org.whispersystems.signalservice.api.storage.StorageKey)6 Collectors (com.annimon.stream.Collectors)4 ByteString (com.google.protobuf.ByteString)4 IOException (java.io.IOException)4 HashMap (java.util.HashMap)4 LinkedList (java.util.LinkedList)4