Migrate from SQLite and ciphertext blobs to SQLCipher + KeyStore

This commit is contained in:
Moxie Marlinspike
2018-01-24 19:17:44 -08:00
parent d1819b6361
commit f36b296e2e
134 changed files with 3633 additions and 3544 deletions

View File

@@ -8,10 +8,7 @@ import android.util.Log;
import org.greenrobot.eventbus.EventBus;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.crypto.AsymmetricMasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.crypto.MediaKey;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.InjectableType;
@@ -20,6 +17,7 @@ import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.util.AttachmentUtil;
import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.Hex;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
@@ -27,7 +25,6 @@ import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.libsignal.InvalidMessageException;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment.ProgressListener;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
@@ -72,7 +69,7 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
public void onRun(MasterSecret masterSecret) throws IOException {
final AttachmentDatabase database = DatabaseFactory.getAttachmentDatabase(context);
final AttachmentId attachmentId = new AttachmentId(partRowId, partUniqueId);
final Attachment attachment = database.getAttachment(masterSecret, attachmentId);
final Attachment attachment = database.getAttachment(attachmentId);
if (attachment == null) {
Log.w(TAG, "attachment no longer exists.");
@@ -92,8 +89,8 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
Log.w(TAG, "Downloading push part " + attachmentId);
database.setTransferState(messageId, attachmentId, AttachmentDatabase.TRANSFER_PROGRESS_STARTED);
retrieveAttachment(masterSecret, messageId, attachmentId, attachment);
MessageNotifier.updateNotification(context, masterSecret);
retrieveAttachment(messageId, attachmentId, attachment);
MessageNotifier.updateNotification(context);
}
@Override
@@ -107,8 +104,7 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
return (exception instanceof PushNetworkException);
}
private void retrieveAttachment(MasterSecret masterSecret,
long messageId,
private void retrieveAttachment(long messageId,
final AttachmentId attachmentId,
final Attachment attachment)
throws IOException
@@ -120,26 +116,23 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
try {
attachmentFile = createTempFile();
SignalServiceAttachmentPointer pointer = createAttachmentPointer(masterSecret, attachment);
InputStream stream = messageReceiver.retrieveAttachment(pointer, attachmentFile, MAX_ATTACHMENT_SIZE, new ProgressListener() {
@Override
public void onAttachmentProgress(long total, long progress) {
EventBus.getDefault().postSticky(new PartProgressEvent(attachment, total, progress));
}
});
SignalServiceAttachmentPointer pointer = createAttachmentPointer(attachment);
InputStream stream = messageReceiver.retrieveAttachment(pointer, attachmentFile, MAX_ATTACHMENT_SIZE, (total, progress) -> EventBus.getDefault().postSticky(new PartProgressEvent(attachment, total, progress)));
database.insertAttachmentsForPlaceholder(masterSecret, messageId, attachmentId, stream);
database.insertAttachmentsForPlaceholder(messageId, attachmentId, stream);
} catch (InvalidPartException | NonSuccessfulResponseCodeException | InvalidMessageException | MmsException e) {
Log.w(TAG, e);
markFailed(messageId, attachmentId);
} finally {
if (attachmentFile != null)
if (attachmentFile != null) {
//noinspection ResultOfMethodCallIgnored
attachmentFile.delete();
}
}
}
@VisibleForTesting
SignalServiceAttachmentPointer createAttachmentPointer(MasterSecret masterSecret, Attachment attachment)
SignalServiceAttachmentPointer createAttachmentPointer(Attachment attachment)
throws InvalidPartException
{
if (TextUtils.isEmpty(attachment.getLocation())) {
@@ -151,10 +144,9 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
}
try {
AsymmetricMasterSecret asymmetricMasterSecret = MasterSecretUtil.getAsymmetricMasterSecret(context, masterSecret);
long id = Long.parseLong(attachment.getLocation());
byte[] key = MediaKey.getDecrypted(masterSecret, asymmetricMasterSecret, attachment.getKey());
String relay = null;
long id = Long.parseLong(attachment.getLocation());
byte[] key = Base64.decode(attachment.getKey());
String relay = null;
if (TextUtils.isEmpty(attachment.getRelay())) {
relay = attachment.getRelay();
@@ -173,7 +165,7 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
Optional.fromNullable(attachment.getDigest()),
Optional.fromNullable(attachment.getFileName()),
attachment.isVoiceNote());
} catch (InvalidMessageException | IOException | ArithmeticException e) {
} catch (IOException | ArithmeticException e) {
Log.w(TAG, e);
throw new InvalidPartException(e);
}
@@ -200,8 +192,8 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
}
@VisibleForTesting static class InvalidPartException extends Exception {
public InvalidPartException(String s) {super(s);}
public InvalidPartException(Exception e) {super(e);}
InvalidPartException(String s) {super(s);}
InvalidPartException(Exception e) {super(e);}
}
}

View File

@@ -48,7 +48,7 @@ public class AttachmentFileNameJob extends MasterSecretJob {
AttachmentId attachmentId = new AttachmentId(attachmentRowId, attachmentUniqueId);
String plaintextFileName = new AsymmetricMasterCipher(MasterSecretUtil.getAsymmetricMasterSecret(context, masterSecret)).decryptBody(encryptedFileName);
DatabaseFactory.getAttachmentDatabase(context).updateAttachmentFileName(masterSecret, attachmentId, plaintextFileName);
DatabaseFactory.getAttachmentDatabase(context).updateAttachmentFileName(attachmentId, plaintextFileName);
}
@Override

View File

