File indexing completed on 2025-03-09 04:54:29

0001 /*
0002    SPDX-FileCopyrightText: 2018-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "messageviewer_export.h"
0010 #include <KMime/Message>
0011 #include <MessageViewer/DKIMCheckPolicy>
0012 #include <MessageViewer/DKIMHeaderParser>
0013 #include <MessageViewer/DKIMInfo>
0014 #include <MessageViewer/DKIMKeyRecord>
0015 #include <QObject>
0016 
0017 namespace MessageViewer
0018 {
0019 /**
0020  * @brief The DKIMCheckSignatureJob class
0021  * @author Laurent Montel <montel@kde.org>
0022  */
0023 class MESSAGEVIEWER_EXPORT DKIMCheckSignatureJob : public QObject
0024 {
0025     Q_OBJECT
0026 public:
0027     enum class DKIMStatus : int {
0028         Unknown = 0,
0029         Valid = 1,
0030         Invalid = 2,
0031         EmailNotSigned = 3,
0032         NeedToBeSigned = 4,
0033     };
0034     Q_ENUM(DKIMStatus)
0035 
0036     enum class DKIMError : int {
0037         Any = 0,
0038         CorruptedBodyHash = 1,
0039         DomainNotExist = 2,
0040         MissingFrom = 3,
0041         MissingSignature = 4,
0042         InvalidQueryMethod = 5,
0043         InvalidHeaderCanonicalization = 6,
0044         InvalidBodyCanonicalization = 7,
0045         InvalidBodyHashAlgorithm = 8,
0046         InvalidSignAlgorithm = 9,
0047         PublicKeyWasRevoked = 10,
0048         SignatureTooLarge = 11,
0049         InsupportedHashAlgorithm = 12,
0050         PublicKeyTooSmall = 13,
0051         ImpossibleToVerifySignature = 14,
0052         DomainI = 15,
0053         TestKeyMode = 16,
0054         ImpossibleToDownloadKey = 17,
0055         HashAlgorithmUnsafeSha1 = 18,
0056         IDomainError = 19,
0057         PublicKeyConversionError = 20,
0058     };
0059     Q_ENUM(DKIMError)
0060     enum class DKIMWarning : int {
0061         Any = 0,
0062         SignatureExpired = 1,
0063         SignatureCreatedInFuture = 2,
0064         SignatureTooSmall = 3,
0065         HashAlgorithmUnsafe = 4,
0066         PublicRsaKeyTooSmall = 5,
0067     };
0068     Q_ENUM(DKIMWarning)
0069 
0070     enum class AuthenticationMethod : int {
0071         Unknown = 0,
0072         Dkim = 1,
0073         Spf = 2,
0074         Dmarc = 3,
0075         Dkimatps = 4,
0076         Auth = 5,
0077     };
0078     Q_ENUM(AuthenticationMethod)
0079 
0080     struct MESSAGEVIEWER_EXPORT DKIMCheckSignatureAuthenticationResult {
0081         QString errorStr;
0082         QString infoResult;
0083         AuthenticationMethod method = AuthenticationMethod::Unknown;
0084         DKIMCheckSignatureJob::DKIMStatus status = DKIMCheckSignatureJob::DKIMStatus::Unknown;
0085         QString sdid; // Signing Domain Identifier
0086         QString auid; // DKIM MAY optionally provide a single responsible Agent or User Identifier (AUID).
0087         [[nodiscard]] bool operator==(const DKIMCheckSignatureAuthenticationResult &other) const;
0088         [[nodiscard]] bool isValid() const;
0089     };
0090 
0091     struct MESSAGEVIEWER_EXPORT CheckSignatureResult {
0092         [[nodiscard]] bool isValid() const;
0093 
0094         [[nodiscard]] bool operator==(const CheckSignatureResult &other) const;
0095 
0096         [[nodiscard]] bool operator!=(const CheckSignatureResult &other) const;
0097 
0098         DKIMCheckSignatureJob::DKIMError error = DKIMCheckSignatureJob::DKIMError::Any;
0099         DKIMCheckSignatureJob::DKIMWarning warning = DKIMCheckSignatureJob::DKIMWarning::Any;
0100         DKIMCheckSignatureJob::DKIMStatus status = DKIMCheckSignatureJob::DKIMStatus::Unknown;
0101         QString sdid; // Signing Domain Identifier
0102         QString auid; // DKIM MAY optionally provide a single responsible Agent or User Identifier (AUID).
0103         QString fromEmail;
0104 
0105         QList<DKIMCheckSignatureAuthenticationResult> listSignatureAuthenticationResult;
0106     };
0107 
0108     explicit DKIMCheckSignatureJob(QObject *parent = nullptr);
0109     ~DKIMCheckSignatureJob() override;
0110     void start();
0111 
0112     [[nodiscard]] QString dkimValue() const;
0113 
0114     [[nodiscard]] DKIMCheckSignatureJob::DKIMStatus status() const;
0115     void setStatus(MessageViewer::DKIMCheckSignatureJob::DKIMStatus status);
0116 
0117     [[nodiscard]] MessageViewer::DKIMCheckSignatureJob::DKIMStatus checkSignature(const MessageViewer::DKIMInfo &info);
0118 
0119     [[nodiscard]] DKIMCheckSignatureJob::DKIMError error() const;
0120 
0121     [[nodiscard]] KMime::Message::Ptr message() const;
0122     void setMessage(const KMime::Message::Ptr &message);
0123 
0124     [[nodiscard]] DKIMCheckSignatureJob::DKIMWarning warning() const;
0125     void setWarning(MessageViewer::DKIMCheckSignatureJob::DKIMWarning warning);
0126 
0127     [[nodiscard]] QString headerCanonizationResult() const;
0128 
0129     [[nodiscard]] QString bodyCanonizationResult() const;
0130 
0131     [[nodiscard]] DKIMCheckPolicy policy() const;
0132     void setPolicy(const DKIMCheckPolicy &policy);
0133 
0134     void setHeaderParser(const DKIMHeaderParser &headerParser);
0135 
0136     void setCheckSignatureAuthenticationResult(const QList<DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult> &lst);
0137 
0138 Q_SIGNALS:
0139     void result(const MessageViewer::DKIMCheckSignatureJob::CheckSignatureResult &checkResult);
0140     void storeKey(const QString &key, const QString &domain, const QString &selector);
0141 
0142 private:
0143     MESSAGEVIEWER_NO_EXPORT void downloadKey(const DKIMInfo &info);
0144     MESSAGEVIEWER_NO_EXPORT void slotDownloadKeyDone(const QList<QByteArray> &lst, const QString &domain, const QString &selector);
0145     MESSAGEVIEWER_NO_EXPORT void parseDKIMKeyRecord(const QString &str, const QString &domain, const QString &selector, bool storeKeyValue = true);
0146     [[nodiscard]] MESSAGEVIEWER_NO_EXPORT QString headerCanonizationSimple() const;
0147     [[nodiscard]] MESSAGEVIEWER_NO_EXPORT QString headerCanonizationRelaxed(bool removeQuoteOnContentType) const;
0148     [[nodiscard]] MESSAGEVIEWER_NO_EXPORT QString bodyCanonizationRelaxed() const;
0149     [[nodiscard]] MESSAGEVIEWER_NO_EXPORT QString bodyCanonizationSimple() const;
0150     [[nodiscard]] MESSAGEVIEWER_NO_EXPORT MessageViewer::DKIMCheckSignatureJob::CheckSignatureResult createCheckResult() const;
0151     MESSAGEVIEWER_NO_EXPORT void verifySignature();
0152     MESSAGEVIEWER_NO_EXPORT void verifyRSASignature();
0153     MESSAGEVIEWER_NO_EXPORT void verifyEd25519Signature();
0154     MESSAGEVIEWER_NO_EXPORT void computeHeaderCanonization(bool removeQuoteOnContentType);
0155     QList<DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult> mCheckSignatureAuthenticationResult;
0156     DKIMCheckPolicy mPolicy;
0157     DKIMHeaderParser mHeaderParser;
0158     KMime::Message::Ptr mMessage;
0159     QString mFromEmail;
0160     DKIMInfo mDkimInfo;
0161     DKIMKeyRecord mDkimKeyRecord;
0162     QString mDkimValue;
0163     QString mHeaderCanonizationResult;
0164     QString mBodyCanonizationResult;
0165     DKIMCheckSignatureJob::DKIMError mError = DKIMCheckSignatureJob::DKIMError::Any;
0166     DKIMCheckSignatureJob::DKIMWarning mWarning = DKIMCheckSignatureJob::DKIMWarning::Any;
0167     DKIMCheckSignatureJob::DKIMStatus mStatus = DKIMCheckSignatureJob::DKIMStatus::Unknown;
0168 };
0169 }
0170 MESSAGEVIEWER_EXPORT QDebug operator<<(QDebug d, const MessageViewer::DKIMCheckSignatureJob::CheckSignatureResult &t);
0171 MESSAGEVIEWER_EXPORT QDebug operator<<(QDebug d, const MessageViewer::DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult &t);
0172 Q_DECLARE_METATYPE(MessageViewer::DKIMCheckSignatureJob::CheckSignatureResult)
0173 Q_DECLARE_TYPEINFO(MessageViewer::DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult, Q_RELOCATABLE_TYPE);