From 6a9c076dc4e6ed70cdd5e5e410d41e60f85889f0 Mon Sep 17 00:00:00 2001 From: Oliver Wiese <oliver.wiese@fu-berlin.de> Date: Wed, 6 Mar 2019 11:16:22 +0100 Subject: [PATCH] update Mailhandler --- enzevalos_iphone/MailHandler.swift | 104 ++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/enzevalos_iphone/MailHandler.swift b/enzevalos_iphone/MailHandler.swift index 98885e3b..e573b474 100644 --- a/enzevalos_iphone/MailHandler.swift +++ b/enzevalos_iphone/MailHandler.swift @@ -512,6 +512,7 @@ class MailHandler { return } if let parser = data { + _ = self.parseMail(parser: parser, record: record, folderPath: folderPath, uid: UInt64(message.uid), flags: message.flags) } @@ -565,7 +566,6 @@ class MailHandler { } } } - if let _ = header?.extraHeaderValue(forName: Autocrypt.AUTOCRYPTHEADER) { autocrypt = Autocrypt(header: header!) } @@ -583,12 +583,16 @@ class MailHandler { cc.append(r as! MCOAddress) } } + var attachedSignature: Data? // 2. parse body for a in (msgParser.attachments())! { let at = a as! MCOAttachment if at.mimeType == "application/pgp-encrypted" { isEnc = true } + if let signature = MailHandler.extractPGPSignature(attachment: at) { + attachedSignature = signature + } if isEnc && at.mimeType == "application/octet-stream" { msgParser = MCOMessageParser(data: at.data) } @@ -618,7 +622,21 @@ class MailHandler { } } - } else { + } + else if let attachedSig = attachedSignature { + let signedData = MailHandler.extractSignedData(data: msgParser.data()) + let pgp = SwiftPGP() + var keyIds = [String]() + if let sender = header?.from.mailbox { + if let adr = DataHandler.handler.findMailAddress(adr: sender) { + for k in adr.publicKeys { + keyIds.append(k.keyID) + } + } + dec = pgp.verify(data: signedData!, attachedSignature: attachedSig, verifyIds: keyIds, fromAdr: sender) + } + } + else { body = parseBody(msgParser: msgParser) if let chipher = findInlinePGP(text: msgParser.plainTextRendering()) { dec = decryptText(body: chipher, from: header?.from, autocrypt: autocrypt) @@ -650,6 +668,88 @@ class MailHandler { } return nil } + + + func findSignedDataAndSignature(data: Data) -> (signedData: Data?, signature: Data?) { + var sig: Data? + if let parser = MCOMessageParser.init(data: data) { + for part in parser.attachments() { + if let attachment = part as? MCOAttachment, let data = MailHandler.extractPGPSignature(attachment: attachment) { + sig = data + break + } + } + } + + return (MailHandler.extractSignedData(data: data), sig) + } + + private static func matches(for regex: String, in text: String) -> [String] { + do { + let regex = try NSRegularExpression(pattern: regex) + let results = regex.matches(in: text, + range: NSRange(text.startIndex..., in: text)) + return results.map { + String(text[Range($0.range, in: text)!]) + } + } catch { + return [] + } + } + private static func findBoundary(rawMail: String) -> String? { + let boundaries = matches(for: "boundary=.*;", in: rawMail) + if let bound = boundaries.first { + let splitted = bound.split(separator: "\"") + if splitted.count == 3 { + return "--"+String(splitted[1]) as String + } + } + return nil + } + + private static func extractSignedData(data: Data) -> Data? { + if let dataString = String.init(data: data, encoding: .utf8){ + if dataString.contains("Content-Type: multipart/signed") , let boundary = findBoundary(rawMail: dataString) { + var parts = dataString.components(separatedBy: boundary).dropFirst().filter({(s: String) -> Bool in + // We drop pgp signature. + // A messages, where a signed part is signed again, are strange and verification can fail -> What about a response etc? + if s.contains("-----BEGIN PGP SIGNATURE-----") { + return false + } + return true + }) + parts = parts.map({(s: String) -> String in + // Convert strings according to RFC3156. See: https://tools.ietf.org/html/rfc3156 page 6 + var newString = s.trimmed() + newString = newString.replacingOccurrences(of: "\r\n", with: "\n") + newString = newString.replacingOccurrences(of: "\n", with: "\r\n") + // Sometimes tabs got lost?! TEST TODO + newString = newString.replacingOccurrences(of: " charset", with: "\tcharset") + //TODO: Remove -- if last symbol + if newString.hasSuffix("--") { + newString = String(newString.dropLast(2)) + } + return newString + }) + if parts.count == 0 { + return parts.first?.data(using: .utf8) + } + else { + let res = parts.joined(separator: "\r\n") + return res.data(using: .utf8) + } + } + } + return nil + } + + + private static func extractPGPSignature(attachment: MCOAttachment) -> Data? { + if attachment.mimeType == "application/pgp-signature" { + return attachment.data + } + return nil + } private func parseBody(msgParser: MCOMessageParser) -> String { -- GitLab