@@ -6,9 +6,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.DirectoryHelper;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
@@ -19,15 +17,13 @@ import java.io.IOException;
public class DirectoryRefreshJob extends ContextJob {
@Nullable private transient Recipient recipient;
@Nullable private transient MasterSecret masterSecret;
private transient boolean notifyOfNewUsers;
public DirectoryRefreshJob(@NonNull Context context, boolean notifyOfNewUsers) {
this(context, null, null, notifyOfNewUsers);
this(context, null, notifyOfNewUsers);
}
public DirectoryRefreshJob(@NonNull Context context,
@Nullable MasterSecret masterSecret,
@Nullable Recipient recipient,
boolean notifyOfNewUsers)
{
@@ -37,7 +33,6 @@ public class DirectoryRefreshJob extends ContextJob {
.create());
this.recipient = recipient;
this.masterSecret = masterSecret;
this.notifyOfNewUsers = notifyOfNewUsers;
}
@@ -53,9 +48,9 @@ public class DirectoryRefreshJob extends ContextJob {
try {
wakeLock.acquire();
if (recipient == null) {
DirectoryHelper.refreshDirectory(context, KeyCachingService.getMasterSecret(context), notifyOfNewUsers);
DirectoryHelper.refreshDirectory(context, notifyOfNewUsers);
} else {
DirectoryHelper.refreshDirectoryFor(context, masterSecret, recipient);
DirectoryHelper.refreshDirectoryFor(context, recipient);
}
} finally {
if (wakeLock.isHeld()) wakeLock.release();

View File

@@ -1,103 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import org.thoughtcrime.securesms.crypto.AsymmetricMasterCipher;
import org.thoughtcrime.securesms.crypto.AsymmetricMasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.libsignal.InvalidMessageException;
import java.io.IOException;
public class MasterSecretDecryptJob extends MasterSecretJob {
private static final long serialVersionUID = 1L;
private static final String TAG = MasterSecretDecryptJob.class.getSimpleName();
public MasterSecretDecryptJob(Context context) {
super(context, JobParameters.newBuilder()
.withRequirement(new MasterSecretRequirement(context))
.create());
}
@Override
public void onRun(MasterSecret masterSecret) {
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsDatabase.Reader smsReader = smsDatabase.getDecryptInProgressMessages(masterSecret);
SmsMessageRecord smsRecord;
while ((smsRecord = smsReader.getNext()) != null) {
try {
String body = getAsymmetricDecryptedBody(masterSecret, smsRecord.getBody().getBody());
smsDatabase.updateMessageBody(new MasterSecretUnion(masterSecret), smsRecord.getId(), body);
} catch (InvalidMessageException e) {
Log.w(TAG, e);
}
}
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
MmsDatabase.Reader mmsReader = mmsDatabase.getDecryptInProgressMessages(masterSecret);
MessageRecord mmsRecord;
while ((mmsRecord = mmsReader.getNext()) != null) {
try {
String body = getAsymmetricDecryptedBody(masterSecret, mmsRecord.getBody().getBody());
mmsDatabase.updateMessageBody(new MasterSecretUnion(masterSecret), mmsRecord.getId(), body);
} catch (InvalidMessageException e) {
Log.w(TAG, e);
}
}
smsReader.close();
mmsReader.close();
MessageNotifier.updateNotification(context, masterSecret);
}
@Override
public boolean onShouldRetryThrowable(Exception exception) {
return false;
}
@Override
public void onAdded() {
}
@Override
public void onCanceled() {
}
private String getAsymmetricDecryptedBody(MasterSecret masterSecret, String body)
throws InvalidMessageException
{
try {
AsymmetricMasterSecret asymmetricMasterSecret = MasterSecretUtil.getAsymmetricMasterSecret(context, masterSecret);
AsymmetricMasterCipher asymmetricMasterCipher = new AsymmetricMasterCipher(asymmetricMasterSecret);
if (TextUtils.isEmpty(body)) return "";
else return asymmetricMasterCipher.decryptBody(body);
} catch (IOException e) {
throw new InvalidMessageException(e);
}
}
}

View File

@@ -14,7 +14,6 @@ import com.google.android.mms.pdu_alt.RetrieveConf;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.UriAttachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
@@ -50,6 +49,8 @@ import java.util.concurrent.TimeUnit;
public class MmsDownloadJob extends MasterSecretJob {
private static final long serialVersionUID = 1L;
private static final String TAG = MmsDownloadJob.class.getSimpleName();
private final long messageId;
@@ -74,7 +75,7 @@ public class MmsDownloadJob extends MasterSecretJob {
public void onAdded() {
if (automatic && KeyCachingService.getMasterSecret(context) == null) {
DatabaseFactory.getMmsDatabase(context).markIncomingNotificationReceived(threadId);
MessageNotifier.updateNotification(context, null);
MessageNotifier.updateNotification(context);
}
}
@@ -120,19 +121,19 @@ public class MmsDownloadJob extends MasterSecretJob {
throw new MmsException("RetrieveConf was null");
}
storeRetrievedMms(masterSecret, contentLocation, messageId, threadId, retrieveConf, notification.get().getSubscriptionId(), notification.get().getFrom());
storeRetrievedMms(contentLocation, messageId, threadId, retrieveConf, notification.get().getSubscriptionId(), notification.get().getFrom());
} catch (ApnUnavailableException e) {
Log.w(TAG, e);
handleDownloadError(masterSecret, messageId, threadId, MmsDatabase.Status.DOWNLOAD_APN_UNAVAILABLE,
handleDownloadError(messageId, threadId, MmsDatabase.Status.DOWNLOAD_APN_UNAVAILABLE,
automatic);
} catch (MmsException e) {
Log.w(TAG, e);
handleDownloadError(masterSecret, messageId, threadId,
handleDownloadError(messageId, threadId,
MmsDatabase.Status.DOWNLOAD_HARD_FAILURE,
automatic);
} catch (MmsRadioException | IOException e) {
Log.w(TAG, e);
handleDownloadError(masterSecret, messageId, threadId,
handleDownloadError(messageId, threadId,
MmsDatabase.Status.DOWNLOAD_SOFT_FAILURE,
automatic);
} catch (DuplicateMessageException e) {
@@ -157,7 +158,7 @@ public class MmsDownloadJob extends MasterSecretJob {
if (automatic) {
database.markIncomingNotificationReceived(threadId);
MessageNotifier.updateNotification(context, null, threadId);
MessageNotifier.updateNotification(context, threadId);
}
}
@@ -166,7 +167,7 @@ public class MmsDownloadJob extends MasterSecretJob {
return false;
}
private void storeRetrievedMms(MasterSecret masterSecret, String contentLocation,
private void storeRetrievedMms(String contentLocation,
long messageId, long threadId, RetrieveConf retrieved,
int subscriptionId, @Nullable Address notificationFrom)
throws MmsException, NoSessionException, DuplicateMessageException, InvalidMessageException,
@@ -229,17 +230,15 @@ public class MmsDownloadJob extends MasterSecretJob {
}
IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false);
Optional<InsertResult> insertResult = database.insertMessageInbox(new MasterSecretUnion(masterSecret),
message, contentLocation, threadId);
Optional<InsertResult> insertResult = database.insertMessageInbox(message, contentLocation, threadId);
if (insertResult.isPresent()) {
database.delete(messageId);
MessageNotifier.updateNotification(context, masterSecret, insertResult.get().getThreadId());
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
}
}
private void handleDownloadError(MasterSecret masterSecret, long messageId, long threadId,
int downloadStatus, boolean automatic)
private void handleDownloadError(long messageId, long threadId, int downloadStatus, boolean automatic)
{
MmsDatabase db = DatabaseFactory.getMmsDatabase(context);
@@ -247,7 +246,7 @@ public class MmsDownloadJob extends MasterSecretJob {
if (automatic) {
db.markIncomingNotificationReceived(threadId);
MessageNotifier.updateNotification(context, masterSecret, threadId);
MessageNotifier.updateNotification(context, threadId);
}
}
}

View File

@@ -76,10 +76,10 @@ public class MmsSendJob extends SendJob {
@Override
public void onSend(MasterSecret masterSecret) throws MmsException, NoSuchMessageException, IOException {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
OutgoingMediaMessage message = database.getOutgoingMessage(masterSecret, messageId);
OutgoingMediaMessage message = database.getOutgoingMessage(messageId);
try {
SendReq pdu = constructSendPdu(masterSecret, message);
SendReq pdu = constructSendPdu(message);
validateDestinations(message, pdu);
@@ -168,14 +168,14 @@ public class MmsSendJob extends SendJob {
}
}
private SendReq constructSendPdu(MasterSecret masterSecret, OutgoingMediaMessage message)
private SendReq constructSendPdu(OutgoingMediaMessage message)
throws UndeliverableMessageException
{
SendReq req = new SendReq();
String lineNumber = getMyNumber(context);
Address destination = message.getRecipient().getAddress();
MediaConstraints mediaConstraints = MediaConstraints.getMmsMediaConstraints(message.getSubscriptionId());
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
List<Attachment> scaledAttachments = scaleAttachments(mediaConstraints, message.getAttachments());
if (!TextUtils.isEmpty(lineNumber)) {
req.setFrom(new EncodedStringValue(lineNumber));
@@ -241,7 +241,7 @@ public class MmsSendJob extends SendJob {
int index = fileName.lastIndexOf(".");
String contentId = (index == -1) ? fileName : fileName.substring(0, index);
part.setContentId(contentId.getBytes());
part.setData(Util.readFully(PartAuthority.getAttachmentStream(context, masterSecret, attachment.getDataUri())));
part.setData(Util.readFully(PartAuthority.getAttachmentStream(context, attachment.getDataUri())));
body.addPart(part);
size += getPartSize(part);

View File

@@ -11,15 +11,11 @@ import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.attachments.PointerAttachment;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.crypto.SecurityEvent;
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.MessagingDatabase;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
@@ -39,7 +35,6 @@ import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.service.WebRtcCallService;
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage;
@@ -67,7 +62,6 @@ import org.whispersystems.libsignal.state.SessionStore;
import org.whispersystems.libsignal.state.SignalProtocolStore;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
@@ -124,18 +118,11 @@ public class PushDecryptJob extends ContextJob {
return;
}
MasterSecret masterSecret = KeyCachingService.getMasterSecret(context);
PushDatabase database = DatabaseFactory.getPushDatabase(context);
SignalServiceEnvelope envelope = database.get(messageId);
Optional<Long> optionalSmsMessageId = smsMessageId > 0 ? Optional.of(smsMessageId) :
Optional.<Long>absent();
Optional<Long> optionalSmsMessageId = smsMessageId > 0 ? Optional.of(smsMessageId) : Optional.absent();
MasterSecretUnion masterSecretUnion;
if (masterSecret == null) masterSecretUnion = new MasterSecretUnion(MasterSecretUtil.getAsymmetricMasterSecret(context, null));
else masterSecretUnion = new MasterSecretUnion(masterSecret);
handleMessage(masterSecretUnion, envelope, optionalSmsMessageId);
handleMessage(envelope, optionalSmsMessageId);
database.delete(messageId);
}
@@ -149,7 +136,7 @@ public class PushDecryptJob extends ContextJob {
}
private void handleMessage(MasterSecretUnion masterSecret, SignalServiceEnvelope envelope, Optional<Long> smsMessageId) {
private void handleMessage(SignalServiceEnvelope envelope, Optional<Long> smsMessageId) {
try {
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
SignalProtocolStore axolotlStore = new SignalProtocolStoreImpl(context);
@@ -161,11 +148,11 @@ public class PushDecryptJob extends ContextJob {
if (content.getDataMessage().isPresent()) {
SignalServiceDataMessage message = content.getDataMessage().get();
if (message.isEndSession()) handleEndSessionMessage(masterSecret, envelope, message, smsMessageId);
else if (message.isGroupUpdate()) handleGroupMessage(masterSecret, envelope, message, smsMessageId);
else if (message.isExpirationUpdate()) handleExpirationUpdate(masterSecret, envelope, message, smsMessageId);
else if (message.getAttachments().isPresent()) handleMediaMessage(masterSecret, envelope, message, smsMessageId);
else if (message.getBody().isPresent()) handleTextMessage(masterSecret, envelope, message, smsMessageId);
if (message.isEndSession()) handleEndSessionMessage(envelope, message, smsMessageId);
else if (message.isGroupUpdate()) handleGroupMessage(envelope, message, smsMessageId);
else if (message.isExpirationUpdate()) handleExpirationUpdate(envelope, message, smsMessageId);
else if (message.getAttachments().isPresent()) handleMediaMessage(envelope, message, smsMessageId);
else if (message.getBody().isPresent()) handleTextMessage(envelope, message, smsMessageId);
if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false))) {
handleUnknownGroupMessage(envelope, message.getGroupInfo().get());
@@ -177,10 +164,10 @@ public class PushDecryptJob extends ContextJob {
} else if (content.getSyncMessage().isPresent()) {
SignalServiceSyncMessage syncMessage = content.getSyncMessage().get();
if (syncMessage.getSent().isPresent()) handleSynchronizeSentMessage(masterSecret, envelope, syncMessage.getSent().get());
else if (syncMessage.getRequest().isPresent()) handleSynchronizeRequestMessage(masterSecret, syncMessage.getRequest().get());
else if (syncMessage.getRead().isPresent()) handleSynchronizeReadMessage(masterSecret, syncMessage.getRead().get(), envelope.getTimestamp());
else if (syncMessage.getVerified().isPresent()) handleSynchronizeVerifiedMessage(masterSecret, syncMessage.getVerified().get());
if (syncMessage.getSent().isPresent()) handleSynchronizeSentMessage(envelope, syncMessage.getSent().get());
else if (syncMessage.getRequest().isPresent()) handleSynchronizeRequestMessage(syncMessage.getRequest().get());
else if (syncMessage.getRead().isPresent()) handleSynchronizeReadMessage(syncMessage.getRead().get(), envelope.getTimestamp());
else if (syncMessage.getVerified().isPresent()) handleSynchronizeVerifiedMessage(syncMessage.getVerified().get());
else Log.w(TAG, "Contains no known sync types...");
} else if (content.getCallMessage().isPresent()) {
Log.w(TAG, "Got call message...");
@@ -205,22 +192,22 @@ public class PushDecryptJob extends ContextJob {
}
} catch (InvalidVersionException e) {
Log.w(TAG, e);
handleInvalidVersionMessage(masterSecret, envelope, smsMessageId);
handleInvalidVersionMessage(envelope, smsMessageId);
} catch (InvalidMessageException | InvalidKeyIdException | InvalidKeyException | MmsException e) {
Log.w(TAG, e);
handleCorruptMessage(masterSecret, envelope, smsMessageId);
handleCorruptMessage(envelope, smsMessageId);
} catch (NoSessionException e) {
Log.w(TAG, e);
handleNoSessionMessage(masterSecret, envelope, smsMessageId);
handleNoSessionMessage(envelope, smsMessageId);
} catch (LegacyMessageException e) {
Log.w(TAG, e);
handleLegacyMessage(masterSecret, envelope, smsMessageId);
handleLegacyMessage(envelope, smsMessageId);
} catch (DuplicateMessageException e) {
Log.w(TAG, e);
handleDuplicateMessage(masterSecret, envelope, smsMessageId);
handleDuplicateMessage(envelope, smsMessageId);
} catch (UntrustedIdentityException e) {
Log.w(TAG, e);
handleUntrustedIdentityMessage(masterSecret, envelope, smsMessageId);
handleUntrustedIdentityMessage(envelope, smsMessageId);
}
}
@@ -304,22 +291,21 @@ public class PushDecryptJob extends ContextJob {
context.startService(intent);
}
private void handleEndSessionMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
private void handleEndSessionMessage(@NonNull SignalServiceEnvelope envelope,
@NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId)
{
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(Address.fromExternal(context, envelope.getSource()),
envelope.getSourceDevice(),
message.getTimestamp(),
"", Optional.<SignalServiceGroup>absent(), 0);
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(Address.fromExternal(context, envelope.getSource()),
envelope.getSourceDevice(),
message.getTimestamp(),
"", Optional.absent(), 0);
Long threadId;
if (!smsMessageId.isPresent()) {
IncomingEndSessionMessage incomingEndSessionMessage = new IncomingEndSessionMessage(incomingTextMessage);
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(masterSecret, incomingEndSessionMessage);
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(incomingEndSessionMessage);
if (insertResult.isPresent()) threadId = insertResult.get().getThreadId();
else threadId = null;
@@ -333,14 +319,13 @@ public class PushDecryptJob extends ContextJob {
sessionStore.deleteAllSessions(envelope.getSource());
SecurityEvent.broadcastSecurityUpdateEvent(context);
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), threadId);
MessageNotifier.updateNotification(context, threadId);
}
}
private long handleSynchronizeSentEndSessionMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SentTranscriptMessage message)
private long handleSynchronizeSentEndSessionMessage(@NonNull SentTranscriptMessage message)
{
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
Recipient recipient = getSyncMessageDestination(message);
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipient, "", -1);
OutgoingEndSessionMessage outgoingEndSessionMessage = new OutgoingEndSessionMessage(outgoingTextMessage);
@@ -353,20 +338,20 @@ public class PushDecryptJob extends ContextJob {
SecurityEvent.broadcastSecurityUpdateEvent(context);
long messageId = database.insertMessageOutbox(masterSecret, threadId, outgoingEndSessionMessage,
false, message.getTimestamp(), null);
long messageId = database.insertMessageOutbox(threadId, outgoingEndSessionMessage,
false, message.getTimestamp(),
null);
database.markAsSent(messageId, true);
}
return threadId;
}
private void handleGroupMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
private void handleGroupMessage(@NonNull SignalServiceEnvelope envelope,
@NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId)
{
GroupMessageProcessor.process(context, masterSecret, envelope, message, false);
GroupMessageProcessor.process(context, envelope, message, false);
if (smsMessageId.isPresent()) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
@@ -381,25 +366,23 @@ public class PushDecryptJob extends ContextJob {
.add(new RequestGroupInfoJob(context, envelope.getSource(), group.getGroupId()));
}
private void handleExpirationUpdate(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
private void handleExpirationUpdate(@NonNull SignalServiceEnvelope envelope,
@NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId)
throws MmsException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
Recipient recipient = getMessageDestination(envelope, message);
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret,
Address.fromExternal(context, envelope.getSource()),
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(Address.fromExternal(context, envelope.getSource()),
message.getTimestamp(), -1,
message.getExpiresInSeconds() * 1000, true,
Optional.fromNullable(envelope.getRelay()),
Optional.<String>absent(), message.getGroupInfo(),
Optional.<List<SignalServiceAttachment>>absent());
Optional.absent(), message.getGroupInfo(),
Optional.absent());
database.insertSecureDecryptedMessageInbox(masterSecret, mediaMessage, -1);
database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipient, message.getExpiresInSeconds());
@@ -408,14 +391,11 @@ public class PushDecryptJob extends ContextJob {
}
}
private void handleSynchronizeVerifiedMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull VerifiedMessage verifiedMessage)
{
IdentityUtil.processVerifiedMessage(context, masterSecret, verifiedMessage);
private void handleSynchronizeVerifiedMessage(@NonNull VerifiedMessage verifiedMessage) {
IdentityUtil.processVerifiedMessage(context, verifiedMessage);
}
private void handleSynchronizeSentMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
private void handleSynchronizeSentMessage(@NonNull SignalServiceEnvelope envelope,
@NonNull SentTranscriptMessage message)
throws MmsException
{
@@ -424,15 +404,15 @@ public class PushDecryptJob extends ContextJob {
Long threadId;
if (message.getMessage().isEndSession()) {
threadId = handleSynchronizeSentEndSessionMessage(masterSecret, message);
threadId = handleSynchronizeSentEndSessionMessage(message);
} else if (message.getMessage().isGroupUpdate()) {
threadId = GroupMessageProcessor.process(context, masterSecret, envelope, message.getMessage(), true);
threadId = GroupMessageProcessor.process(context, envelope, message.getMessage(), true);
} else if (message.getMessage().isExpirationUpdate()) {
threadId = handleSynchronizeSentExpirationUpdate(masterSecret, message);
threadId = handleSynchronizeSentExpirationUpdate(message);
} else if (message.getMessage().getAttachments().isPresent()) {
threadId = handleSynchronizeSentMediaMessage(masterSecret, message);
threadId = handleSynchronizeSentMediaMessage(message);
} else {
threadId = handleSynchronizeSentTextMessage(masterSecret, message);
threadId = handleSynchronizeSentTextMessage(message);
}
if (message.getMessage().getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get().getGroupId(), false))) {
@@ -453,14 +433,13 @@ public class PushDecryptJob extends ContextJob {
if (threadId != null) {
DatabaseFactory.getThreadDatabase(getContext()).setRead(threadId, true);
MessageNotifier.updateNotification(getContext(), masterSecret.getMasterSecret().orNull());
MessageNotifier.updateNotification(getContext());
}
MessageNotifier.setLastDesktopActivityTimestamp(message.getTimestamp());
}
private void handleSynchronizeRequestMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull RequestMessage message)
private void handleSynchronizeRequestMessage(@NonNull RequestMessage message)
{
if (message.isContactsRequest()) {
ApplicationContext.getInstance(context)
@@ -487,9 +466,7 @@ public class PushDecryptJob extends ContextJob {
}
}
private void handleSynchronizeReadMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull List<ReadMessage> readMessages,
long envelopeTimestamp)
private void handleSynchronizeReadMessage(@NonNull List<ReadMessage> readMessages, long envelopeTimestamp)
{
for (ReadMessage readMessage : readMessages) {
List<Pair<Long, Long>> expiringText = DatabaseFactory.getSmsDatabase(context).setTimestampRead(new SyncMessageId(Address.fromExternal(context, readMessage.getSender()), readMessage.getTimestamp()), envelopeTimestamp);
@@ -510,19 +487,17 @@ public class PushDecryptJob extends ContextJob {
MessageNotifier.setLastDesktopActivityTimestamp(envelopeTimestamp);
MessageNotifier.cancelDelayedNotifications();
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull());
MessageNotifier.updateNotification(context);
}
private void handleMediaMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
private void handleMediaMessage(@NonNull SignalServiceEnvelope envelope,
@NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId)
throws MmsException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
Recipient recipient = getMessageDestination(envelope, message);
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret,
Address.fromExternal(context, envelope.getSource()),
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(Address.fromExternal(context, envelope.getSource()),
message.getTimestamp(), -1,
message.getExpiresInSeconds() * 1000, false,
Optional.fromNullable(envelope.getRelay()),
@@ -531,36 +506,29 @@ public class PushDecryptJob extends ContextJob {
message.getAttachments());
if (message.getExpiresInSeconds() != recipient.getExpireMessages()) {
handleExpirationUpdate(masterSecret, envelope, message, Optional.<Long>absent());
handleExpirationUpdate(envelope, message, Optional.absent());
}
Optional<InsertResult> insertResult = database.insertSecureDecryptedMessageInbox(masterSecret, mediaMessage, -1);
Optional<InsertResult> insertResult = database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
if (insertResult.isPresent()) {
List<DatabaseAttachment> attachments = DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessage(null, insertResult.get().getMessageId());
List<DatabaseAttachment> attachments = DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessage(insertResult.get().getMessageId());
for (DatabaseAttachment attachment : attachments) {
ApplicationContext.getInstance(context)
.getJobManager()
.add(new AttachmentDownloadJob(context, insertResult.get().getMessageId(), attachment.getAttachmentId(), false));
if (!masterSecret.getMasterSecret().isPresent()) {
ApplicationContext.getInstance(context)
.getJobManager()
.add(new AttachmentFileNameJob(context, masterSecret.getAsymmetricMasterSecret().get(), attachment, mediaMessage));
}
}
if (smsMessageId.isPresent()) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
}
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
}
}
private long handleSynchronizeSentExpirationUpdate(@NonNull MasterSecretUnion masterSecret,
@NonNull SentTranscriptMessage message)
private long handleSynchronizeSentExpirationUpdate(@NonNull SentTranscriptMessage message)
throws MmsException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
@@ -571,7 +539,7 @@ public class PushDecryptJob extends ContextJob {
message.getMessage().getExpiresInSeconds() * 1000);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
long messageId = database.insertMessageOutbox(masterSecret, expirationUpdateMessage, threadId, false, null);
long messageId = database.insertMessageOutbox(expirationUpdateMessage, threadId, false, null);
database.markAsSent(messageId, true);
@@ -580,14 +548,13 @@ public class PushDecryptJob extends ContextJob {
return threadId;
}
private long handleSynchronizeSentMediaMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SentTranscriptMessage message)
private long handleSynchronizeSentMediaMessage(@NonNull SentTranscriptMessage message)
throws MmsException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
Recipient recipients = getSyncMessageDestination(message);
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipients, message.getMessage().getBody().orNull(),
PointerAttachment.forPointers(masterSecret, message.getMessage().getAttachments()),
PointerAttachment.forPointers(message.getMessage().getAttachments()),
message.getTimestamp(), -1,
message.getMessage().getExpiresInSeconds() * 1000,
ThreadDatabase.DistributionTypes.DEFAULT);
@@ -595,15 +562,15 @@ public class PushDecryptJob extends ContextJob {
mediaMessage = new OutgoingSecureMediaMessage(mediaMessage);
if (recipients.getExpireMessages() != message.getMessage().getExpiresInSeconds()) {
handleSynchronizeSentExpirationUpdate(masterSecret, message);
handleSynchronizeSentExpirationUpdate(message);
}
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
long messageId = database.insertMessageOutbox(masterSecret, mediaMessage, threadId, false, null);
long messageId = database.insertMessageOutbox(mediaMessage, threadId, false, null);
database.markAsSent(messageId, true);
for (DatabaseAttachment attachment : DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessage(null, messageId)) {
for (DatabaseAttachment attachment : DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessage(messageId)) {
ApplicationContext.getInstance(context)
.getJobManager()
.add(new AttachmentDownloadJob(context, messageId, attachment.getAttachmentId(), false));
@@ -621,24 +588,23 @@ public class PushDecryptJob extends ContextJob {
return threadId;
}
private void handleTextMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
private void handleTextMessage(@NonNull SignalServiceEnvelope envelope,
@NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId)
throws MmsException
{
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
String body = message.getBody().isPresent() ? message.getBody().get() : "";
Recipient recipient = getMessageDestination(envelope, message);
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
String body = message.getBody().isPresent() ? message.getBody().get() : "";
Recipient recipient = getMessageDestination(envelope, message);
if (message.getExpiresInSeconds() != recipient.getExpireMessages()) {
handleExpirationUpdate(masterSecret, envelope, message, Optional.<Long>absent());
handleExpirationUpdate(envelope, message, Optional.absent());
}
Long threadId;
if (smsMessageId.isPresent() && !message.getGroupInfo().isPresent()) {
threadId = database.updateBundleMessageBody(masterSecret, smsMessageId.get(), body).second;
threadId = database.updateBundleMessageBody(smsMessageId.get(), body).second;
} else {
IncomingTextMessage textMessage = new IncomingTextMessage(Address.fromExternal(context, envelope.getSource()),
envelope.getSourceDevice(),
@@ -647,7 +613,7 @@ public class PushDecryptJob extends ContextJob {
message.getExpiresInSeconds() * 1000);
textMessage = new IncomingEncryptedMessage(textMessage, body);
Optional<InsertResult> insertResult = database.insertMessageInbox(masterSecret, textMessage);
Optional<InsertResult> insertResult = database.insertMessageInbox(textMessage);
if (insertResult.isPresent()) threadId = insertResult.get().getThreadId();
else threadId = null;
@@ -656,12 +622,11 @@ public class PushDecryptJob extends ContextJob {
}
if (threadId != null) {
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), threadId);
MessageNotifier.updateNotification(context, threadId);
}
}
private long handleSynchronizeSentTextMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SentTranscriptMessage message)
private long handleSynchronizeSentTextMessage(@NonNull SentTranscriptMessage message)
throws MmsException
{
@@ -670,7 +635,7 @@ public class PushDecryptJob extends ContextJob {
long expiresInMillis = message.getMessage().getExpiresInSeconds() * 1000;
if (recipient.getExpireMessages() != message.getMessage().getExpiresInSeconds()) {
handleSynchronizeSentExpirationUpdate(masterSecret, message);
handleSynchronizeSentExpirationUpdate(message);
}
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
@@ -682,12 +647,12 @@ public class PushDecryptJob extends ContextJob {
OutgoingMediaMessage outgoingMediaMessage = new OutgoingMediaMessage(recipient, new SlideDeck(), body, message.getTimestamp(), -1, expiresInMillis, ThreadDatabase.DistributionTypes.DEFAULT);
outgoingMediaMessage = new OutgoingSecureMediaMessage(outgoingMediaMessage);
messageId = DatabaseFactory.getMmsDatabase(context).insertMessageOutbox(masterSecret, outgoingMediaMessage, threadId, false, null);
messageId = DatabaseFactory.getMmsDatabase(context).insertMessageOutbox(outgoingMediaMessage, threadId, false, null);
database = DatabaseFactory.getMmsDatabase(context);
} else {
OutgoingTextMessage outgoingTextMessage = new OutgoingEncryptedMessage(recipient, body, expiresInMillis);
messageId = DatabaseFactory.getEncryptingSmsDatabase(context).insertMessageOutbox(masterSecret, threadId, outgoingTextMessage, false, message.getTimestamp(), null);
messageId = DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(threadId, outgoingTextMessage, false, message.getTimestamp(), null);
database = DatabaseFactory.getSmsDatabase(context);
}
@@ -703,80 +668,76 @@ public class PushDecryptJob extends ContextJob {
return threadId;
}
private void handleInvalidVersionMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
private void handleInvalidVersionMessage(@NonNull SignalServiceEnvelope envelope,
@NonNull Optional<Long> smsMessageId)
{
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
if (!smsMessageId.isPresent()) {
Optional<InsertResult> insertResult = insertPlaceholder(envelope);
if (insertResult.isPresent()) {
smsDatabase.markAsInvalidVersionKeyExchange(insertResult.get().getMessageId());
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
}
} else {
smsDatabase.markAsInvalidVersionKeyExchange(smsMessageId.get());
}
}
private void handleCorruptMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
private void handleCorruptMessage(@NonNull SignalServiceEnvelope envelope,
@NonNull Optional<Long> smsMessageId)
{
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
if (!smsMessageId.isPresent()) {
Optional<InsertResult> insertResult = insertPlaceholder(envelope);
if (insertResult.isPresent()) {
smsDatabase.markAsDecryptFailed(insertResult.get().getMessageId());
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
}
} else {
smsDatabase.markAsDecryptFailed(smsMessageId.get());
}
}
private void handleNoSessionMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
private void handleNoSessionMessage(@NonNull SignalServiceEnvelope envelope,
@NonNull Optional<Long> smsMessageId)
{
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
if (!smsMessageId.isPresent()) {
Optional<InsertResult> insertResult = insertPlaceholder(envelope);
if (insertResult.isPresent()) {
smsDatabase.markAsNoSession(insertResult.get().getMessageId());
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
}
} else {
smsDatabase.markAsNoSession(smsMessageId.get());
}
}
private void handleLegacyMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
private void handleLegacyMessage(@NonNull SignalServiceEnvelope envelope,
@NonNull Optional<Long> smsMessageId)
{
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
if (!smsMessageId.isPresent()) {
Optional<InsertResult> insertResult = insertPlaceholder(envelope);
if (insertResult.isPresent()) {
smsDatabase.markAsLegacyVersion(insertResult.get().getMessageId());
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
}
} else {
smsDatabase.markAsLegacyVersion(smsMessageId.get());
}
}
private void handleDuplicateMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
@SuppressWarnings("unused")
private void handleDuplicateMessage(@NonNull SignalServiceEnvelope envelope,
@NonNull Optional<Long> smsMessageId)
{
// Let's start ignoring these now
@@ -791,33 +752,32 @@ public class PushDecryptJob extends ContextJob {
// }
}
private void handleUntrustedIdentityMessage(@NonNull MasterSecretUnion masterSecret,
@NonNull SignalServiceEnvelope envelope,
private void handleUntrustedIdentityMessage(@NonNull SignalServiceEnvelope envelope,
@NonNull Optional<Long> smsMessageId)
{
try {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
Address sourceAddress = Address.fromExternal(context, envelope.getSource());
byte[] serialized = envelope.hasLegacyMessage() ? envelope.getLegacyMessage() : envelope.getContent();
PreKeySignalMessage whisperMessage = new PreKeySignalMessage(serialized);
IdentityKey identityKey = whisperMessage.getIdentityKey();
String encoded = Base64.encodeBytes(serialized);
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
Address sourceAddress = Address.fromExternal(context, envelope.getSource());
byte[] serialized = envelope.hasLegacyMessage() ? envelope.getLegacyMessage() : envelope.getContent();
PreKeySignalMessage whisperMessage = new PreKeySignalMessage(serialized);
IdentityKey identityKey = whisperMessage.getIdentityKey();
String encoded = Base64.encodeBytes(serialized);
IncomingTextMessage textMessage = new IncomingTextMessage(sourceAddress,
envelope.getSourceDevice(),
envelope.getTimestamp(), encoded,
Optional.<SignalServiceGroup>absent(), 0);
Optional.absent(), 0);
if (!smsMessageId.isPresent()) {
IncomingPreKeyBundleMessage bundleMessage = new IncomingPreKeyBundleMessage(textMessage, encoded, envelope.hasLegacyMessage());
Optional<InsertResult> insertResult = database.insertMessageInbox(masterSecret, bundleMessage);
Optional<InsertResult> insertResult = database.insertMessageInbox(bundleMessage);
if (insertResult.isPresent()) {
database.setMismatchedIdentity(insertResult.get().getMessageId(), sourceAddress, identityKey);
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
}
} else {
database.updateMessageBody(masterSecret, smsMessageId.get(), encoded);
database.updateMessageBody(smsMessageId.get(), encoded);
database.markAsPreKeyBundle(smsMessageId.get());
database.setMismatchedIdentity(smsMessageId.get(), sourceAddress, identityKey);
}
@@ -863,11 +823,11 @@ public class PushDecryptJob extends ContextJob {
}
private Optional<InsertResult> insertPlaceholder(@NonNull SignalServiceEnvelope envelope) {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
IncomingTextMessage textMessage = new IncomingTextMessage(Address.fromExternal(context, envelope.getSource()),
envelope.getSourceDevice(),
envelope.getTimestamp(), "",
Optional.<SignalServiceGroup>absent(), 0);
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
IncomingTextMessage textMessage = new IncomingTextMessage(Address.fromExternal(context, envelope.getSource()),
envelope.getSourceDevice(),
envelope.getTimestamp(), "",
Optional.absent(), 0);
textMessage = new IncomingEncryptedMessage(textMessage, "");
return database.insertMessageInbox(textMessage);

View File

@@ -12,7 +12,6 @@ import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupReceiptDatabase;
import org.thoughtcrime.securesms.database.GroupReceiptDatabase.GroupReceiptInfo;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
@@ -82,10 +81,10 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
throws MmsException, IOException, NoSuchMessageException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
OutgoingMediaMessage message = database.getOutgoingMessage(masterSecret, messageId);
OutgoingMediaMessage message = database.getOutgoingMessage(messageId);
try {
deliver(masterSecret, message, filterAddress == null ? null : Address.fromSerialized(filterAddress));
deliver(message, filterAddress == null ? null : Address.fromSerialized(filterAddress));
database.markAsSent(messageId, true);
markAttachmentsUploaded(messageId, message.getAttachments());
@@ -135,7 +134,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
DatabaseFactory.getMmsDatabase(context).markAsSentFailed(messageId);
}
private void deliver(MasterSecret masterSecret, OutgoingMediaMessage message, @Nullable Address filterAddress)
private void deliver(OutgoingMediaMessage message, @Nullable Address filterAddress)
throws IOException, RecipientFormattingException, InvalidNumberException,
EncapsulatedExceptions, UndeliverableMessageException
{
@@ -143,8 +142,8 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
Optional<byte[]> profileKey = getProfileKey(message.getRecipient());
List<Address> recipients = getGroupMessageRecipients(groupId, messageId);
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
List<SignalServiceAttachment> attachmentStreams = getAttachmentsFor(masterSecret, scaledAttachments);
List<Attachment> scaledAttachments = scaleAttachments(mediaConstraints, message.getAttachments());
List<SignalServiceAttachment> attachmentStreams = getAttachmentsFor(scaledAttachments);
List<SignalServiceAddress> addresses;

View File

@@ -59,10 +59,10 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
{
ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
OutgoingMediaMessage message = database.getOutgoingMessage(masterSecret, messageId);
OutgoingMediaMessage message = database.getOutgoingMessage(messageId);
try {
deliver(masterSecret, message);
deliver(message);
database.markAsSent(messageId, true);
markAttachmentsUploaded(messageId, message.getAttachments());
@@ -97,7 +97,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
notifyMediaMessageDeliveryFailed(context, messageId);
}
private void deliver(MasterSecret masterSecret, OutgoingMediaMessage message)
private void deliver(OutgoingMediaMessage message)
throws RetryLaterException, InsecureFallbackApprovalException, UntrustedIdentityException,
UndeliverableMessageException
{
@@ -108,8 +108,8 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
try {
SignalServiceAddress address = getPushAddress(message.getRecipient().getAddress());
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
List<SignalServiceAttachment> attachmentStreams = getAttachmentsFor(masterSecret, scaledAttachments);
List<Attachment> scaledAttachments = scaleAttachments(mediaConstraints, message.getAttachments());
List<SignalServiceAttachment> attachmentStreams = getAttachmentsFor(scaledAttachments);
Optional<byte[]> profileKey = getProfileKey(message.getRecipient());
SignalServiceDataMessage mediaMessage = SignalServiceDataMessage.newBuilder()
.withBody(message.getBody())

View File

@@ -10,7 +10,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.whispersystems.jobqueue.JobManager;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
@@ -29,7 +28,7 @@ public abstract class PushReceivedJob extends ContextJob {
if (!isActiveNumber(recipient)) {
DatabaseFactory.getRecipientDatabase(context).setRegistered(recipient, RecipientDatabase.RegisteredState.REGISTERED);
ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context, KeyCachingService.getMasterSecret(context), recipient, false));
ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context, recipient, false));
}
if (envelope.isReceipt()) {

View File

@@ -80,13 +80,13 @@ public abstract class PushSendJob extends SendJob {
return new SignalServiceAddress(address.toPhoneString(), Optional.fromNullable(relay));
}
protected List<SignalServiceAttachment> getAttachmentsFor(MasterSecret masterSecret, List<Attachment> parts) {
protected List<SignalServiceAttachment> getAttachmentsFor(List<Attachment> parts) {
List<SignalServiceAttachment> attachments = new LinkedList<>();
for (final Attachment attachment : parts) {
try {
if (attachment.getDataUri() == null || attachment.getSize() == 0) throw new IOException("Assertion failed, outgoing attachment has no data!");
InputStream is = PartAuthority.getAttachmentStream(context, masterSecret, attachment.getDataUri());
InputStream is = PartAuthority.getAttachmentStream(context, attachment.getDataUri());
attachments.add(SignalServiceAttachment.newStreamBuilder()
.withStream(is)
.withContentType(attachment.getContentType())

View File

@@ -7,8 +7,8 @@ import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
@@ -48,8 +48,8 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
@Override
public void onPushSend(MasterSecret masterSecret) throws NoSuchMessageException, RetryLaterException {
ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsMessageRecord record = database.getMessage(masterSecret, messageId);
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
SmsMessageRecord record = database.getMessage(messageId);
try {
Log.w(TAG, "Sending message: " + messageId);

View File

@@ -22,6 +22,7 @@ import java.util.List;
public abstract class SendJob extends MasterSecretJob {
@SuppressWarnings("unused")
private final static String TAG = SendJob.class.getSimpleName();
public SendJob(Context context, JobParameters parameters) {
@@ -49,8 +50,7 @@ public abstract class SendJob extends MasterSecretJob {
}
}
protected List<Attachment> scaleAttachments(@NonNull MasterSecret masterSecret,
@NonNull MediaConstraints constraints,
protected List<Attachment> scaleAttachments(@NonNull MediaConstraints constraints,
@NonNull List<Attachment> attachments)
throws UndeliverableMessageException
{
@@ -59,11 +59,11 @@ public abstract class SendJob extends MasterSecretJob {
for (Attachment attachment : attachments) {
try {
if (constraints.isSatisfied(context, masterSecret, attachment)) {
if (constraints.isSatisfied(context, attachment)) {
results.add(attachment);
} else if (constraints.canResize(attachment)) {
MediaStream resized = constraints.getResizedMedia(context, masterSecret, attachment);
results.add(attachmentDatabase.updateAttachmentData(masterSecret, attachment, resized));
MediaStream resized = constraints.getResizedMedia(context, attachment);
results.add(attachmentDatabase.updateAttachmentData(attachment, resized));
} else {
throw new UndeliverableMessageException("Size constraints could not be met!");
}

View File

@@ -6,15 +6,11 @@ import android.support.annotation.Nullable;
import android.telephony.SmsMessage;
import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.libsignal.util.guava.Optional;
@@ -48,22 +44,13 @@ public class SmsReceiveJob extends ContextJob {
public void onRun() {
Log.w(TAG, "onRun()");
Optional<IncomingTextMessage> message = assembleMessageFragments(pdus, subscriptionId);
MasterSecret masterSecret = KeyCachingService.getMasterSecret(context);
MasterSecretUnion masterSecretUnion;
if (masterSecret == null) {
masterSecretUnion = new MasterSecretUnion(MasterSecretUtil.getAsymmetricMasterSecret(context, null));
} else {
masterSecretUnion = new MasterSecretUnion(masterSecret);
}
Optional<IncomingTextMessage> message = assembleMessageFragments(pdus, subscriptionId);
if (message.isPresent() && !isBlocked(message.get())) {
Optional<InsertResult> insertResult = storeMessage(masterSecretUnion, message.get());
Optional<InsertResult> insertResult = storeMessage(message.get());
if (insertResult.isPresent()) {
MessageNotifier.updateNotification(context, masterSecret, insertResult.get().getThreadId());
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
}
} else if (message.isPresent()) {
Log.w(TAG, "*** Received blocked SMS, ignoring...");
@@ -91,8 +78,8 @@ public class SmsReceiveJob extends ContextJob {
return false;
}
private Optional<InsertResult> storeMessage(MasterSecretUnion masterSecret, IncomingTextMessage message) {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
private Optional<InsertResult> storeMessage(IncomingTextMessage message) {
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
if (message.isSecureMessage()) {
IncomingTextMessage placeholder = new IncomingTextMessage(message, "");
@@ -101,7 +88,7 @@ public class SmsReceiveJob extends ContextJob {
return insertResult;
} else {
return database.insertMessageInbox(masterSecret, message);
return database.insertMessageInbox(message);
}
}

View File

@@ -11,8 +11,8 @@ import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.jobs.requirements.NetworkOrServiceRequirement;
@@ -43,8 +43,8 @@ public class SmsSendJob extends SendJob {
@Override
public void onSend(MasterSecret masterSecret) throws NoSuchMessageException {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsMessageRecord record = database.getMessage(masterSecret, messageId);
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
SmsMessageRecord record = database.getMessage(messageId);
try {
Log.w(TAG, "Sending message: " + messageId);

View File

@@ -8,8 +8,8 @@ import android.util.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
@@ -46,7 +46,7 @@ public class SmsSentJob extends MasterSecretJob {
switch (action) {
case SmsDeliveryListener.SENT_SMS_ACTION:
handleSentResult(masterSecret, messageId, result);
handleSentResult(messageId, result);
break;
case SmsDeliveryListener.DELIVERED_SMS_ACTION:
handleDeliveredResult(messageId, result);
@@ -65,13 +65,13 @@ public class SmsSentJob extends MasterSecretJob {
}
private void handleDeliveredResult(long messageId, int result) {
DatabaseFactory.getEncryptingSmsDatabase(context).markStatus(messageId, result);
DatabaseFactory.getSmsDatabase(context).markStatus(messageId, result);
}
private void handleSentResult(MasterSecret masterSecret, long messageId, int result) {
private void handleSentResult(long messageId, int result) {
try {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsMessageRecord record = database.getMessage(masterSecret, messageId);
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
SmsMessageRecord record = database.getMessage(messageId);
switch (result) {
case Activity.RESULT_OK: