private void handleStaleDevices(TextSecureAddress recipient, StaleDevices staleDevices) { foreach (uint staleDeviceId in staleDevices.getStaleDevices()) { store.DeleteSession(new AxolotlAddress(recipient.getNumber(), staleDeviceId)); } }
private async void handleMismatchedDevices(PushServiceSocket socket, TextSecureAddress recipient, MismatchedDevices mismatchedDevices) { try { foreach (uint extraDeviceId in mismatchedDevices.getExtraDevices()) { store.DeleteSession(new AxolotlAddress(recipient.getNumber(), extraDeviceId)); } foreach (uint missingDeviceId in mismatchedDevices.getMissingDevices()) { PreKeyBundle preKey = await socket.getPreKey(recipient, missingDeviceId); try { SessionBuilder sessionBuilder = new SessionBuilder(store, new AxolotlAddress(recipient.getNumber(), missingDeviceId)); sessionBuilder.process(preKey); } catch (libaxolotl.exceptions.UntrustedIdentityException e) { throw new UntrustedIdentityException("Untrusted identity key!", recipient.getNumber(), preKey.getIdentityKey()); } } } catch (InvalidKeyException e) { throw new Exception(e.Message); } }
/** * Construct a TextSecureMessageSender. * * @param url The URL of the TextSecure server. * @param trustStore The trust store containing the TextSecure server's signing TLS certificate. * @param user The TextSecure username (eg phone number). * @param password The TextSecure user's password. * @param store The AxolotlStore. * @param eventListener An optional event listener, which fires whenever sessions are * setup or torn down for a recipient. */ public TextSecureMessageSender(String url, TrustStore trustStore, String user, String password, AxolotlStore store, May <EventListener> eventListener, String userAgent) { this.socket = new PushServiceSocket(url, trustStore, new StaticCredentialsProvider(user, password, null), userAgent); this.store = store; this.localAddress = new TextSecureAddress(user); this.eventListener = eventListener; }
private async Task <OutgoingPushMessageList> getEncryptedMessages(PushServiceSocket socket, TextSecureAddress recipient, ulong timestamp, byte[] plaintext, bool legacy) { List <OutgoingPushMessage> messages = new List <OutgoingPushMessage>(); if (!recipient.Equals(localAddress)) { messages.Add(await getEncryptedMessage(socket, recipient, TextSecureAddress.DEFAULT_DEVICE_ID, plaintext, legacy)); } foreach (uint deviceId in store.GetSubDeviceSessions(recipient.getNumber())) { messages.Add(await getEncryptedMessage(socket, recipient, deviceId, plaintext, legacy)); } return(new OutgoingPushMessageList(recipient.getNumber(), timestamp, recipient.getRelay().HasValue ? recipient.getRelay().ForceGetValue() : null, messages)); }
private void deliver(SmsMessageRecord message) { try { TextSecureAddress address = getPushAddress(message.getIndividualRecipient().getNumber()); TextSecureDataMessage textSecureMessage = TextSecureDataMessage.newBuilder() .withTimestamp((ulong)TimeUtil.GetUnixTimestampMillis(message.getDateSent())) .withBody(message.getBody().getBody()) .asEndSessionMessage(message.isEndSession()) .build(); Debug.WriteLine("TextSendTask deliver"); messageSender.sendMessage(address, textSecureMessage); } catch (InvalidNumberException e /*| UnregisteredUserException e*/) { //Log.w(TAG, e); //throw new InsecureFallbackApprovalException(e); } catch (Exception e) { //Log.w(TAG, e); //throw new RetryLaterException(e); } }
/** * Send a message to a single recipient. * * @param recipient The message's destination. * @param message The message. * @throws UntrustedIdentityException * @throws IOException */ public async void sendMessage(TextSecureAddress recipient, TextSecureDataMessage message) { byte[] content = await createMessageContent(message); ulong timestamp = message.getTimestamp(); SendMessageResponse response = await sendMessage(recipient, timestamp, content, true); if (response != null && response.getNeedsSync()) { byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, new May <TextSecureAddress>(recipient), timestamp); await sendMessage(localAddress, timestamp, syncMessage, false); } if (message.isEndSession()) { store.DeleteAllSessions(recipient.getNumber()); if (eventListener.HasValue) { eventListener.ForceGetValue().onSecurityEvent(recipient); } } }
private async Task <SendMessageResponse> sendMessage(TextSecureAddress recipient, ulong timestamp, byte[] content, bool legacy) { for (int i = 0; i < 3; i++) { try { OutgoingPushMessageList messages = await getEncryptedMessages(socket, recipient, timestamp, content, legacy); return(await socket.sendMessage(messages)); } catch (MismatchedDevicesException mde) { Debug.WriteLine(mde.Message, TAG); handleMismatchedDevices(socket, recipient, mde.getMismatchedDevices()); } catch (StaleDevicesException ste) { //Log.w(TAG, ste); handleStaleDevices(recipient, ste.getStaleDevices()); } } throw new Exception("Failed to resolve conflicts after 3 attempts!"); }
private void handleMessage(/*MasterSecretUnion masterSecret, */ TextSecureEnvelope envelope /*, Optional<Long> smsMessageId*/) { try { AxolotlStore axolotlStore = new TextSecureAxolotlStore(); TextSecureAddress localAddress = new TextSecureAddress(TextSecurePreferences.getLocalNumber()); TextSecureCipher cipher = new TextSecureCipher(localAddress, axolotlStore); TextSecureContent content = cipher.decrypt(envelope); if (content.getDataMessage().HasValue) { TextSecureDataMessage message = content.getDataMessage().ForceGetValue(); if (message.isEndSession()) { handleEndSessionMessage(/*masterSecret, */ envelope, message /*, smsMessageId*/); } //else if (message.isGroupUpdate()) handleGroupMessage(masterSecret, envelope, message, smsMessageId); //else if (message.getAttachments().isPresent()) handleMediaMessage(masterSecret, envelope, message, smsMessageId); else { handleTextMessage(/*masterSecret, */ envelope, message /*, smsMessageId*/); } } /*else if (content.getSyncMessage().HasValue) TODO: SYNC enable * { * TextSecureSyncMessage syncMessage = content.getSyncMessage().ForceGetValue(); * * if (syncMessage.getSent().HasValue) handleSynchronizeSentMessage(masterSecret, syncMessage.getSent().ForceGetValue(), smsMessageId); * else if (syncMessage.getRequest().HasValue) handleSynchronizeRequestMessage(masterSecret, syncMessage.getRequest().ForceGetValue()); * }*/ if (envelope.isPreKeyWhisperMessage()) { App.Current.Worker.AddTaskActivities(new RefreshPreKeysTask()); //ApplicationContext.getInstance(context).getJobManager().add(new RefreshPreKeysJob(context)); } } catch (InvalidVersionException e) { //Log.w(TAG, e); //handleInvalidVersionMessage(masterSecret, envelope, smsMessageId); } /* catch (InvalidMessageException | InvalidKeyIdException | InvalidKeyException | MmsException e) { * Log.w(TAG, e); * handleCorruptMessage(masterSecret, envelope, smsMessageId); * } catch (NoSessionException e) * { * Log.w(TAG, e); * handleNoSessionMessage(masterSecret, envelope, smsMessageId); * } * catch (LegacyMessageException e) * { * Log.w(TAG, e); * handleLegacyMessage(masterSecret, envelope, smsMessageId); * } * catch (DuplicateMessageException e) * { * Log.w(TAG, e); * handleDuplicateMessage(masterSecret, envelope, smsMessageId); * } * catch (UntrustedIdentityException e) * { * Log.w(TAG, e); * handleUntrustedIdentityMessage(masterSecret, envelope, smsMessageId); * }*/ }
public TextSecureCipher(TextSecureAddress localAddress, AxolotlStore axolotlStore) { this.axolotlStore = axolotlStore; this.localAddress = localAddress; }
/** * Send a delivery receipt for a received message. It is not necessary to call this * when receiving messages through {@link org.whispersystems.textsecure.api.TextSecureMessagePipe}. * @param recipient The sender of the received message you're acknowledging. * @param messageId The message id of the received message you're acknowledging. * @throws IOException */ public void sendDeliveryReceipt(TextSecureAddress recipient, ulong messageId) { this.socket.sendReceipt(recipient.getNumber(), messageId, recipient.getRelay()); }
private async Task <OutgoingPushMessage> getEncryptedMessage(PushServiceSocket socket, TextSecureAddress recipient, uint deviceId, byte[] plaintext, bool legacy) { AxolotlAddress axolotlAddress = new AxolotlAddress(recipient.getNumber(), deviceId); TextSecureCipher cipher = new TextSecureCipher(localAddress, store); if (!store.ContainsSession(axolotlAddress)) { try { List <PreKeyBundle> preKeys = await socket.getPreKeys(recipient, deviceId); foreach (PreKeyBundle preKey in preKeys) { try { AxolotlAddress preKeyAddress = new AxolotlAddress(recipient.getNumber(), preKey.getDeviceId()); SessionBuilder sessionBuilder = new SessionBuilder(store, preKeyAddress); sessionBuilder.process(preKey); } catch (libaxolotl.exceptions.UntrustedIdentityException e) { throw new UntrustedIdentityException("Untrusted identity key!", recipient.getNumber(), preKey.getIdentityKey()); } } if (eventListener.HasValue) { eventListener.ForceGetValue().onSecurityEvent(recipient); } } catch (InvalidKeyException e) { throw new Exception(e.Message); } } return(cipher.encrypt(axolotlAddress, plaintext, legacy)); }