Refactor protobuf validation exceptions.

fork-5.53.8
Greyson Parrelli 2021-08-06 14:47:43 -04:00 zatwierdzone przez GitHub
rodzic 570b4d7150
commit 0762a93787
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
5 zmienionych plików z 98 dodań i 50 usunięć

Wyświetl plik

@ -47,6 +47,7 @@ import org.whispersystems.libsignal.protocol.CiphertextMessage;
import org.whispersystems.libsignal.protocol.DecryptionErrorMessage; import org.whispersystems.libsignal.protocol.DecryptionErrorMessage;
import org.whispersystems.libsignal.state.SignalProtocolStore; import org.whispersystems.libsignal.state.SignalProtocolStore;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.InvalidMessageStructureException;
import org.whispersystems.signalservice.api.crypto.ContentHint; import org.whispersystems.signalservice.api.crypto.ContentHint;
import org.whispersystems.signalservice.api.crypto.SignalServiceCipher; import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
import org.whispersystems.signalservice.api.messages.SignalServiceContent; import org.whispersystems.signalservice.api.messages.SignalServiceContent;
@ -110,7 +111,7 @@ public final class MessageDecryptionUtil {
} catch (ProtocolDuplicateMessageException e) { } catch (ProtocolDuplicateMessageException e) {
Log.w(TAG, String.valueOf(envelope.getTimestamp()), e); Log.w(TAG, String.valueOf(envelope.getTimestamp()), e);
return DecryptionResult.forError(MessageState.DUPLICATE_MESSAGE, toExceptionMetadata(e), jobs); return DecryptionResult.forError(MessageState.DUPLICATE_MESSAGE, toExceptionMetadata(e), jobs);
} catch (InvalidMetadataVersionException | InvalidMetadataMessageException e) { } catch (InvalidMetadataVersionException | InvalidMetadataMessageException | InvalidMessageStructureException e) {
Log.w(TAG, String.valueOf(envelope.getTimestamp()), e); Log.w(TAG, String.valueOf(envelope.getTimestamp()), e);
return DecryptionResult.forNoop(jobs); return DecryptionResult.forNoop(jobs);
} catch (SelfSendException e) { } catch (SelfSendException e) {

Wyświetl plik

@ -0,0 +1,44 @@
package org.whispersystems.signalservice.api;
import org.whispersystems.libsignal.util.guava.Optional;
/**
* An exception thrown when something about the proto is malformed. e.g. one of the fields has an invalid value.
*/
public final class InvalidMessageStructureException extends Exception {
private final Optional<String> sender;
private final Optional<Integer> device;
public InvalidMessageStructureException(String message) {
super(message);
this.sender = Optional.absent();
this.device = Optional.absent();
}
public InvalidMessageStructureException(String message, String sender, int device) {
super(message);
this.sender = Optional.fromNullable(sender);
this.device = Optional.of(device);
}
public InvalidMessageStructureException(Exception e, String sender, int device) {
super(e);
this.sender = Optional.fromNullable(sender);
this.device = Optional.of(device);
}
public InvalidMessageStructureException(Exception e) {
super(e);
this.sender = Optional.absent();
this.device = Optional.absent();
}
public Optional<String> getSender() {
return sender;
}
public Optional<Integer> getDevice() {
return device;
}
}

Wyświetl plik

@ -41,6 +41,7 @@ import org.whispersystems.libsignal.protocol.PreKeySignalMessage;
import org.whispersystems.libsignal.protocol.SignalMessage; import org.whispersystems.libsignal.protocol.SignalMessage;
import org.whispersystems.libsignal.state.SignalProtocolStore; import org.whispersystems.libsignal.state.SignalProtocolStore;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.InvalidMessageStructureException;
import org.whispersystems.signalservice.api.SignalSessionLock; import org.whispersystems.signalservice.api.SignalSessionLock;
import org.whispersystems.signalservice.api.messages.SignalServiceContent; import org.whispersystems.signalservice.api.messages.SignalServiceContent;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
@ -135,7 +136,7 @@ public class SignalServiceCipher {
ProtocolUntrustedIdentityException, ProtocolNoSessionException, ProtocolUntrustedIdentityException, ProtocolNoSessionException,
ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidVersionException, ProtocolInvalidMessageException,
ProtocolInvalidKeyException, ProtocolDuplicateMessageException, ProtocolInvalidKeyException, ProtocolDuplicateMessageException,
SelfSendException, UnsupportedDataMessageException SelfSendException, UnsupportedDataMessageException, InvalidMessageStructureException
{ {
try { try {
if (envelope.hasLegacyMessage()) { if (envelope.hasLegacyMessage()) {
@ -174,7 +175,7 @@ public class SignalServiceCipher {
ProtocolLegacyMessageException, ProtocolInvalidKeyException, ProtocolLegacyMessageException, ProtocolInvalidKeyException,
ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidVersionException, ProtocolInvalidMessageException,
ProtocolInvalidKeyIdException, ProtocolNoSessionException, ProtocolInvalidKeyIdException, ProtocolNoSessionException,
SelfSendException SelfSendException, InvalidMessageStructureException
{ {
try { try {
@ -182,7 +183,7 @@ public class SignalServiceCipher {
SignalServiceMetadata metadata; SignalServiceMetadata metadata;
if (!envelope.hasSource() && !envelope.isUnidentifiedSender()) { if (!envelope.hasSource() && !envelope.isUnidentifiedSender()) {
throw new ProtocolInvalidMessageException(new InvalidMessageException("Non-UD envelope is missing a source!"), null, 0); throw new InvalidMessageStructureException("Non-UD envelope is missing a source!");
} }
if (envelope.isPreKeySignalMessage()) { if (envelope.isPreKeySignalMessage()) {

Wyświetl plik

@ -3,6 +3,7 @@ package org.whispersystems.signalservice.api.messages;
import org.signal.libsignal.metadata.ProtocolInvalidMessageException; import org.signal.libsignal.metadata.ProtocolInvalidMessageException;
import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.InvalidMessageException;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.InvalidMessageStructureException;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.AttachmentPointer; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.AttachmentPointer;
/** /**
@ -43,14 +44,14 @@ public final class SignalServiceAttachmentRemoteId {
} }
} }
public static SignalServiceAttachmentRemoteId from(AttachmentPointer attachmentPointer) throws ProtocolInvalidMessageException { public static SignalServiceAttachmentRemoteId from(AttachmentPointer attachmentPointer) throws InvalidMessageStructureException {
switch (attachmentPointer.getAttachmentIdentifierCase()) { switch (attachmentPointer.getAttachmentIdentifierCase()) {
case CDNID: case CDNID:
return new SignalServiceAttachmentRemoteId(attachmentPointer.getCdnId()); return new SignalServiceAttachmentRemoteId(attachmentPointer.getCdnId());
case CDNKEY: case CDNKEY:
return new SignalServiceAttachmentRemoteId(attachmentPointer.getCdnKey()); return new SignalServiceAttachmentRemoteId(attachmentPointer.getCdnKey());
case ATTACHMENTIDENTIFIER_NOT_SET: case ATTACHMENTIDENTIFIER_NOT_SET:
throw new ProtocolInvalidMessageException(new InvalidMessageException("AttachmentPointer CDN location not set"), null, 0); throw new InvalidMessageStructureException("AttachmentPointer CDN location not set");
} }
return null; return null;
} }

Wyświetl plik

@ -21,6 +21,7 @@ import org.whispersystems.libsignal.logging.Log;
import org.whispersystems.libsignal.protocol.DecryptionErrorMessage; import org.whispersystems.libsignal.protocol.DecryptionErrorMessage;
import org.whispersystems.libsignal.protocol.SenderKeyDistributionMessage; import org.whispersystems.libsignal.protocol.SenderKeyDistributionMessage;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.InvalidMessageStructureException;
import org.whispersystems.signalservice.api.messages.calls.AnswerMessage; import org.whispersystems.signalservice.api.messages.calls.AnswerMessage;
import org.whispersystems.signalservice.api.messages.calls.BusyMessage; import org.whispersystems.signalservice.api.messages.calls.BusyMessage;
import org.whispersystems.signalservice.api.messages.calls.HangupMessage; import org.whispersystems.signalservice.api.messages.calls.HangupMessage;
@ -370,7 +371,7 @@ public final class SignalServiceContent {
SignalServiceContentProto signalServiceContentProto = SignalServiceContentProto.parseFrom(data); SignalServiceContentProto signalServiceContentProto = SignalServiceContentProto.parseFrom(data);
return createFromProto(signalServiceContentProto); return createFromProto(signalServiceContentProto);
} catch (InvalidProtocolBufferException | ProtocolInvalidMessageException | ProtocolInvalidKeyException | UnsupportedDataMessageException e) { } catch (InvalidProtocolBufferException | ProtocolInvalidMessageException | ProtocolInvalidKeyException | UnsupportedDataMessageException | InvalidMessageStructureException e) {
// We do not expect any of these exceptions if this byte[] has come from serialize. // We do not expect any of these exceptions if this byte[] has come from serialize.
throw new AssertionError(e); throw new AssertionError(e);
} }
@ -380,7 +381,7 @@ public final class SignalServiceContent {
* Takes internal protobuf serialization format and processes it into a {@link SignalServiceContent}. * Takes internal protobuf serialization format and processes it into a {@link SignalServiceContent}.
*/ */
public static SignalServiceContent createFromProto(SignalServiceContentProto serviceContentProto) public static SignalServiceContent createFromProto(SignalServiceContentProto serviceContentProto)
throws ProtocolInvalidMessageException, ProtocolInvalidKeyException, UnsupportedDataMessageException throws ProtocolInvalidMessageException, ProtocolInvalidKeyException, UnsupportedDataMessageException, InvalidMessageStructureException
{ {
SignalServiceMetadata metadata = SignalServiceMetadataProtobufSerializer.fromProtobuf(serviceContentProto.getMetadata()); SignalServiceMetadata metadata = SignalServiceMetadataProtobufSerializer.fromProtobuf(serviceContentProto.getMetadata());
SignalServiceAddress localAddress = SignalServiceAddressProtobufSerializer.fromProtobuf(serviceContentProto.getLocalAddress()); SignalServiceAddress localAddress = SignalServiceAddressProtobufSerializer.fromProtobuf(serviceContentProto.getLocalAddress());
@ -502,7 +503,7 @@ public final class SignalServiceContent {
private static SignalServiceDataMessage createSignalServiceMessage(SignalServiceMetadata metadata, private static SignalServiceDataMessage createSignalServiceMessage(SignalServiceMetadata metadata,
SignalServiceProtos.DataMessage content) SignalServiceProtos.DataMessage content)
throws ProtocolInvalidMessageException, UnsupportedDataMessageException throws UnsupportedDataMessageException, InvalidMessageStructureException
{ {
SignalServiceGroup groupInfoV1 = createGroupV1Info(content); SignalServiceGroup groupInfoV1 = createGroupV1Info(content);
SignalServiceGroupV2 groupInfoV2 = createGroupV2Info(content); SignalServiceGroupV2 groupInfoV2 = createGroupV2Info(content);
@ -511,7 +512,7 @@ public final class SignalServiceContent {
try { try {
groupContext = SignalServiceGroupContext.createOptional(groupInfoV1, groupInfoV2); groupContext = SignalServiceGroupContext.createOptional(groupInfoV1, groupInfoV2);
} catch (InvalidMessageException e) { } catch (InvalidMessageException e) {
throw new ProtocolInvalidMessageException(e, null, 0); throw new InvalidMessageStructureException(e);
} }
@ -537,12 +538,7 @@ public final class SignalServiceContent {
groupContext); groupContext);
} }
SignalServiceDataMessage.Payment payment; SignalServiceDataMessage.Payment payment = createPayment(content);
try {
payment = createPayment(content);
} catch (InvalidMessageException e) {
throw new ProtocolInvalidMessageException(e, metadata.getSender().getIdentifier(), metadata.getSenderDevice());
}
if (content.getRequiredProtocolVersion() > SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT.getNumber()) { if (content.getRequiredProtocolVersion() > SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT.getNumber()) {
throw new UnsupportedDataMessageProtocolVersionException(SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT.getNumber(), throw new UnsupportedDataMessageProtocolVersionException(SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT.getNumber(),
@ -557,7 +553,7 @@ public final class SignalServiceContent {
} }
if (content.hasTimestamp() && content.getTimestamp() != metadata.getTimestamp()) { if (content.hasTimestamp() && content.getTimestamp() != metadata.getTimestamp()) {
throw new ProtocolInvalidMessageException(new InvalidMessageException("Timestamps don't match: " + content.getTimestamp() + " vs " + metadata.getTimestamp()), throw new InvalidMessageStructureException("Timestamps don't match: " + content.getTimestamp() + " vs " + metadata.getTimestamp(),
metadata.getSender().getIdentifier(), metadata.getSender().getIdentifier(),
metadata.getSenderDevice()); metadata.getSenderDevice());
} }
@ -585,7 +581,7 @@ public final class SignalServiceContent {
private static SignalServiceSyncMessage createSynchronizeMessage(SignalServiceMetadata metadata, private static SignalServiceSyncMessage createSynchronizeMessage(SignalServiceMetadata metadata,
SignalServiceProtos.SyncMessage content) SignalServiceProtos.SyncMessage content)
throws ProtocolInvalidMessageException, ProtocolInvalidKeyException, UnsupportedDataMessageException throws ProtocolInvalidKeyException, UnsupportedDataMessageException, InvalidMessageStructureException
{ {
if (content.hasSent()) { if (content.hasSent()) {
Map<SignalServiceAddress, Boolean> unidentifiedStatuses = new HashMap<>(); Map<SignalServiceAddress, Boolean> unidentifiedStatuses = new HashMap<>();
@ -596,7 +592,7 @@ public final class SignalServiceContent {
: Optional.<SignalServiceAddress>absent(); : Optional.<SignalServiceAddress>absent();
if (!address.isPresent() && !dataMessage.getGroupContext().isPresent()) { if (!address.isPresent() && !dataMessage.getGroupContext().isPresent()) {
throw new ProtocolInvalidMessageException(new InvalidMessageException("SyncMessage missing both destination and group ID!"), null, 0); throw new InvalidMessageStructureException("SyncMessage missing both destination and group ID!");
} }
for (SignalServiceProtos.SyncMessage.Sent.UnidentifiedDeliveryStatus status : sentContent.getUnidentifiedStatusList()) { for (SignalServiceProtos.SyncMessage.Sent.UnidentifiedDeliveryStatus status : sentContent.getUnidentifiedStatusList()) {
@ -656,7 +652,7 @@ public final class SignalServiceContent {
ViewOnceOpenMessage timerRead = new ViewOnceOpenMessage(address, content.getViewOnceOpen().getTimestamp()); ViewOnceOpenMessage timerRead = new ViewOnceOpenMessage(address, content.getViewOnceOpen().getTimestamp());
return SignalServiceSyncMessage.forViewOnceOpen(timerRead); return SignalServiceSyncMessage.forViewOnceOpen(timerRead);
} else { } else {
throw new ProtocolInvalidMessageException(new InvalidMessageException("ViewOnceOpen message has no sender!"), null, 0); throw new InvalidMessageStructureException("ViewOnceOpen message has no sender!");
} }
} }
@ -676,8 +672,9 @@ public final class SignalServiceContent {
} else if (verified.getState() == SignalServiceProtos.Verified.State.UNVERIFIED) { } else if (verified.getState() == SignalServiceProtos.Verified.State.UNVERIFIED) {
verifiedState = VerifiedMessage.VerifiedState.UNVERIFIED; verifiedState = VerifiedMessage.VerifiedState.UNVERIFIED;
} else { } else {
throw new ProtocolInvalidMessageException(new InvalidMessageException("Unknown state: " + verified.getState().getNumber()), throw new InvalidMessageStructureException("Unknown state: " + verified.getState().getNumber(),
metadata.getSender().getIdentifier(), metadata.getSenderDevice()); metadata.getSender().getIdentifier(),
metadata.getSenderDevice());
} }
return SignalServiceSyncMessage.forVerified(new VerifiedMessage(destination, identityKey, verifiedState, System.currentTimeMillis())); return SignalServiceSyncMessage.forVerified(new VerifiedMessage(destination, identityKey, verifiedState, System.currentTimeMillis()));
@ -685,7 +682,7 @@ public final class SignalServiceContent {
throw new ProtocolInvalidKeyException(e, metadata.getSender().getIdentifier(), metadata.getSenderDevice()); throw new ProtocolInvalidKeyException(e, metadata.getSender().getIdentifier(), metadata.getSenderDevice());
} }
} else { } else {
throw new ProtocolInvalidMessageException(new InvalidMessageException("Verified message has no sender!"), null, 0); throw new InvalidMessageStructureException("Verified message has no sender!");
} }
} }
@ -786,7 +783,7 @@ public final class SignalServiceContent {
if (address.isPresent()) { if (address.isPresent()) {
responseMessage = MessageRequestResponseMessage.forIndividual(address.get(), type); responseMessage = MessageRequestResponseMessage.forIndividual(address.get(), type);
} else { } else {
throw new ProtocolInvalidMessageException(new InvalidMessageException("Message request response has an invalid thread identifier!"), null, 0); throw new InvalidMessageStructureException("Message request response has an invalid thread identifier!");
} }
} }
@ -868,15 +865,15 @@ public final class SignalServiceContent {
return new SignalServiceReceiptMessage(type, content.getTimestampList(), metadata.getTimestamp()); return new SignalServiceReceiptMessage(type, content.getTimestampList(), metadata.getTimestamp());
} }
private static DecryptionErrorMessage createDecryptionErrorMessage(SignalServiceMetadata metadata, ByteString content) throws ProtocolInvalidMessageException { private static DecryptionErrorMessage createDecryptionErrorMessage(SignalServiceMetadata metadata, ByteString content) throws InvalidMessageStructureException {
try { try {
return new DecryptionErrorMessage(content.toByteArray()); return new DecryptionErrorMessage(content.toByteArray());
} catch (InvalidMessageException e) { } catch (InvalidMessageException e) {
throw new ProtocolInvalidMessageException(e, metadata.getSender().getIdentifier(), metadata.getSenderDevice()); throw new InvalidMessageStructureException(e, metadata.getSender().getIdentifier(), metadata.getSenderDevice());
} }
} }
private static SignalServiceTypingMessage createTypingMessage(SignalServiceMetadata metadata, SignalServiceProtos.TypingMessage content) throws ProtocolInvalidMessageException { private static SignalServiceTypingMessage createTypingMessage(SignalServiceMetadata metadata, SignalServiceProtos.TypingMessage content) throws InvalidMessageStructureException {
SignalServiceTypingMessage.Action action; SignalServiceTypingMessage.Action action;
if (content.getAction() == SignalServiceProtos.TypingMessage.Action.STARTED) action = SignalServiceTypingMessage.Action.STARTED; if (content.getAction() == SignalServiceProtos.TypingMessage.Action.STARTED) action = SignalServiceTypingMessage.Action.STARTED;
@ -884,7 +881,7 @@ public final class SignalServiceContent {
else action = SignalServiceTypingMessage.Action.UNKNOWN; else action = SignalServiceTypingMessage.Action.UNKNOWN;
if (content.hasTimestamp() && content.getTimestamp() != metadata.getTimestamp()) { if (content.hasTimestamp() && content.getTimestamp() != metadata.getTimestamp()) {
throw new ProtocolInvalidMessageException(new InvalidMessageException("Timestamps don't match: " + content.getTimestamp() + " vs " + metadata.getTimestamp()), throw new InvalidMessageStructureException("Timestamps don't match: " + content.getTimestamp() + " vs " + metadata.getTimestamp(),
metadata.getSender().getIdentifier(), metadata.getSender().getIdentifier(),
metadata.getSenderDevice()); metadata.getSenderDevice());
} }
@ -894,7 +891,9 @@ public final class SignalServiceContent {
Optional.<byte[]>absent()); Optional.<byte[]>absent());
} }
private static SignalServiceDataMessage.Quote createQuote(SignalServiceProtos.DataMessage content, boolean isGroupV2) throws ProtocolInvalidMessageException { private static SignalServiceDataMessage.Quote createQuote(SignalServiceProtos.DataMessage content, boolean isGroupV2)
throws InvalidMessageStructureException
{
if (!content.hasQuote()) return null; if (!content.hasQuote()) return null;
List<SignalServiceDataMessage.Quote.QuotedAttachment> attachments = new LinkedList<>(); List<SignalServiceDataMessage.Quote.QuotedAttachment> attachments = new LinkedList<>();
@ -919,7 +918,7 @@ public final class SignalServiceContent {
} }
} }
private static List<SignalServiceDataMessage.Preview> createPreviews(SignalServiceProtos.DataMessage content) throws ProtocolInvalidMessageException { private static List<SignalServiceDataMessage.Preview> createPreviews(SignalServiceProtos.DataMessage content) throws InvalidMessageStructureException {
if (content.getPreviewCount() <= 0) return null; if (content.getPreviewCount() <= 0) return null;
List<SignalServiceDataMessage.Preview> results = new LinkedList<>(); List<SignalServiceDataMessage.Preview> results = new LinkedList<>();
@ -941,7 +940,9 @@ public final class SignalServiceContent {
return results; return results;
} }
private static List<SignalServiceDataMessage.Mention> createMentions(List<SignalServiceProtos.DataMessage.BodyRange> bodyRanges, String body, boolean isGroupV2) throws ProtocolInvalidMessageException { private static List<SignalServiceDataMessage.Mention> createMentions(List<SignalServiceProtos.DataMessage.BodyRange> bodyRanges, String body, boolean isGroupV2)
throws InvalidMessageStructureException
{
if (bodyRanges == null || bodyRanges.isEmpty() || body == null) { if (bodyRanges == null || bodyRanges.isEmpty() || body == null) {
return null; return null;
} }
@ -953,19 +954,19 @@ public final class SignalServiceContent {
try { try {
mentions.add(new SignalServiceDataMessage.Mention(UuidUtil.parseOrThrow(bodyRange.getMentionUuid()), bodyRange.getStart(), bodyRange.getLength())); mentions.add(new SignalServiceDataMessage.Mention(UuidUtil.parseOrThrow(bodyRange.getMentionUuid()), bodyRange.getStart(), bodyRange.getLength()));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new ProtocolInvalidMessageException(new InvalidMessageException(e), null, 0); throw new InvalidMessageStructureException("Invalid body range!");
} }
} }
} }
if (mentions.size() > 0 && !isGroupV2) { if (mentions.size() > 0 && !isGroupV2) {
throw new ProtocolInvalidMessageException(new InvalidMessageException("Mentions received in non-GV2 message"), null, 0); throw new InvalidMessageStructureException("Mentions received in non-GV2 message");
} }
return mentions; return mentions;
} }
private static SignalServiceDataMessage.Sticker createSticker(SignalServiceProtos.DataMessage content) throws ProtocolInvalidMessageException { private static SignalServiceDataMessage.Sticker createSticker(SignalServiceProtos.DataMessage content) throws InvalidMessageStructureException {
if (!content.hasSticker() || if (!content.hasSticker() ||
!content.getSticker().hasPackId() || !content.getSticker().hasPackId() ||
!content.getSticker().hasPackKey() || !content.getSticker().hasPackKey() ||
@ -1027,7 +1028,7 @@ public final class SignalServiceContent {
return new SignalServiceDataMessage.GroupCallUpdate(groupCallUpdate.getEraId()); return new SignalServiceDataMessage.GroupCallUpdate(groupCallUpdate.getEraId());
} }
private static SignalServiceDataMessage.Payment createPayment(SignalServiceProtos.DataMessage content) throws InvalidMessageException { private static SignalServiceDataMessage.Payment createPayment(SignalServiceProtos.DataMessage content) throws InvalidMessageStructureException {
if (!content.hasPayment()) { if (!content.hasPayment()) {
return null; return null;
} }
@ -1036,17 +1037,17 @@ public final class SignalServiceContent {
switch (payment.getItemCase()) { switch (payment.getItemCase()) {
case NOTIFICATION: return new SignalServiceDataMessage.Payment(createPaymentNotification(payment)); case NOTIFICATION: return new SignalServiceDataMessage.Payment(createPaymentNotification(payment));
default : throw new InvalidMessageException("Unknown payment item"); default : throw new InvalidMessageStructureException("Unknown payment item");
} }
} }
private static SignalServiceDataMessage.PaymentNotification createPaymentNotification(SignalServiceProtos.DataMessage.Payment content) private static SignalServiceDataMessage.PaymentNotification createPaymentNotification(SignalServiceProtos.DataMessage.Payment content)
throws InvalidMessageException throws InvalidMessageStructureException
{ {
if (!content.hasNotification() || if (!content.hasNotification() ||
content.getNotification().getTransactionCase() != SignalServiceProtos.DataMessage.Payment.Notification.TransactionCase.MOBILECOIN) content.getNotification().getTransactionCase() != SignalServiceProtos.DataMessage.Payment.Notification.TransactionCase.MOBILECOIN)
{ {
throw new InvalidMessageException(); throw new InvalidMessageStructureException("Badly-formatted payment notification!");
} }
SignalServiceProtos.DataMessage.Payment.Notification payment = content.getNotification(); SignalServiceProtos.DataMessage.Payment.Notification payment = content.getNotification();
@ -1054,7 +1055,7 @@ public final class SignalServiceContent {
return new SignalServiceDataMessage.PaymentNotification(payment.getMobileCoin().getReceipt().toByteArray(), payment.getNote()); return new SignalServiceDataMessage.PaymentNotification(payment.getMobileCoin().getReceipt().toByteArray(), payment.getNote());
} }
private static List<SharedContact> createSharedContacts(SignalServiceProtos.DataMessage content) throws ProtocolInvalidMessageException { private static List<SharedContact> createSharedContacts(SignalServiceProtos.DataMessage content) throws InvalidMessageStructureException {
if (content.getContactCount() <= 0) return null; if (content.getContactCount() <= 0) return null;
List<SharedContact> results = new LinkedList<>(); List<SharedContact> results = new LinkedList<>();
@ -1149,7 +1150,7 @@ public final class SignalServiceContent {
return results; return results;
} }
private static SignalServiceAttachmentPointer createAttachmentPointer(SignalServiceProtos.AttachmentPointer pointer) throws ProtocolInvalidMessageException { private static SignalServiceAttachmentPointer createAttachmentPointer(SignalServiceProtos.AttachmentPointer pointer) throws InvalidMessageStructureException {
return new SignalServiceAttachmentPointer(pointer.getCdnNumber(), return new SignalServiceAttachmentPointer(pointer.getCdnNumber(),
SignalServiceAttachmentRemoteId.from(pointer), SignalServiceAttachmentRemoteId.from(pointer),
pointer.getContentType(), pointer.getContentType(),
@ -1168,7 +1169,7 @@ public final class SignalServiceContent {
} }
private static SignalServiceGroup createGroupV1Info(SignalServiceProtos.DataMessage content) throws ProtocolInvalidMessageException { private static SignalServiceGroup createGroupV1Info(SignalServiceProtos.DataMessage content) throws InvalidMessageStructureException {
if (!content.hasGroup()) return null; if (!content.hasGroup()) return null;
SignalServiceGroup.Type type; SignalServiceGroup.Type type;
@ -1197,7 +1198,7 @@ public final class SignalServiceContent {
if (SignalServiceAddress.isValidAddress(null, member.getE164())) { if (SignalServiceAddress.isValidAddress(null, member.getE164())) {
members.add(new SignalServiceAddress(null, member.getE164())); members.add(new SignalServiceAddress(null, member.getE164()));
} else { } else {
throw new ProtocolInvalidMessageException(new InvalidMessageException("GroupContext.Member had no address!"), null, 0); throw new InvalidMessageStructureException("GroupContext.Member had no address!");
} }
} }
} else if (content.getGroup().getMembersE164Count() > 0) { } else if (content.getGroup().getMembersE164Count() > 0) {
@ -1233,15 +1234,15 @@ public final class SignalServiceContent {
return new SignalServiceGroup(content.getGroup().getId().toByteArray()); return new SignalServiceGroup(content.getGroup().getId().toByteArray());
} }
private static SignalServiceGroupV2 createGroupV2Info(SignalServiceProtos.DataMessage content) throws ProtocolInvalidMessageException { private static SignalServiceGroupV2 createGroupV2Info(SignalServiceProtos.DataMessage content) throws InvalidMessageStructureException {
if (!content.hasGroupV2()) return null; if (!content.hasGroupV2()) return null;
SignalServiceProtos.GroupContextV2 groupV2 = content.getGroupV2(); SignalServiceProtos.GroupContextV2 groupV2 = content.getGroupV2();
if (!groupV2.hasMasterKey()) { if (!groupV2.hasMasterKey()) {
throw new ProtocolInvalidMessageException(new InvalidMessageException("No GV2 master key on message"), null, 0); throw new InvalidMessageStructureException("No GV2 master key on message");
} }
if (!groupV2.hasRevision()) { if (!groupV2.hasRevision()) {
throw new ProtocolInvalidMessageException(new InvalidMessageException("No GV2 revision on message"), null, 0); throw new InvalidMessageStructureException("No GV2 revision on message");
} }
SignalServiceGroupV2.Builder builder; SignalServiceGroupV2.Builder builder;
@ -1249,7 +1250,7 @@ public final class SignalServiceContent {
builder = SignalServiceGroupV2.newBuilder(new GroupMasterKey(groupV2.getMasterKey().toByteArray())) builder = SignalServiceGroupV2.newBuilder(new GroupMasterKey(groupV2.getMasterKey().toByteArray()))
.withRevision(groupV2.getRevision()); .withRevision(groupV2.getRevision());
} catch (InvalidInputException e) { } catch (InvalidInputException e) {
throw new ProtocolInvalidMessageException(new InvalidMessageException(e), null, 0); throw new InvalidMessageStructureException("Invalid GV2 input!");
} }
if (groupV2.hasGroupChange() && !groupV2.getGroupChange().isEmpty()) { if (groupV2.hasGroupChange() && !groupV2.getGroupChange().isEmpty()) {