diff --git a/enzevalos_iphone/Dialog/DialogOption.swift b/enzevalos_iphone/Dialog/DialogOption.swift index ede6f098709b637f4890c2cff71884453f052818..09ae087525eb4732e7bde3e6f29e8e0944961504 100644 --- a/enzevalos_iphone/Dialog/DialogOption.swift +++ b/enzevalos_iphone/Dialog/DialogOption.swift @@ -95,10 +95,8 @@ enum DialogOption: Dialog { case invitationWelcome case invitationStep case invitationHelp - case travelInfo case corrupted case couldNotDecrypt - case couldNotDecryptTravel case encryptedBefore @@ -109,10 +107,8 @@ enum DialogOption: Dialog { case .invitationWelcome : return UIColor.Invitation.orange case .invitationStep : return UIColor.Invitation.orange case .invitationHelp : return UIColor.Invitation.orange - case .travelInfo : return UIColor.Invitation.orange case .corrupted : return ThemeManager.troubleMessageColor() case .couldNotDecrypt : return ThemeManager.unencryptedMessageColor() - case .couldNotDecryptTravel : return ThemeManager.unencryptedMessageColor() case .encryptedBefore : return ThemeManager.unencryptedMessageColor() } } @@ -146,10 +142,8 @@ enum DialogOption: Dialog { return nil } case .invitationStep : return nil - case .travelInfo : return nil case .corrupted : return Image(systemName: "exclamationmark.triangle.fill") case .couldNotDecrypt : return nil - case .couldNotDecryptTravel : return nil case .encryptedBefore : return nil } } @@ -175,13 +169,11 @@ enum DialogOption: Dialog { return UIImage(named: "postcard") } case .invitationStep : return nil - case .travelInfo : return nil - case .corrupted : - let icon = UIImage(systemName: "exclamationmark.triangle.fill")? - .tint(color: self.color) - return icon + case .corrupted : return nil + // TODO let icon = UIImage(systemName: "exclamationmark.triangle.fill")? + // .tint(color: self.color) + // return icon case .couldNotDecrypt : return nil - case .couldNotDecryptTravel : return nil case .encryptedBefore : return nil } @@ -194,10 +186,8 @@ enum DialogOption: Dialog { case .invitationWelcome, .invitationHelp : return nil case .invitationStep : return UIImage(named: "ic_secure_card") - case .travelInfo : return TravelHandler.planeIcon case .corrupted : return nil case .couldNotDecrypt : return nil - case .couldNotDecryptTravel : return nil case .encryptedBefore : return nil } } @@ -211,10 +201,8 @@ enum DialogOption: Dialog { case .invitationWelcome, .invitationHelp : return NSLocalizedString("Invitation.Welcome.Title", comment: "") case .invitationStep : return NSLocalizedString("Invitation.Step.Title", comment: "") - case .travelInfo : return NSLocalizedString("TravelInfo.Title", comment: "") case .corrupted : return NSLocalizedString("corruptedHeadline", comment: "corrupted mail") case .couldNotDecrypt : return NSLocalizedString("couldNotDecryptHeadline", comment: "couldn't decrypt message") - case .couldNotDecryptTravel : return NSLocalizedString("couldNotDecryptTravelHeadline", comment: "couldn't decrypt message") case .encryptedBefore : return NSLocalizedString("encryptedBeforeHeadline", comment: "encrypted by sender before") } } @@ -240,10 +228,8 @@ enum DialogOption: Dialog { return "" } return String(format: NSLocalizedString("Invitation.Code.Message", comment: ""), code) - case .travelInfo : return NSLocalizedString("TravelInfo.Message", comment: "") case .corrupted : return NSLocalizedString("corruptedText", comment: "corrupted mail") case .couldNotDecrypt : return NSLocalizedString("couldNotDecryptText", comment: "couldn't decrypt message") - case .couldNotDecryptTravel : return NSLocalizedString("couldNotDecryptTravelText", comment: "couldn't decrypt message") case .encryptedBefore : return NSLocalizedString("encryptedBeforeText", comment: "encrypted by sender before") } } @@ -261,10 +247,8 @@ enum DialogOption: Dialog { } case .invitationStep : return NSLocalizedString("Invitation.Step.CTA", comment: "") case .invitationHelp : return NSLocalizedString("Done", comment: "") - case .travelInfo : return NSLocalizedString("TravelInfo.Remember", comment: "") case .corrupted : return nil case .couldNotDecrypt : return nil - case .couldNotDecryptTravel : return nil case .encryptedBefore : return nil } } @@ -276,10 +260,8 @@ enum DialogOption: Dialog { case .invitationWelcome : return NSLocalizedString("Invitation.Welcome.Later", comment: "") case .invitationStep : return nil case .invitationHelp : return nil - case .travelInfo : return NSLocalizedString("MoreInformation", comment: "") case .corrupted : return nil case .couldNotDecrypt : return nil - case .couldNotDecryptTravel : return nil case .encryptedBefore : return nil } } @@ -291,10 +273,8 @@ enum DialogOption: Dialog { case .invitationWelcome : return NSLocalizedString("Invitation.Welcome.Dont.Ask", comment: "") case .invitationStep : return NSLocalizedString("Invitation.Step.Undo", comment: "") case .invitationHelp : return nil - case .travelInfo : return NSLocalizedString("OK", comment: "") case .corrupted : return nil case .couldNotDecrypt : return nil - case .couldNotDecryptTravel : return nil case .encryptedBefore : return nil } } diff --git a/enzevalos_iphone/MailHandler.swift b/enzevalos_iphone/MailHandler.swift index 5522d22cfd540cea4feb7715fc2c7317bed3f724..179dc93b464b71427138dc6981c2ba8b0458c734 100644 --- a/enzevalos_iphone/MailHandler.swift +++ b/enzevalos_iphone/MailHandler.swift @@ -45,14 +45,18 @@ fileprivate func > <T : Comparable>(lhs: T?, rhs: T?) -> Bool { return rhs < lhs } } + + enum SendViewMailSecurityState { + case letter + case postcard + } class MailHandler { private static let MAXMAILS = 25 - private static let extraHeaders = Autocrypt.EXTRAHEADERS + [TravelHandler.backupHeader] + private static let extraHeaders = Autocrypt.EXTRAHEADERS private let dataProvider = PersitentDataProvider() - var delegate: MailHandlerDelegator? static var INBOX: String { return UserManager.backendInboxFolderPath } @@ -567,335 +571,6 @@ class MailHandler { } } - /* - public func getRepeals(for keyID: String) -> [Repeal] { - let mails = DataHandler.handler.allMailsInFolder(key: keyID, contact: nil, folder: DataHandler.handler.findFolder(with: TravelHandler.keyManagementFolder), isSecure: true) - var repeals: [Repeal] = [] - for mail in mails { - if let repeal = getRepeal(from: mail) { - repeals.append(repeal) - } - } - return repeals - } - - private func getRepeal(from mail: PersistentMail) -> Repeal? { - if let encryptedBody = mail.encryptedBody, let mco = MCOAddress(mailbox: mail.from.mailAddress), let dec = decryptText(body: encryptedBody, from: mco, autocrypt: nil) { - if let msgParser = MCOMessageParser(data: dec.decryptedData), let html = msgParser.plainTextBodyRenderingAndStripWhitespace(false) { - - var repealAttachments = Set<TempAttachment>() - let lineArray = html.components(separatedBy: "\n") - var body = lineArray.joined(separator: "\n") - body = body.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - body.append("\n") - let readableAttachments = parseUserReadableAttachments(parser: msgParser, sentEncrypted: true) - for at in readableAttachments { - at.encState = (dec.encryptionState) - at.sigState = dec.signatureState - } - repealAttachments = readableAttachments.filter({$0.mimeType == .travelRepeal}) - - let encState: EncryptionState = dec.encryptionState - let signState: SignatureState = dec.signatureState - - if let repealAttachment = repealAttachments.first, (encState == .ValidedEncryptedWithCurrentKey || encState == .ValidEncryptedWithOldKey) && signState == .ValidSignature , let signKeyID = dec.signKey, let signKey = DataHandler.handler.findKey(keyID: signKeyID), let fingerprint = signKey.fingerprint { - let repeal = Repeal(fingerprint: fingerprint, secret: String(data: repealAttachment.data, encoding: .utf8)!, date: mail.date) - return repeal - } - } - } - return nil - } - - private func getCallForUse(from attachment: TempAttachment, date: Date) -> CallForUse? { - let content = String(data: attachment.data, encoding: .utf8) - if let components = content?.components(separatedBy: "\n"), components.count >= 2 { - let secret = String(components[0].dropFirst(TravelHandler.callForUseSecretHeader.count)) - let fingerprint = String(components[1].dropFirst(TravelHandler.callForUseFingerprintHeader.count)) - return CallForUse(fingerprint: fingerprint, secret: secret, date: date) - } - return nil - } - - public func decrypt(mail: PersistentMail) { - if let encryptedBody = mail.encryptedBody, let mco = MCOAddress(mailbox: mail.from.mailAddress), let dec = decryptText(body: encryptedBody, from: mco, autocrypt: nil) { - if let msgParser = MCOMessageParser(data: dec.decryptedData), let html = msgParser.plainTextBodyRenderingAndStripWhitespace(false) { - - var newKeyIds: [String] = [] - var newSecretKeyIds: [String] = [] - var callForRepealMail = false - var callForUseMail = false - var repealsKey: PersistentKey? = nil - var validCallForUse = false - var misstrustNewKey = false - var moveToFolderPath: String? = nil - let lineArray = html.components(separatedBy: "\n") - var body = lineArray.joined(separator: "\n") - body = body.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - body.append("\n") - var readableAttachments = parseUserReadableAttachments(parser: msgParser, sentEncrypted: true) - for at in readableAttachments { - at.encState = (dec.encryptionState) - at.sigState = dec.signatureState - } - let useAttachments = readableAttachments.filter({$0.mimeType == .travelUse}) - callForRepealMail = readableAttachments.filter({$0.mimeType == .travelRepeal}).count > 0 - callForUseMail = !callForRepealMail && useAttachments.count > 0 - //TODO: handle publickeys in case of callForUse - let travelMail = callForRepealMail || callForUseMail - if travelMail { - mail.storeEncrypted = true - moveToFolderPath = TravelHandler.keyManagementFolder - readableAttachments = Set<TempAttachment>() - - if callForUseMail, let useAttachment = useAttachments.first, let cfu = getCallForUse(from: useAttachment, date: mail.date), cfu.fingerprint.count > 16 { - let repealedKeyID = String(cfu.fingerprint.dropFirst(cfu.fingerprint.count-16)) - if let repealedKey = DataHandler.handler.findKey(keyID: repealedKeyID), repealedKey.repealed && repealedKey.currentlyActiveKey.lastSeen ?? mail.date <= cfu.date { - var repeals = getRepeals(for: repealedKeyID) - repeals = repeals.filter({$0.fingerprint == cfu.fingerprint}) - repeals = repeals.filter({$0.date <= cfu.date}) - if let first = repeals.first { - var maxRepeal = first - for repeal in repeals { - if repeal.date > maxRepeal.date { - maxRepeal = repeal - } - } - if maxRepeal.secret == cfu.secret && !repealedKey.failedCallForUse { - validCallForUse = true - newKeyIds = [] - repealsKey = repealedKey - for a in (msgParser.attachments())! { - let at = a as! MCOAttachment - newKeyIds.append(contentsOf: parsePublicKeys(attachment: at)) - } - } else { - if maxRepeal.secret != cfu.secret && !repealedKey.failedCallForUse { - misstrustNewKey = true - } - repealedKey.failedCallForUse = true - } - } - } - } - if callForUseMail && !validCallForUse { - newKeyIds = [] - for a in (msgParser.attachments())! { - let at = a as! MCOAttachment - newKeyIds.append(contentsOf: parsePublicKeys(attachment: at)) - } - } - - } else { - for at in readableAttachments { - at.encState = dec.encryptionState - at.sigState = dec.signatureState - } - //TODO: add readable attachments to mail here - for a in (msgParser.attachments())! { - let at = a as! MCOAttachment - newKeyIds.append(contentsOf: parsePublicKeys(attachment: at)) - if let sks = parseSecretKey(attachment: at) { - newSecretKeyIds.append(contentsOf: sks) - } - } - for keyId in newKeyIds { - _ = DataHandler.handler.newPublicKey(keyID: keyId, cryptoType: CryptoScheme.PGP, adr: mail.from.mailAddress, autocrypt: false, firstMail: mail, transferType: nil) - } - newKeyIds = [] - for keyID in newSecretKeyIds { - _ = DataHandler.handler.newSecretKey(keyID: keyID, addPk: false) - } - } - //attention: if mail.storeEncrypted == true we have to reencrypt this mail again - mail.body = body - - let encState: EncryptionState = dec.encryptionState - let signState: SignatureState = dec.signatureState - - switch encState { - case EncryptionState.NoEncryption: - mail.isEncrypted = false - mail.trouble = false - mail.unableToDecrypt = false - case EncryptionState.UnableToDecrypt: - mail.unableToDecrypt = true - mail.isEncrypted = true - mail.trouble = false - case EncryptionState.ValidEncryptedWithOldKey: - mail.isEncrypted = true - mail.trouble = false - mail.unableToDecrypt = false - mail.decryptedBody = body - mail.decryptedWithOldPrivateKey = true - case EncryptionState.ValidedEncryptedWithCurrentKey: - mail.isEncrypted = true - mail.trouble = false - mail.unableToDecrypt = false - mail.decryptedBody = body - } - - switch signState { - case SignatureState.NoSignature: - mail.isSigned = false - case SignatureState.NoPublicKey: - mail.isSigned = true - mail.isCorrectlySigned = false - case SignatureState.InvalidSignature: - mail.isSigned = true - mail.isCorrectlySigned = false - mail.trouble = true - case SignatureState.ValidSignature: - mail.isCorrectlySigned = true - mail.isSigned = true - if let signedKey = DataHandler.handler.findKey(keyID: dec.signKey!) { - mail.signedKey = signedKey - mail.keyID = signedKey.keyID - if let lastSeen = signedKey.currentlyActiveKey.lastSeen, lastSeen < mail.date { - signedKey.currentlyActiveKey = signedKey - signedKey.lastSeen = lastSeen - let repeals = AppDelegate.getAppDelegate().mailHandler.getRepeals(for: signedKey.keyID) - if signedKey.repealed, let first = repeals.first { - var maxRepeal = first - for repeal in repeals { - if repeal.date > maxRepeal.date && repeal.date <= Date.init() { - maxRepeal = repeal - } - } - if maxRepeal.date < mail.date { - signedKey.repealed = false - } - } - } - } - else { - mail.signedKey = DataHandler.handler.newPublicKey(keyID: dec.signKey!, cryptoType: dec.encType, adr: dec.signedAdrs.first!, autocrypt: false, firstMail: mail, newGenerated: false, transferType: nil) - } - } - //TODO: we should delete this mail, if it is a callForRepeal and its date is in the future - if callForRepealMail, mail.isSecure, let signKeyID = dec.signKey, let signKey = DataHandler.handler.findKey(keyID: signKeyID) { - if let keyDate = signKey.currentlyActiveKey.lastSeen { - if keyDate <= mail.date && mail.date <= Date.init() { - signKey.currentlyActiveKey = signKey - signKey.lastSeen = mail.date - signKey.repealed = true - } - } else { - signKey.currentlyActiveKey = signKey - signKey.lastSeen = mail.date - signKey.repealed = true - } - } - for keyId in newKeyIds { - let newKey = DataHandler.handler.newPublicKey(keyID: keyId, cryptoType: CryptoScheme.PGP, adr: mail.from.mailAddress, autocrypt: false, firstMail: mail, transferType: nil) - if misstrustNewKey { - newKey.misstrust = true - } - if validCallForUse, let repealedKey = repealsKey { - repealedKey.repealed = false - repealedKey.addChild(child: newKey) - //TODO: should we allow to add more than one key? - } - } - if let moveToFolderPath = moveToFolderPath, moveToFolderPath != mail.folder.path { - move(mails: [mail], from: mail.folder.path, to: moveToFolderPath) - } - } - } - } - - public func reencrypt(mail: PersistentMail) { - if mail.isEncrypted { - mail.body = nil - mail.decryptedBody = nil - if let attachments = mail.attachments { - mail.attachments = NSSet(array: attachments.filter({ - if let attachment = $0 as? Attachment { - return attachment.encryptionState <= 0 - } - return false - })) - } - } - } - - private func parseUserReadableAttachments(parser: MCOMessageParser, sentEncrypted: Bool = false) -> Set<TempAttachment> { - var attachments = Set<TempAttachment>() - for at in parser.attachments() { - if let attachment = at as? MCOAttachment, let mimetype = MIMETYPE.findMIMETYPE(attachment: attachment) { - if (mimetype == .travelUse || mimetype == .travelRepeal) && !sentEncrypted { - continue - } - attachments.insert(TempAttachment(name: attachment.filename, data: attachment.data, mimeType: mimetype)) - } - } - return attachments - } - - private func parsePublicKeys(attachment: MCOAttachment) -> [String] { - var newKey = [String]() - if let content = attachment.decodedString() { - if content.contains("-----BEGIN PGP PUBLIC KEY BLOCK-----") { - if let start = content.range(of: "-----BEGIN PGP PUBLIC KEY BLOCK-----") { - if let end = content.range(of: "-----END PGP PUBLIC KEY BLOCK-----\n") { - let s = start.lowerBound - let e = end.upperBound - let pk = content[s..<e] - let pgp = SwiftPGP() - if let keyId = try? pgp.importKeys(key: String(pk), pw: nil, isSecretKey: false, autocrypt: false) { - newKey.append(contentsOf: keyId) - } - } - } - } - } else if attachment.mimeType == "application/octet-stream", let content = String(data: attachment.data, encoding: String.Encoding.utf8), content.hasPrefix("-----BEGIN PGP PUBLIC KEY BLOCK-----") && (content.hasSuffix("-----END PGP PUBLIC KEY BLOCK-----") || content.hasSuffix("-----END PGP PUBLIC KEY BLOCK-----\n")) { - let pgp = SwiftPGP() - if let keyId = try? pgp.importKeys(key: content, pw: nil, isSecretKey: false, autocrypt: false) { - newKey.append(contentsOf: keyId) - } - } else if attachment.mimeType == "application/pgp-keys" { - let pgp = SwiftPGP() - if let keyIds = try? pgp.importKeys(data: attachment.data, pw: nil, secret: false) { - newKey.append(contentsOf: keyIds) - } - } - return newKey - } - - private func parseSecretKey(attachment: MCOAttachment) -> [String]? { - return nil - } - - private func decryptText(body: String, from: MCOAddress?, autocrypt: Autocrypt?) -> CryptoObject? { - var sender: String? = nil - if let fromMCO = from { - sender = fromMCO.mailbox - } - if let data = body.data(using: .utf8) { - let pgp = SwiftPGP() - var keyIds = [String]() - if sender != nil, let adr = DataHandler.handler.findMailAddress(adr: sender!) { - for k in adr.publicKeys { - keyIds.append(k.keyID) - } - } - if let a = autocrypt { - if let key = try? pgp.importKeys(key: a.key, pw: nil, isSecretKey: false, autocrypt: true) { - keyIds.append(contentsOf: key) - } - } - let secretkeys = DataHandler.handler.findSecretKeys() - var decIds = [String]() - for sk in secretkeys { - decIds.append(sk.keyID) - } - - return pgp.decrypt(data: data, decKeyIDs: decIds, signatureIDs: keyIds, fromAddr: sender ?? "") - } - - return nil - } - */ func move(mails: [MailRecord], from: String, to: String, folderCreated: Bool = false) { guard IMAPSession != nil else { diff --git a/enzevalos_iphone/OutgoingMail.swift b/enzevalos_iphone/OutgoingMail.swift index 5e2ce83ced1d3a6c59d5c3aed5851bd11656fec4..975fd61e95268bf4c3005969a19f9a3876c3df41 100644 --- a/enzevalos_iphone/OutgoingMail.swift +++ b/enzevalos_iphone/OutgoingMail.swift @@ -409,27 +409,6 @@ class OutgoingMail { mail.inviteMail = true return mail } - static func createTravelRepeal(addr: String, sharedSecret: String) -> OutgoingMail { - let mail = OutgoingMail(toEntrys: [addr], ccEntrys: [], bccEntrys: [], subject: "Travel Message", textContent: "", htmlContent: nil) - let bodyText = "You are receiving this message, because the keypair it is signed with will soon be (temporary) disabled by its owner. The owner will be unable to decrypt messages encrypted with the keypair.\nTo be able to communicate securely after the keypair is disabled, you will receive a second message with a new keypair attached. To enable you to trust the new key at the same level as you do for the current key, a secret is attached in the end of this message (see SECRET). The message introducing the new keypair will have a secret attached too. ONLY if both secrets are equal AND there were no other messages introducing new keypairs in the meanwhile you can trust the new keypair!\n\nPlease do not send a message using the current keypair anymore, since it is decativated now.\n\nFor more information visit: "+TravelHandler.website+"\n\nThis Message was automatically generated by my Letterbox email client.\n\nSECRET:\n" - mail.addTextAttachment(text: bodyText+sharedSecret) - mail.addAttachment(filename: "repeal.txt", mimeType: MIMETYPE.travelRepeal.rawValue, charset: "UTF-8", data: sharedSecret.data(using: .utf8)!) - - return mail - } - //TODO: @jabo callForUse - static func createTravelCallForUse(addr: String, sharedSecret: String, pubKey: String, keyID: String, repealedKeyFingerprint: String) -> OutgoingMail { - let mail = OutgoingMail(toEntrys: [addr], ccEntrys: [], bccEntrys: [], subject: "Travel Message", textContent: "", htmlContent: nil) - //do not use autocrypt to be able to parse new key as related to the prevoius one - mail.autocrypt = false - let bodyText = "This message introduces the senders new keypair. You can trust this key in the same level as you did with the last valid key if and ONLY IF the attached secret (see SECRET) matches with the secret attached to the previous 'Travel Message' asking to repeal the senders keypair.\n\nFor more information visit: "+TravelHandler.website+"\n\nThis Message was automatically generated by my Letterbox email client.\n\nSECRET:\n"+sharedSecret - mail.addTextAttachment(text: pubKey) - mail.addTextAttachment(text: bodyText) - mail.addAttachment(filename: "callForUse.txt", mimeType: MIMETYPE.travelUse.rawValue, charset: "UTF-8", data: (TravelHandler.callForUseSecretHeader+sharedSecret+"\n"+TravelHandler.callForUseFingerprintHeader+repealedKeyFingerprint).data(using: .utf8)!) - mail.addAttachment(filename: keyID+".asc.asc", mimeType: "application/pgp-keys", charset: "UTF-8", data: pubKey.data(using: .utf8)!) - - return mail - } static func createSecretKeyExportMail(keyID: String, keyData: String) -> OutgoingMail{ let useraddr = (UserManager.loadUserValue(Attribute.userAddr) as! String) diff --git a/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift b/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift index 9e87a13fa2eb99d1cdc0fc0149f133cee3528150..7e03ea49a2ebc2fe949c42986396f9dac669a6dc 100644 --- a/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift +++ b/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift @@ -116,7 +116,7 @@ protocol DisplayMail { extension DisplayMail { /* TODO: MORE DIALOGS - //else if (mail.isNewPubKey) && !(mail.deleteWhileTravel){} + //else if (mail.isNewPubKey) {} // message contained new public key */ diff --git a/enzevalos_iphone/TempAttachment.swift b/enzevalos_iphone/TempAttachment.swift index 2877cc85f90bab9cf8fde6a8692fc4dbf4ad58fe..9b8acbdd57692027c3f31cfa1a1ca0c9d3e181e7 100644 --- a/enzevalos_iphone/TempAttachment.swift +++ b/enzevalos_iphone/TempAttachment.swift @@ -54,7 +54,7 @@ class TempAttachment: Hashable { self.sigState = sigState } - func store(mail: PersistentMail) { + func store(mail: MailRecord) { } diff --git a/enzevalos_iphone/mail/IncomingMail.swift b/enzevalos_iphone/mail/IncomingMail.swift index 1b34959289e33506ce307d554340b9ea672547cb..12fc5c6d1ff3e91dc2c480dc3d1e85d3bbd07364 100644 --- a/enzevalos_iphone/mail/IncomingMail.swift +++ b/enzevalos_iphone/mail/IncomingMail.swift @@ -188,16 +188,9 @@ class IncomingMail { private var newAutocrypPublicKeys: [String] = [] private var newSecretKeyIDs: [String]? = [] - // Travel info private var readableAttachments = Set<TempAttachment>() - private var repealAttachments = Set<TempAttachment>() private var useAttachments = Set<TempAttachment>() - private var travelMail = false - private var callForRepealMail = false - private var callForUseMail = false - private var validCallForUse = false - private var misstrustNewKey = false - private var repealsKey: PersistentKey? = nil + // Crypto info @@ -348,9 +341,7 @@ class IncomingMail { callForUseMail = !callForRepealMail && useAttachments.count > 0 travelMail = callForRepealMail || callForUseMail } - if travelMail { - publicKeyRaw = parseTravelMail() - } + readableAttachments=parseUserReadableAttachments(parser: msgParser) @@ -455,129 +446,6 @@ class IncomingMail { secretKeys.append(contentsOf: secretKeyRaw) } - private func parseTravelMail() -> [String] { - var newKeysRaw: [String] = [] - storeEncrypted = true - moveToFolderPath = TravelHandler.keyManagementFolder - readableAttachments = Set<TempAttachment>() - if callForUseMail, let useAttachment = useAttachments.first, let cfu = getCallForUse(from: useAttachment, date: date), cfu.fingerprint.count > 16 { - let repealedKeyID = String(cfu.fingerprint.dropFirst(cfu.fingerprint.count-16)) - if let repealedKey = DataHandler.handler.findKey(keyID: repealedKeyID), repealedKey.repealed && repealedKey.currentlyActiveKey.lastSeen ?? date <= cfu.date { - var repeals = getRepeals(for: repealedKeyID) - repeals = repeals.filter({$0.fingerprint == cfu.fingerprint}) - repeals = repeals.filter({$0.date <= cfu.date}) - if let first = repeals.first { - var maxRepeal = first - for repeal in repeals { - if repeal.date > maxRepeal.date { - maxRepeal = repeal - } - } - if maxRepeal.secret == cfu.secret && !repealedKey.failedCallForUse { - validCallForUse = true - newKeysRaw = [] - repealsKey = repealedKey - for a in (msgParser.attachments())! { - let at = a as! MCOAttachment - newKeysRaw.append(contentsOf: IncomingMail.findPublicKeys(attachment: at)) - } - } else { - if maxRepeal.secret != cfu.secret && !repealedKey.failedCallForUse { - misstrustNewKey = true - } - repealedKey.failedCallForUse = true - } - } - } - } - if callForUseMail && !validCallForUse { - newKeysRaw = [] - for a in (msgParser.attachments())! { - let at = a as! MCOAttachment - newKeysRaw.append(contentsOf: IncomingMail.findPublicKeys(attachment: at)) - } - } - return newKeysRaw - } - - public func getRepeals(for keyID: String) -> [Repeal] { - let mails = DataHandler.handler.allMailsInFolder(key: keyID, contact: nil, folder: DataHandler.handler.findFolder(with: TravelHandler.keyManagementFolder), isSecure: true) - var repeals: [Repeal] = [] - for mail in mails { - if let repeal = getRepeal(from: mail) { - repeals.append(repeal) - } - } - return repeals - } - - private func getRepeal(from mail: PersistentMail) -> Repeal? { - if let encryptedBody = mail.encryptedBody, let mco = MCOAddress(mailbox: mail.from.mailAddress), let dec = decryptText(body: encryptedBody, from: mco, autocrypt: nil) { - if let msgParser = MCOMessageParser(data: dec.decryptedData), let html = msgParser.plainTextBodyRenderingAndStripWhitespace(false) { - - var repealAttachments = Set<TempAttachment>() - let lineArray = html.components(separatedBy: "\n") - var body = lineArray.joined(separator: "\n") - body = body.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - body.append("\n") - let readableAttachments = parseUserReadableAttachments(parser: msgParser, sentEncrypted: true) - for at in readableAttachments { - at.encState = (dec.encryptionState) - at.sigState = dec.signatureState - } - repealAttachments = readableAttachments.filter({$0.mimeType == .travelRepeal}) - - let encState: EncryptionState = dec.encryptionState - let signState: SignatureState = dec.signatureState - - if let repealAttachment = repealAttachments.first, (encState == .ValidedEncryptedWithCurrentKey || encState == .ValidEncryptedWithOldKey) && signState == .ValidSignature , let signKeyID = dec.signKey, let signKey = DataHandler.handler.findKey(keyID: signKeyID), let fingerprint = signKey.fingerprint { - let repeal = Repeal(fingerprint: fingerprint, secret: String(data: repealAttachment.data, encoding: .utf8)!, date: mail.date) - return repeal - } - } - } - return nil - } - - private func decryptText(body: String, from: MCOAddress?, autocrypt: Autocrypt?) -> CryptoObject? { - var sender: String? = nil - if let fromMCO = from { - sender = fromMCO.mailbox - } - if let data = body.data(using: .utf8) { - let pgp = SwiftPGP() - var keyIds = [String]() - if sender != nil, let adr = DataHandler.handler.findMailAddress(adr: sender!) { - for k in adr.publicKeys { - keyIds.append(k.keyID) - } - } - if let a = autocrypt { - if let key = try? pgp.importKeys(key: a.key, pw: nil, isSecretKey: false, autocrypt: true) { - keyIds.append(contentsOf: key) - } - } - let secretkeys = DataHandler.handler.findSecretKeys() - var decIds = [String]() - for sk in secretkeys { - decIds.append(sk.keyID ) - } - - return pgp.decrypt(data: data, decKeyIDs: decIds, signatureIDs: keyIds, fromAddr: sender ?? "") - } - - return nil - } - - private func getCallForUse(from attachment: TempAttachment, date: Date) -> CallForUse? { - let content = String(data: attachment.data, encoding: .utf8) - if let components = content?.components(separatedBy: "\n"), components.count >= 2 { - let secret = String(components[0].dropFirst(TravelHandler.callForUseSecretHeader.count)) - let fingerprint = String(components[1].dropFirst(TravelHandler.callForUseFingerprintHeader.count)) - return CallForUse(fingerprint: fingerprint, secret: secret, date: date) - } - return nil - } private func mergeCryptoObject(newCryptoObj: CryptoObject) { if let oldCrypto = cryptoObj { @@ -677,16 +545,6 @@ class IncomingMail { } } - if let _ = header.extraHeaderValue(forName: TravelHandler.backupHeader) { - storeEncrypted = true - moveToFolderPath = TravelHandler.backupFolder - } - - if let _ = header.extraHeaderValue(forName: Autocrypt.SETUPMESSAGE) { - // TODO: Distinguish between other keys (future work) - // moveToFolderPath = TravelHandler.backupFolder - } - if let f = header.from { from = f }