File indexing completed on 2025-03-09 04:54:13
0001 /* 0002 SPDX-FileCopyrightText: 2020 Sandro Kanuß <sknauss@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "autocryptutils.h" 0008 0009 #include "autocryptstorage.h" 0010 0011 #include "autocrypt_debug.h" 0012 0013 #include <QHash> 0014 0015 using namespace MessageCore; 0016 0017 HeaderMixupNodeHelper::HeaderMixupNodeHelper(MimeTreeParser::NodeHelper *n, KMime::Content *m) 0018 : message(m) 0019 , mNodeHelper(n) 0020 { 0021 } 0022 0023 QDateTime HeaderMixupNodeHelper::dateHeader() const 0024 { 0025 return mNodeHelper->dateHeader(message); 0026 } 0027 0028 bool HeaderMixupNodeHelper::hasMailHeader(const char *header) const 0029 { 0030 return mNodeHelper->hasMailHeader(header, message); 0031 } 0032 0033 QSharedPointer<KMime::Headers::Generics::AddressList> HeaderMixupNodeHelper::mailHeaderAsAddressList(const char *header) const 0034 { 0035 return mNodeHelper->mailHeaderAsAddressList(header, message); 0036 } 0037 0038 const KMime::Headers::Base *HeaderMixupNodeHelper::mailHeaderAsBase(const char *header) const 0039 { 0040 return mNodeHelper->mailHeaderAsBase(header, message); 0041 } 0042 0043 QList<MimeTreeParser::MessagePart::Ptr> HeaderMixupNodeHelper::messagePartsOfMailHeader(const char *header) const 0044 { 0045 return mNodeHelper->messagePartsOfMailHeader(header, message); 0046 } 0047 0048 QList<KMime::Headers::Base *> HeaderMixupNodeHelper::headers(const char *header) const 0049 { 0050 return mNodeHelper->headers(header, message); 0051 } 0052 0053 QHash<QByteArray, QByteArray> MessageCore::paramsFromAutocryptHeader(const KMime::Headers::Base *const header) 0054 { 0055 QHash<QByteArray, QByteArray> params; 0056 0057 const auto &parts = header->as7BitString(false).split(';'); 0058 for (const auto &part : parts) { 0059 const auto &i = part.split('='); 0060 params[i[0].trimmed()] = i[1].trimmed(); 0061 } 0062 return params; 0063 } 0064 0065 void MessageCore::processAutocryptfromMail(const HeaderMixupNodeHelper &mixup) 0066 { 0067 auto storage = AutocryptStorage::self(); 0068 0069 QByteArray messageid = "<NO Message-ID header>"; 0070 if (mixup.mailHeaderAsBase("Message-ID")) { 0071 messageid = mixup.mailHeaderAsBase("Message-ID")->as7BitString(false); 0072 } 0073 0074 const auto fromAddr = mixup.mailHeaderAsAddressList("from"); 0075 if (fromAddr->addresses().size() != 1) { 0076 qInfo(AUTOCRYPT_LOG) << "Don't update Autocrypt storage, none or multiple From headers found in " << messageid; 0077 return; 0078 } 0079 0080 if (mixup.hasMailHeader("Autocrypt")) { 0081 KMime::Headers::Base *header = nullptr; 0082 int valid = 0; 0083 for (const auto h : mixup.headers("Autocrypt")) { 0084 const auto params = paramsFromAutocryptHeader(h); 0085 if (params.value("addr") != fromAddr->addresses().value(0)) { 0086 continue; 0087 } 0088 bool invalid = false; 0089 for (const auto &key : params.keys()) { 0090 if (key == "addr") { 0091 continue; 0092 } else if (key == "prefer-encrypt") { 0093 continue; 0094 } else if (key == "keydata") { 0095 continue; 0096 } else if (key[0] == '_') { 0097 continue; 0098 } else { 0099 invalid = true; 0100 break; 0101 } 0102 } 0103 if (invalid) { 0104 continue; 0105 } 0106 if (!header) { 0107 header = h; 0108 } 0109 valid++; 0110 } 0111 if (valid == 1) { 0112 const auto params = paramsFromAutocryptHeader(header); 0113 auto recipient = storage->addRecipient(params.value("addr")); 0114 recipient->updateFromMessage(mixup, header); 0115 qInfo(AUTOCRYPT_LOG) << "Update Autocrypt information for " << recipient->addr() << " from " << messageid; 0116 } else { 0117 qInfo(AUTOCRYPT_LOG) << "Don't update Autocrypt storage, because we have multiple valid Autocrypt headers found in " << messageid; 0118 } 0119 } else { 0120 auto recipient = storage->getRecipient(fromAddr->addresses().value(0)); 0121 if (recipient) { 0122 recipient->updateFromMessage(mixup, nullptr); 0123 qInfo(AUTOCRYPT_LOG) << "Update Autocrypt information for " << recipient->addr() << " from " << messageid; 0124 } 0125 } 0126 0127 if (mixup.hasMailHeader("Autocrypt-Gossip")) { 0128 MimeTreeParser::MessagePart::Ptr messagePart(nullptr); 0129 for (const auto &mp : mixup.messagePartsOfMailHeader("Autocrypt-Gossip")) { 0130 if (mp.staticCast<MimeTreeParser::EncryptedMessagePart>()) { 0131 messagePart = mp; 0132 break; 0133 } 0134 } 0135 if (messagePart) { 0136 for (const auto &header : messagePart->headers("Autocrypt-Gossip")) { 0137 const auto params = paramsFromAutocryptHeader(header); 0138 auto recipient = storage->addRecipient(params.value("addr")); 0139 recipient->updateFromGossip(mixup, header); 0140 qInfo(AUTOCRYPT_LOG) << "Update Autocrypt Gossip information for" << recipient->addr() << " from " << messageid; 0141 } 0142 } 0143 } 0144 storage->save(); 0145 }