File indexing completed on 2025-03-09 04:54:29
0001 /* 0002 SPDX-FileCopyrightText: 2019-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "dkimkeyrecord.h" 0008 #include "messageviewer_dkimcheckerdebug.h" 0009 0010 using namespace MessageViewer; 0011 0012 DKIMKeyRecord::DKIMKeyRecord() = default; 0013 0014 bool DKIMKeyRecord::parseKey(const QString &key) 0015 { 0016 qDebug() << " key " << key; 0017 QString newKey = key; 0018 if (newKey.isEmpty()) { 0019 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "Error: trying to parse empty key"; 0020 return false; 0021 } 0022 newKey.replace(QLatin1StringView("; "), QLatin1StringView(";")); 0023 const QStringList items = newKey.split(QLatin1Char(';')); 0024 for (int i = 0; i < items.count(); ++i) { 0025 const QString elem = items.at(i).trimmed(); 0026 if (elem.startsWith(QLatin1StringView("v="))) { 0027 mVersion = elem.right(elem.length() - 2); 0028 } else if (elem.startsWith(QLatin1StringView("h="))) { 0029 // Parse multi array. 0030 mHashAlgorithm = elem.right(elem.length() - 2).split(QLatin1Char(':')); 0031 } else if (elem.startsWith(QLatin1StringView("k="))) { // Key type (rsa by default) 0032 mKeyType = elem.right(elem.length() - 2); 0033 } else if (elem.startsWith(QLatin1StringView("n="))) { // Notes (optional empty by default) 0034 mNote = elem.right(elem.length() - 2); 0035 } else if (elem.startsWith(QLatin1StringView("p="))) { // Public key 0036 mPublicKey = elem.right(elem.length() - 2).remove(QLatin1Char(' ')); 0037 } else if (elem.startsWith(QLatin1StringView("s="))) { // Service Default is "*" 0038 // Service Type (plain-text; OPTIONAL; default is "*"). A colon- 0039 // separated list of service types to which this record applies. 0040 // Verifiers for a given service type MUST ignore this record if the 0041 // appropriate type is not listed. Unrecognized service types MUST 0042 // be ignored. Currently defined service types are as follows: 0043 const QStringList lst = elem.right(elem.length() - 2).split(QLatin1Char(':')); 0044 for (const QString &service : lst) { 0045 if (service == QLatin1Char('*') || service == QLatin1StringView("email")) { 0046 mService = service; 0047 } 0048 } 0049 } else if (elem.startsWith(QLatin1StringView("t="))) { // Flag 0050 // t= Flags, represented as a colon-separated list of names (plain- 0051 // text; OPTIONAL, default is no flags set). Unrecognized flags MUST 0052 // be ignored. The defined flags are as follows: 0053 0054 // y This domain is testing DKIM. Verifiers MUST NOT treat messages 0055 // from Signers in testing mode differently from unsigned email, 0056 // even should the signature fail to verify. Verifiers MAY wish 0057 // to track testing mode results to assist the Signer. 0058 0059 // s Any DKIM-Signature header fields using the "i=" tag MUST have 0060 // the same domain value on the right-hand side of the "@" in the 0061 // "i=" tag and the value of the "d=" tag. That is, the "i=" 0062 // domain MUST NOT be a subdomain of "d=". Use of this flag is 0063 // RECOMMENDED unless subdomaining is required. 0064 mFlags = elem.right(elem.length() - 2).split(QLatin1Char(':')); 0065 } 0066 } 0067 if (mVersion.isEmpty()) { // It's optional 0068 mVersion = QStringLiteral("DKIM1"); 0069 } 0070 if (mKeyType.isEmpty()) { // Rsa by default 0071 mKeyType = QStringLiteral("rsa"); 0072 } 0073 if (mService.isEmpty()) { 0074 mService = QLatin1Char('*'); 0075 } 0076 return true; 0077 } 0078 0079 QString DKIMKeyRecord::version() const 0080 { 0081 return mVersion; 0082 } 0083 0084 void DKIMKeyRecord::setVersion(const QString &version) 0085 { 0086 mVersion = version; 0087 } 0088 0089 QString DKIMKeyRecord::keyType() const 0090 { 0091 return mKeyType; 0092 } 0093 0094 void DKIMKeyRecord::setKeyType(const QString &keyType) 0095 { 0096 mKeyType = keyType; 0097 } 0098 0099 QString DKIMKeyRecord::note() const 0100 { 0101 return mNote; 0102 } 0103 0104 void DKIMKeyRecord::setNote(const QString ¬e) 0105 { 0106 mNote = note; 0107 } 0108 0109 QString DKIMKeyRecord::publicKey() const 0110 { 0111 return mPublicKey; 0112 } 0113 0114 void DKIMKeyRecord::setPublicKey(const QString &publicKey) 0115 { 0116 mPublicKey = publicKey; 0117 } 0118 0119 QString DKIMKeyRecord::service() const 0120 { 0121 return mService; 0122 } 0123 0124 void DKIMKeyRecord::setService(const QString &service) 0125 { 0126 mService = service; 0127 } 0128 0129 QStringList DKIMKeyRecord::flags() const 0130 { 0131 return mFlags; 0132 } 0133 0134 void DKIMKeyRecord::setFlags(const QStringList &flags) 0135 { 0136 mFlags = flags; 0137 } 0138 0139 bool DKIMKeyRecord::operator==(const DKIMKeyRecord &other) const 0140 { 0141 return mVersion == other.version() && mNote == other.note() && mPublicKey == other.publicKey() && mService == other.service() 0142 && mHashAlgorithm == other.hashAlgorithm() && mFlags == other.flags(); 0143 } 0144 0145 QStringList DKIMKeyRecord::hashAlgorithm() const 0146 { 0147 return mHashAlgorithm; 0148 } 0149 0150 void DKIMKeyRecord::setHashAlgorithm(const QStringList &hashAlgorithm) 0151 { 0152 mHashAlgorithm = hashAlgorithm; 0153 } 0154 0155 QDebug operator<<(QDebug d, const DKIMKeyRecord &t) 0156 { 0157 d << "mVersion " << t.version(); 0158 d << "mKeyType " << t.keyType(); 0159 d << "mNote " << t.note(); 0160 d << "mPublicKey " << t.publicKey(); 0161 d << "mService " << t.service(); 0162 d << "mHashAlgorithm " << t.hashAlgorithm(); 0163 d << "mFlags " << t.flags(); 0164 return d; 0165 }