import keys from autocrypt headers
This commit is contained in:
parent
42bd8683dd
commit
99dea3a466
3 changed files with 53 additions and 15 deletions
|
@ -11,6 +11,7 @@ import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.VisibleForTesting;
|
import android.support.annotation.VisibleForTesting;
|
||||||
|
|
||||||
|
import com.fsck.k9.mail.Message;
|
||||||
import com.fsck.k9.mail.internet.MimeMessage;
|
import com.fsck.k9.mail.internet.MimeMessage;
|
||||||
import com.fsck.k9.mail.internet.MimeUtility;
|
import com.fsck.k9.mail.internet.MimeUtility;
|
||||||
import okio.ByteString;
|
import okio.ByteString;
|
||||||
|
@ -30,7 +31,7 @@ public class AutocryptOperations {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean addAutocryptPeerUpdateToIntentIfPresent(MimeMessage currentMessage, Intent intent) {
|
public boolean addAutocryptPeerUpdateToIntentIfPresent(Message currentMessage, Intent intent) {
|
||||||
AutocryptHeader autocryptHeader = getValidAutocryptHeader(currentMessage);
|
AutocryptHeader autocryptHeader = getValidAutocryptHeader(currentMessage);
|
||||||
if (autocryptHeader == null) {
|
if (autocryptHeader == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -51,7 +52,7 @@ public class AutocryptOperations {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processCleartextMessage(OpenPgpApi openPgpApi, MimeMessage currentMessage) {
|
public void processCleartextMessage(OpenPgpApi openPgpApi, Message currentMessage) {
|
||||||
Intent intent = new Intent(OpenPgpApi.ACTION_UPDATE_AUTOCRYPT_PEER);
|
Intent intent = new Intent(OpenPgpApi.ACTION_UPDATE_AUTOCRYPT_PEER);
|
||||||
boolean hasInlineKeyData = addAutocryptPeerUpdateToIntentIfPresent(currentMessage, intent);
|
boolean hasInlineKeyData = addAutocryptPeerUpdateToIntentIfPresent(currentMessage, intent);
|
||||||
if (hasInlineKeyData) {
|
if (hasInlineKeyData) {
|
||||||
|
@ -61,7 +62,7 @@ public class AutocryptOperations {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
AutocryptHeader getValidAutocryptHeader(MimeMessage currentMessage) {
|
AutocryptHeader getValidAutocryptHeader(Message currentMessage) {
|
||||||
String[] headers = currentMessage.getHeader(AUTOCRYPT_HEADER);
|
String[] headers = currentMessage.getHeader(AUTOCRYPT_HEADER);
|
||||||
ArrayList<AutocryptHeader> autocryptHeaders = parseAllAutocryptHeaders(headers);
|
ArrayList<AutocryptHeader> autocryptHeaders = parseAllAutocryptHeaders(headers);
|
||||||
|
|
||||||
|
@ -126,7 +127,7 @@ public class AutocryptOperations {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAutocryptHeader(MimeMessage currentMessage) {
|
public boolean hasAutocryptHeader(Message currentMessage) {
|
||||||
return currentMessage.getHeader(AUTOCRYPT_HEADER).length > 0;
|
return currentMessage.getHeader(AUTOCRYPT_HEADER).length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,8 @@ import android.content.Intent;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.VisibleForTesting;
|
import android.support.annotation.VisibleForTesting;
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
import com.fsck.k9.Globals;
|
import com.fsck.k9.Globals;
|
||||||
import com.fsck.k9.K9;
|
|
||||||
import com.fsck.k9.activity.compose.ComposeCryptoStatus;
|
import com.fsck.k9.activity.compose.ComposeCryptoStatus;
|
||||||
import com.fsck.k9.mail.Body;
|
import com.fsck.k9.mail.Body;
|
||||||
import com.fsck.k9.mail.BodyPart;
|
import com.fsck.k9.mail.BodyPart;
|
||||||
|
@ -36,6 +34,7 @@ import org.apache.james.mime4j.util.MimeUtil;
|
||||||
import org.openintents.openpgp.OpenPgpError;
|
import org.openintents.openpgp.OpenPgpError;
|
||||||
import org.openintents.openpgp.util.OpenPgpApi;
|
import org.openintents.openpgp.util.OpenPgpApi;
|
||||||
import org.openintents.openpgp.util.OpenPgpApi.OpenPgpDataSource;
|
import org.openintents.openpgp.util.OpenPgpApi.OpenPgpDataSource;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
|
||||||
public class PgpMessageBuilder extends MessageBuilder {
|
public class PgpMessageBuilder extends MessageBuilder {
|
||||||
|
|
|
@ -17,6 +17,9 @@ import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.WorkerThread;
|
import android.support.annotation.WorkerThread;
|
||||||
|
|
||||||
|
import com.fsck.k9.crypto.AutocryptOperations;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
import com.fsck.k9.K9;
|
import com.fsck.k9.K9;
|
||||||
import com.fsck.k9.crypto.MessageDecryptVerifier;
|
import com.fsck.k9.crypto.MessageDecryptVerifier;
|
||||||
import com.fsck.k9.mail.Address;
|
import com.fsck.k9.mail.Address;
|
||||||
|
@ -62,6 +65,7 @@ public class MessageCryptoHelper {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final String openPgpProviderPackage;
|
private final String openPgpProviderPackage;
|
||||||
|
private final AutocryptOperations autocryptOperations;
|
||||||
private final Object callbackLock = new Object();
|
private final Object callbackLock = new Object();
|
||||||
private final Deque<CryptoPart> partsToDecryptOrVerify = new ArrayDeque<>();
|
private final Deque<CryptoPart> partsToDecryptOrVerify = new ArrayDeque<>();
|
||||||
|
|
||||||
|
@ -79,6 +83,7 @@ public class MessageCryptoHelper {
|
||||||
private Intent currentCryptoResult;
|
private Intent currentCryptoResult;
|
||||||
private Intent userInteractionResultIntent;
|
private Intent userInteractionResultIntent;
|
||||||
private boolean secondPassStarted;
|
private boolean secondPassStarted;
|
||||||
|
private boolean thirdPassStarted;
|
||||||
private CancelableBackgroundOperation cancelableBackgroundOperation;
|
private CancelableBackgroundOperation cancelableBackgroundOperation;
|
||||||
private boolean isCancelled;
|
private boolean isCancelled;
|
||||||
|
|
||||||
|
@ -95,6 +100,7 @@ public class MessageCryptoHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.openPgpApiFactory = openPgpApiFactory;
|
this.openPgpApiFactory = openPgpApiFactory;
|
||||||
|
autocryptOperations = new AutocryptOperations();
|
||||||
openPgpProviderPackage = K9.getOpenPgpProvider();
|
openPgpProviderPackage = K9.getOpenPgpProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +131,8 @@ public class MessageCryptoHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runSecondPass() {
|
private void runSecondPass() {
|
||||||
|
secondPassStarted = true;
|
||||||
|
|
||||||
List<Part> signedParts = MessageDecryptVerifier.findSignedParts(currentMessage, messageAnnotations);
|
List<Part> signedParts = MessageDecryptVerifier.findSignedParts(currentMessage, messageAnnotations);
|
||||||
processFoundSignedParts(signedParts);
|
processFoundSignedParts(signedParts);
|
||||||
|
|
||||||
|
@ -134,6 +142,19 @@ public class MessageCryptoHelper {
|
||||||
decryptOrVerifyNextPart();
|
decryptOrVerifyNextPart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void runThirdPass() {
|
||||||
|
thirdPassStarted = true;
|
||||||
|
|
||||||
|
if (messageAnnotations.isEmpty()) {
|
||||||
|
if (autocryptOperations.hasAutocryptHeader(currentMessage)) {
|
||||||
|
CryptoPart cryptoPart = new CryptoPart(CryptoPartType.PLAIN_AUTOCRYPT, currentMessage);
|
||||||
|
partsToDecryptOrVerify.add(cryptoPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptOrVerifyNextPart();
|
||||||
|
}
|
||||||
|
|
||||||
private void processFoundEncryptedParts(List<Part> foundParts) {
|
private void processFoundEncryptedParts(List<Part> foundParts) {
|
||||||
for (Part part : foundParts) {
|
for (Part part : foundParts) {
|
||||||
if (!MessageHelper.isCompletePartAvailable(part)) {
|
if (!MessageHelper.isCompletePartAvailable(part)) {
|
||||||
|
@ -194,7 +215,7 @@ public class MessageCryptoHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (partsToDecryptOrVerify.isEmpty()) {
|
if (partsToDecryptOrVerify.isEmpty()) {
|
||||||
runSecondPassOrReturnResultToFragment();
|
runNextPassOrReturnResultToFragment();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,19 +260,22 @@ public class MessageCryptoHelper {
|
||||||
Intent decryptIntent = userInteractionResultIntent;
|
Intent decryptIntent = userInteractionResultIntent;
|
||||||
userInteractionResultIntent = null;
|
userInteractionResultIntent = null;
|
||||||
if (decryptIntent == null) {
|
if (decryptIntent == null) {
|
||||||
decryptIntent = getDecryptionIntent();
|
decryptIntent = getDecryptVerifyIntent();
|
||||||
}
|
}
|
||||||
decryptVerify(decryptIntent);
|
decryptVerify(decryptIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private Intent getDecryptionIntent() {
|
private Intent getDecryptVerifyIntent() {
|
||||||
Intent decryptIntent = new Intent(OpenPgpApi.ACTION_DECRYPT_VERIFY);
|
Intent decryptIntent = new Intent(OpenPgpApi.ACTION_DECRYPT_VERIFY);
|
||||||
|
|
||||||
Address[] from = currentMessage.getFrom();
|
Address[] from = currentMessage.getFrom();
|
||||||
if (from.length > 0) {
|
if (from.length > 0) {
|
||||||
decryptIntent.putExtra(OpenPgpApi.EXTRA_SENDER_ADDRESS, from[0].getAddress());
|
decryptIntent.putExtra(OpenPgpApi.EXTRA_SENDER_ADDRESS, from[0].getAddress());
|
||||||
|
// we add this here independently of the autocrypt peer update, to allow picking up signing keys as gossip
|
||||||
|
decryptIntent.putExtra(OpenPgpApi.EXTRA_AUTOCRYPT_PEER_ID, from[0].getAddress());
|
||||||
}
|
}
|
||||||
|
autocryptOperations.addAutocryptPeerUpdateToIntentIfPresent(currentMessage, decryptIntent);
|
||||||
|
|
||||||
decryptIntent.putExtra(OpenPgpApi.EXTRA_SUPPORT_OVERRIDE_CRYPTO_WARNING, true);
|
decryptIntent.putExtra(OpenPgpApi.EXTRA_SUPPORT_OVERRIDE_CRYPTO_WARNING, true);
|
||||||
decryptIntent.putExtra(OpenPgpApi.EXTRA_DECRYPTION_RESULT, cachedDecryptionResult);
|
decryptIntent.putExtra(OpenPgpApi.EXTRA_DECRYPTION_RESULT, cachedDecryptionResult);
|
||||||
|
@ -275,6 +299,10 @@ public class MessageCryptoHelper {
|
||||||
callAsyncInlineOperation(intent);
|
callAsyncInlineOperation(intent);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case PLAIN_AUTOCRYPT: {
|
||||||
|
callAsyncParseAutocryptHeaderOperation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalStateException("Unknown crypto part type: " + cryptoPartType);
|
throw new IllegalStateException("Unknown crypto part type: " + cryptoPartType);
|
||||||
|
@ -285,6 +313,12 @@ public class MessageCryptoHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void callAsyncParseAutocryptHeaderOperation() {
|
||||||
|
// TODO make actually async (then callback to onCryptoFinished)
|
||||||
|
autocryptOperations.processCleartextMessage(openPgpApi, (Message) currentCryptoPart.part);
|
||||||
|
onCryptoFinished();
|
||||||
|
}
|
||||||
|
|
||||||
private void callAsyncInlineOperation(Intent intent) throws IOException {
|
private void callAsyncInlineOperation(Intent intent) throws IOException {
|
||||||
OpenPgpDataSource dataSource = getDataSourceForEncryptedOrInlineData();
|
OpenPgpDataSource dataSource = getDataSourceForEncryptedOrInlineData();
|
||||||
OpenPgpDataSink<MimeBodyPart> dataSink = getDataSinkForDecryptedInlineData();
|
OpenPgpDataSink<MimeBodyPart> dataSink = getDataSinkForDecryptedInlineData();
|
||||||
|
@ -600,13 +634,16 @@ public class MessageCryptoHelper {
|
||||||
decryptOrVerifyNextPart();
|
decryptOrVerifyNextPart();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runSecondPassOrReturnResultToFragment() {
|
private void runNextPassOrReturnResultToFragment() {
|
||||||
if (secondPassStarted) {
|
if (!secondPassStarted) {
|
||||||
callbackReturnResult();
|
runSecondPass();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
secondPassStarted = true;
|
if (!thirdPassStarted) {
|
||||||
runSecondPass();
|
runThirdPass();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callbackReturnResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanupAfterProcessingFinished() {
|
private void cleanupAfterProcessingFinished() {
|
||||||
|
@ -699,7 +736,8 @@ public class MessageCryptoHelper {
|
||||||
private enum CryptoPartType {
|
private enum CryptoPartType {
|
||||||
PGP_INLINE,
|
PGP_INLINE,
|
||||||
PGP_ENCRYPTED,
|
PGP_ENCRYPTED,
|
||||||
PGP_SIGNED
|
PGP_SIGNED,
|
||||||
|
PLAIN_AUTOCRYPT
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
Loading…
Reference in a new issue