session-android/src/org/thoughtcrime/securesms/service/SmsReceiver.java

178 lines
7.6 KiB
Java
Raw Normal View History

2012-10-30 00:34:14 +00:00
/**
2011-12-20 18:20:44 +00:00
* Copyright (C) 2011 Whisper Systems
2012-10-30 00:34:14 +00:00
*
2011-12-20 18:20:44 +00:00
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
2012-10-30 00:34:14 +00:00
*
2011-12-20 18:20:44 +00:00
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.service;
2012-10-30 00:34:14 +00:00
import android.content.Context;
import android.content.Intent;
import android.preference.PreferenceManager;
import android.util.Log;
2011-12-20 18:20:44 +00:00
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.crypto.DecryptingQueue;
import org.thoughtcrime.securesms.crypto.InvalidKeyException;
import org.thoughtcrime.securesms.crypto.InvalidVersionException;
import org.thoughtcrime.securesms.crypto.KeyExchangeMessage;
import org.thoughtcrime.securesms.crypto.KeyExchangeProcessor;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
2011-12-20 18:20:44 +00:00
import org.thoughtcrime.securesms.protocol.Prefix;
import org.thoughtcrime.securesms.protocol.WirePrefix;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.sms.MultipartMessageHandler;
import org.thoughtcrime.securesms.sms.TextMessage;
import java.util.ArrayList;
2011-12-20 18:20:44 +00:00
public class SmsReceiver {
private MultipartMessageHandler multipartMessageHandler = new MultipartMessageHandler();
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
private final Context context;
2012-10-30 00:34:14 +00:00
2013-02-15 03:15:40 +00:00
public SmsReceiver(Context context) {
this.context = context;
2011-12-20 18:20:44 +00:00
}
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
private String assembleSecureMessageFragments(String sender, String messageBody) {
String localPrefix;
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
if (WirePrefix.isEncryptedMessage(messageBody)) {
localPrefix = Prefix.ASYMMETRIC_ENCRYPT;
} else {
localPrefix = Prefix.KEY_EXCHANGE;
}
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
Log.w("SMSReceiverService", "Calculated local prefix for message: " + messageBody + " - Local Prefix: " + localPrefix);
messageBody = messageBody.substring(WirePrefix.PREFIX_SIZE);
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
Log.w("SMSReceiverService", "Parsed off wire prefix: " + messageBody);
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
if (!multipartMessageHandler.isManualTransport(messageBody))
return localPrefix + messageBody;
else
return multipartMessageHandler.processPotentialMultipartMessage(localPrefix, sender, messageBody);
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
}
2012-10-30 00:34:14 +00:00
private String assembleMessageFragments(TextMessage[] messages) {
2011-12-20 18:20:44 +00:00
StringBuilder body = new StringBuilder();
2012-10-30 00:34:14 +00:00
for (TextMessage message : messages) {
body.append(message.getMessage());
2011-12-20 18:20:44 +00:00
}
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
String messageBody = body.toString();
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
if (WirePrefix.isEncryptedMessage(messageBody) || WirePrefix.isKeyExchange(messageBody)) {
return assembleSecureMessageFragments(messages[0].getSender(), messageBody);
2011-12-20 18:20:44 +00:00
} else {
return messageBody;
}
}
2012-10-30 00:34:14 +00:00
private long storeSecureMessage(MasterSecret masterSecret, TextMessage message, String messageBody) {
2011-12-20 18:20:44 +00:00
long messageId = DatabaseFactory.getSmsDatabase(context).insertSecureMessageReceived(message, messageBody);
Log.w("SmsReceiver", "Inserted secure message received: " + messageId);
2012-10-30 00:34:14 +00:00
if (masterSecret != null)
DecryptingQueue.scheduleDecryption(context, masterSecret, messageId, message.getSender(), messageBody);
return messageId;
2011-12-20 18:20:44 +00:00
}
2012-10-30 00:34:14 +00:00
private long storeStandardMessage(MasterSecret masterSecret, TextMessage message, String messageBody) {
2011-12-20 18:20:44 +00:00
if (masterSecret != null) return DatabaseFactory.getEncryptingSmsDatabase(context).insertMessageReceived(masterSecret, message, messageBody);
else if (MasterSecretUtil.hasAsymmericMasterSecret(context)) return DatabaseFactory.getEncryptingSmsDatabase(context).insertMessageReceived(MasterSecretUtil.getAsymmetricMasterSecret(context, null), message, messageBody);
2012-10-30 00:34:14 +00:00
else return DatabaseFactory.getSmsDatabase(context).insertMessageReceived(message, messageBody);
2011-12-20 18:20:44 +00:00
}
private long storeKeyExchangeMessage(MasterSecret masterSecret, TextMessage message, String messageBody) {
2011-12-20 18:20:44 +00:00
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(ApplicationPreferencesActivity.AUTO_KEY_EXCHANGE_PREF, true)) {
try {
Recipient recipient = new Recipient(null, message.getSender(), null, null);
2012-10-30 00:34:14 +00:00
KeyExchangeMessage keyExchangeMessage = new KeyExchangeMessage(messageBody);
KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipient);
Log.w("SmsReceiver", "Received key with fingerprint: " + keyExchangeMessage.getPublicKey().getFingerprint());
if (processor.isStale(keyExchangeMessage)) {
messageBody = messageBody.substring(Prefix.KEY_EXCHANGE.length());
messageBody = Prefix.STALE_KEY_EXCHANGE + messageBody;
} else if (!processor.hasCompletedSession() || processor.hasSameSessionIdentity(keyExchangeMessage)) {
messageBody = messageBody.substring(Prefix.KEY_EXCHANGE.length());
messageBody = Prefix.PROCESSED_KEY_EXCHANGE + messageBody;
long messageId = storeStandardMessage(masterSecret, message, messageBody);
long threadId = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageId);
processor.processKeyExchangeMessage(keyExchangeMessage, threadId);
return messageId;
2012-10-30 00:34:14 +00:00
}
2011-12-20 18:20:44 +00:00
} catch (InvalidVersionException e) {
2012-10-30 00:34:14 +00:00
Log.w("SmsReceiver", e);
2011-12-20 18:20:44 +00:00
} catch (InvalidKeyException e) {
2012-10-30 00:34:14 +00:00
Log.w("SmsReceiver", e);
2011-12-20 18:20:44 +00:00
}
}
return storeStandardMessage(masterSecret, message, messageBody);
2011-12-20 18:20:44 +00:00
}
2012-10-30 00:34:14 +00:00
private long storeMessage(MasterSecret masterSecret, TextMessage message, String messageBody) {
2011-12-20 18:20:44 +00:00
if (messageBody.startsWith(Prefix.ASYMMETRIC_ENCRYPT)) {
return storeSecureMessage(masterSecret, message, messageBody);
2011-12-20 18:20:44 +00:00
} else if (messageBody.startsWith(Prefix.KEY_EXCHANGE)) {
return storeKeyExchangeMessage(masterSecret, message, messageBody);
2011-12-20 18:20:44 +00:00
} else {
return storeStandardMessage(masterSecret, message, messageBody);
2011-12-20 18:20:44 +00:00
}
}
// private SmsMessage[] parseMessages(Bundle bundle) {
// Object[] pdus = (Object[])bundle.get("pdus");
// SmsMessage[] messages = new SmsMessage[pdus.length];
//
// for (int i=0;i<pdus.length;i++)
// messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
//
// return messages;
// }
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
private void handleReceiveMessage(MasterSecret masterSecret, Intent intent) {
ArrayList<TextMessage> messagesList = intent.getExtras().getParcelableArrayList("text_messages");
TextMessage[] messages = messagesList.toArray(new TextMessage[0]);
// Bundle bundle = intent.getExtras();
// SmsMessage[] messages = parseMessages(bundle);
2011-12-20 18:20:44 +00:00
String message = assembleMessageFragments(messages);
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
if (message != null) {
long messageId = storeMessage(masterSecret, messages[0], message);
long threadId = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageId);
MessageNotifier.updateNotification(context, masterSecret, threadId);
2012-10-30 00:34:14 +00:00
}
2011-12-20 18:20:44 +00:00
}
2012-10-30 00:34:14 +00:00
2011-12-20 18:20:44 +00:00
public void process(MasterSecret masterSecret, Intent intent) {
2013-02-15 03:15:40 +00:00
if (intent.getAction().equals(SendReceiveService.RECEIVE_SMS_ACTION)) {
2011-12-20 18:20:44 +00:00
handleReceiveMessage(masterSecret, intent);
2013-02-15 03:15:40 +00:00
}
2011-12-20 18:20:44 +00:00
}
}