messageview: handling for unsupported multipart/(signed|encrypted)

This commit is contained in:
Vincent Breitmoser 2016-05-23 16:04:58 +02:00
parent e71cff565e
commit 7305a20b8b
2 changed files with 70 additions and 38 deletions

View file

@ -39,7 +39,7 @@ public class MessageDecryptVerifier {
Part part = partsToCheck.pop();
Body body = part.getBody();
if (isPgpMimeEncryptedPart(part)) {
if (isPartMultipartEncrypted(part)) {
encryptedParts.add(part);
} else if (body instanceof Multipart) {
Multipart multipart = (Multipart) body;
@ -62,7 +62,7 @@ public class MessageDecryptVerifier {
Part part = partsToCheck.pop();
Body body = part.getBody();
if (isPgpMimeSignedPart(part)) {
if (isPartMultipartSigned(part)) {
signedParts.add(part);
} else if (body instanceof Multipart) {
Multipart multipart = (Multipart) body;
@ -109,7 +109,7 @@ public class MessageDecryptVerifier {
}
public static byte[] getSignatureData(Part part) throws IOException, MessagingException {
if (isPgpMimeSignedPart(part)) {
if (isPartMultipartSigned(part)) {
Body body = part.getBody();
if (body instanceof Multipart) {
Multipart multi = (Multipart) body;
@ -125,23 +125,23 @@ public class MessageDecryptVerifier {
return null;
}
private static boolean isPgpMimeSignedPart(Part part) {
if (!isSameMimeType(part.getMimeType(), MULTIPART_SIGNED)) {
return false;
}
String contentType = part.getContentType();
String protocol = MimeUtility.getHeaderParameter(contentType, PROTOCOL_PARAMETER);
return APPLICATION_PGP_SIGNATURE.equalsIgnoreCase(protocol);
private static boolean isPartMultipartSigned(Part part) {
return isSameMimeType(part.getMimeType(), MULTIPART_SIGNED);
}
private static boolean isPgpMimeEncryptedPart(Part part) {
if (!isSameMimeType(part.getMimeType(), MULTIPART_ENCRYPTED)) {
return false;
}
private static boolean isPartMultipartEncrypted(Part part) {
return isSameMimeType(part.getMimeType(), MULTIPART_ENCRYPTED);
}
public static boolean isPgpMimeEncryptedOrSignedPart(Part part) {
String contentType = part.getContentType();
String protocol = MimeUtility.getHeaderParameter(contentType, PROTOCOL_PARAMETER);
return APPLICATION_PGP_ENCRYPTED.equalsIgnoreCase(protocol);
String protocolParameter = MimeUtility.getHeaderParameter(contentType, PROTOCOL_PARAMETER);
boolean isPgpEncrypted = isSameMimeType(part.getMimeType(), MULTIPART_ENCRYPTED) &&
APPLICATION_PGP_ENCRYPTED.equalsIgnoreCase(protocolParameter);
boolean isPgpSigned = isSameMimeType(part.getMimeType(), MULTIPART_SIGNED) &&
APPLICATION_PGP_SIGNATURE.equalsIgnoreCase(protocolParameter);
return isPgpEncrypted || isPgpSigned;
}
}

View file

@ -16,6 +16,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.util.Log;
import com.fsck.k9.Account;
@ -29,6 +30,7 @@ import com.fsck.k9.mail.Multipart;
import com.fsck.k9.mail.Part;
import com.fsck.k9.mail.internet.MessageExtractor;
import com.fsck.k9.mail.internet.MimeBodyPart;
import com.fsck.k9.mail.internet.MimeMultipart;
import com.fsck.k9.mail.internet.TextBody;
import com.fsck.k9.mailstore.CryptoResultAnnotation.CryptoError;
import com.fsck.k9.mailstore.DecryptStreamParser;
@ -55,7 +57,6 @@ public class MessageCryptoHelper {
private final Activity activity;
private final MessageCryptoCallback callback;
private final Account account;
private LocalMessage message;
private Deque<CryptoPart> partsToDecryptOrVerify = new ArrayDeque<>();
private OpenPgpApi openPgpApi;
@ -76,19 +77,17 @@ public class MessageCryptoHelper {
}
public void decryptOrVerifyMessagePartsIfNecessary(LocalMessage message) {
this.message = message;
if (!account.isOpenPgpProviderConfigured()) {
returnResultToFragment();
return;
}
List<Part> encryptedParts = MessageDecryptVerifier.findEncryptedParts(message);
processFoundParts(encryptedParts, CryptoPartType.ENCRYPTED, CryptoError.ENCRYPTED_BUT_INCOMPLETE,
processFoundEncryptedParts(encryptedParts,
MessageHelper.createEmptyPart());
List<Part> signedParts = MessageDecryptVerifier.findSignedParts(message);
processFoundParts(signedParts, CryptoPartType.SIGNED, CryptoError.SIGNED_BUT_INCOMPLETE, NO_REPLACEMENT_PART);
processFoundSignedParts(signedParts);
List<Part> inlineParts = MessageDecryptVerifier.findPgpInlineParts(message);
addFoundInlinePgpParts(inlineParts);
@ -96,15 +95,35 @@ public class MessageCryptoHelper {
decryptOrVerifyNextPart();
}
private void processFoundParts(List<Part> foundParts, CryptoPartType cryptoPartType, CryptoError errorIfIncomplete,
MimeBodyPart replacementPart) {
private void processFoundEncryptedParts(List<Part> foundParts, MimeBodyPart replacementPart) {
for (Part part : foundParts) {
if (MessageHelper.isCompletePartAvailable(part)) {
CryptoPart cryptoPart = new CryptoPart(cryptoPartType, part);
partsToDecryptOrVerify.add(cryptoPart);
} else {
addErrorAnnotation(part, errorIfIncomplete, replacementPart);
if (!MessageHelper.isCompletePartAvailable(part)) {
addErrorAnnotation(part, CryptoError.ENCRYPTED_BUT_INCOMPLETE, replacementPart);
continue;
}
if (MessageDecryptVerifier.isPgpMimeEncryptedOrSignedPart(part)) {
CryptoPart cryptoPart = new CryptoPart(CryptoPartType.PGP_ENCRYPTED, part);
partsToDecryptOrVerify.add(cryptoPart);
continue;
}
addErrorAnnotation(part, CryptoError.ENCRYPTED_BUT_UNSUPPORTED, replacementPart);
}
}
private void processFoundSignedParts(List<Part> foundParts) {
for (Part part : foundParts) {
if (!MessageHelper.isCompletePartAvailable(part)) {
MimeBodyPart replacementPart = getMultipartSignedContentPartIfAvailable(part);
addErrorAnnotation(part, CryptoError.SIGNED_BUT_INCOMPLETE, replacementPart);
continue;
}
if (MessageDecryptVerifier.isPgpMimeEncryptedOrSignedPart(part)) {
CryptoPart cryptoPart = new CryptoPart(CryptoPartType.PGP_SIGNED, part);
partsToDecryptOrVerify.add(cryptoPart);
continue;
}
MimeBodyPart replacementPart = getMultipartSignedContentPartIfAvailable(part);
addErrorAnnotation(part, CryptoError.SIGNED_BUT_UNSUPPORTED, replacementPart);
}
}
@ -115,7 +134,7 @@ public class MessageCryptoHelper {
private void addFoundInlinePgpParts(List<Part> foundParts) {
for (Part part : foundParts) {
CryptoPart cryptoPart = new CryptoPart(CryptoPartType.INLINE_PGP, part);
CryptoPart cryptoPart = new CryptoPart(CryptoPartType.PGP_INLINE, part);
partsToDecryptOrVerify.add(cryptoPart);
}
}
@ -176,15 +195,15 @@ public class MessageCryptoHelper {
try {
CryptoPartType cryptoPartType = currentCryptoPart.type;
switch (cryptoPartType) {
case SIGNED: {
case PGP_SIGNED: {
callAsyncDetachedVerify(intent);
return;
}
case ENCRYPTED: {
case PGP_ENCRYPTED: {
callAsyncDecrypt(intent);
return;
}
case INLINE_PGP: {
case PGP_INLINE: {
callAsyncInlineOperation(intent);
return;
}
@ -286,12 +305,12 @@ public class MessageCryptoHelper {
try {
Part part = currentCryptoPart.part;
CryptoPartType cryptoPartType = currentCryptoPart.type;
if (cryptoPartType == CryptoPartType.ENCRYPTED) {
if (cryptoPartType == CryptoPartType.PGP_ENCRYPTED) {
Multipart multipartEncryptedMultipart = (Multipart) part.getBody();
BodyPart encryptionPayloadPart = multipartEncryptedMultipart.getBodyPart(1);
Body encryptionPayloadBody = encryptionPayloadPart.getBody();
encryptionPayloadBody.writeTo(out);
} else if (cryptoPartType == CryptoPartType.INLINE_PGP) {
} else if (cryptoPartType == CryptoPartType.PGP_INLINE) {
String text = MessageExtractor.getTextFromPart(part);
out.write(text.getBytes());
} else {
@ -464,8 +483,21 @@ public class MessageCryptoHelper {
}
private enum CryptoPartType {
INLINE_PGP,
ENCRYPTED,
SIGNED
PGP_INLINE,
PGP_ENCRYPTED,
PGP_SIGNED
}
@Nullable
private static MimeBodyPart getMultipartSignedContentPartIfAvailable(Part part) {
MimeBodyPart replacementPart = NO_REPLACEMENT_PART;
Body body = part.getBody();
if (body instanceof MimeMultipart) {
MimeMultipart multipart = ((MimeMultipart) part.getBody());
if (multipart.getCount() >= 1) {
replacementPart = (MimeBodyPart) multipart.getBodyPart(0);
}
}
return replacementPart;
}
}