File indexing completed on 2024-06-23 05:18:28

0001 /*  -*- c++ -*-
0002     keyresolver.h
0003 
0004     This file is part of libkleopatra, the KDE keymanagement library
0005     SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB
0006 
0007     Based on kpgp.h
0008     Copyright (C) 2001,2002 the KPGP authors
0009     See file libkdenetwork/AUTHORS.kpgp for details
0010 
0011     SPDX-License-Identifier: GPL-2.0-or-later
0012 */
0013 
0014 #pragma once
0015 
0016 #include "messagecomposer_export.h"
0017 #include <Libkleo/Enum>
0018 #include <Libkleo/KeyApprovalDialog>
0019 
0020 #include <gpgme++/key.h>
0021 
0022 #include <vector>
0023 
0024 #include <QSharedPointer>
0025 #include <QStringList>
0026 
0027 namespace MessageComposer
0028 {
0029 class ContactPreference;
0030 }
0031 
0032 namespace Kleo
0033 {
0034 class ExpiryChecker;
0035 
0036 enum Result {
0037     Failure = 0,
0038     Ok = 1,
0039     Canceled = 2,
0040 };
0041 /**
0042      \short A class to resolve signing/encryption keys w.r.t. per-recipient preferences
0043 
0044      \section Step 1: Set the information needed
0045 
0046      The constructor takes some basic options as arguments, such as
0047      whether or not encryption was actually requested. Recipient and
0048      sender information is then set by using \c
0049      setEncryptToSelfKeys(), \c setSigningKeys(), \c
0050      setPrimaryRecipients() (To/Cc) and \c setSecondaryRecipients()
0051      (Bcc).
0052 
0053      \section Step 2: Lookup and check per-recipient crypto preferences / Opportunistic Encryption
0054 
0055      First, \c checkSigningPreferences() goes through all recipient's
0056      signing preferences, to determine whether or not to sign. It also
0057      takes into account the available signing keys and whether or not
0058      the user explicitly requested signing.
0059 
0060      \c checkEncryptionPreferences() does the same for encryption
0061      preferences. If opportunistic encryption is enabled, recipients
0062      without encryption preferences set are treated as if they had a
0063      preference of \c AskWheneverPossible.
0064 
0065      In both cases an Action code is returned, with the following
0066      meanings:
0067 
0068      <dl><dt>Conflict</dt><dd>A conflict was detected. E.g. one
0069      recipient's preference was set to "always encrypt", while another
0070      one's preference was set to "never encrypt". You should ask the
0071      user what to do.</dd></dt>
0072 
0073      <dt>DoIt, DontDoIt</dt><dd>Do/Don't sign/encrypt</dd>
0074 
0075      <dt>Ask</dt><dd>(Some) crypto preferences request to prompt the
0076      user, so do it.</dd>
0077 
0078      <dt>Impossible</dt><dd>Signing or encryption is impossible,
0079      e.g. due to missing keys or unsupported formats.</dd> </dl>
0080 
0081      \section Step 3: Resolve all keys.
0082 
0083      In case signing or encryption was implicitly or explicitly
0084      requested by the user, \c resolveAllKeys() tries to find signing
0085      keys for each required format, as well as encryption keys for all
0086      recipients (incl. the sender, if encrypt-to-self is set).
0087 
0088      \section Step 4: Get signing keys.
0089 
0090      If, after key resolving, signing is still requested and
0091      apparently possible, you can get the result of all this by
0092      iterating over the available message formats and retrieving the
0093      set of signing keys to use with a call to \c signingKeys().
0094 
0095      \section Step 5: Get encryption key sets.
0096 
0097      If after key resolving, encryption is still requested and
0098      apparently possible, you can get the result of all this by
0099      calling \c encryptionItems() with the current message format at
0100      hand as its argument.
0101 
0102      This will return a list of recipient-list/key-list pairs that
0103      each describe a copy of the (possibly signed) message to be
0104      encrypted independently.
0105 
0106      Note that it's only necessary to sign the message once for each
0107      message format, although it might be necessary to create more
0108      than one message when encrypting. This is because encryption
0109      allows the recipients to learn about the other recipients the
0110      message was encrypted to, so each secondary (BCC) recipient need
0111      a copy of it's own to hide the other secondary recipients.
0112     */
0113 
0114 class MESSAGECOMPOSER_EXPORT KeyResolver
0115 {
0116 public:
0117     KeyResolver(bool encToSelf, bool showApproval, bool oppEncryption, unsigned int format, const std::shared_ptr<Kleo::ExpiryChecker> &expiryChecker);
0118 
0119     ~KeyResolver();
0120 
0121     struct Item : public KeyApprovalDialog::Item {
0122         Item()
0123             : KeyApprovalDialog::Item()
0124             , signPref(UnknownSigningPreference)
0125             , format(AutoFormat)
0126             , needKeys(true)
0127         {
0128         }
0129 
0130         Item(const QString &a, EncryptionPreference e, SigningPreference s, CryptoMessageFormat f)
0131             : KeyApprovalDialog::Item(a, std::vector<GpgME::Key>(), e)
0132             , signPref(s)
0133             , format(f)
0134             , needKeys(true)
0135         {
0136         }
0137 
0138         Item(const QString &a, const std::vector<GpgME::Key> &k, EncryptionPreference e, SigningPreference s, CryptoMessageFormat f)
0139             : KeyApprovalDialog::Item(a, k, e)
0140             , signPref(s)
0141             , format(f)
0142             , needKeys(false)
0143         {
0144         }
0145 
0146         SigningPreference signPref;
0147         CryptoMessageFormat format;
0148         bool needKeys;
0149     };
0150 
0151     /**
0152        Set the fingerprints of keys to be used for encrypting to
0153        self. Also looks them up and complains if they're not usable or
0154        found.
0155     */
0156     [[nodiscard]] Kleo::Result setEncryptToSelfKeys(const QStringList &fingerprints);
0157     /**
0158         Set the fingerprints of keys to be used for signing. Also
0159         looks them up and complains if they're not usable or found.
0160     */
0161     [[nodiscard]] Kleo::Result setSigningKeys(const QStringList &fingerprints);
0162     /**
0163        Set the list of primary (To/CC) recipient addresses. Also looks
0164        up possible keys, but doesn't interact with the user.
0165     */
0166     void setPrimaryRecipients(const QStringList &addresses);
0167     /**
0168        Set the list of secondary (BCC) recipient addresses. Also looks
0169        up possible keys, but doesn't interact with the user.
0170     */
0171     void setSecondaryRecipients(const QStringList &addresses);
0172 
0173     /**
0174        Determine whether to sign or not, depending on the
0175        per-recipient signing preferences, as well as the availability
0176        of usable signing keys.
0177     */
0178     [[nodiscard]] Action checkSigningPreferences(bool signingRequested) const;
0179     /**
0180        Determine whether to encrypt or not, depending on the
0181        per-recipient encryption preferences, as well as the availability
0182        of usable encryption keys.
0183     */
0184     [[nodiscard]] Action checkEncryptionPreferences(bool encryptionRequested) const;
0185 
0186     /**
0187        Queries the user for missing keys and displays a key approval
0188        dialog if needed.
0189     */
0190     [[nodiscard]] Kleo::Result resolveAllKeys(bool &signingRequested, bool &encryptionRequested);
0191 
0192     /**
0193        @return the signing keys to use (if any) for the given message
0194        format.
0195     */
0196     [[nodiscard]] std::vector<GpgME::Key> signingKeys(CryptoMessageFormat f) const;
0197 
0198     struct SplitInfo {
0199         SplitInfo() = default;
0200 
0201         explicit SplitInfo(const QStringList &r)
0202             : recipients(r)
0203         {
0204         }
0205 
0206         SplitInfo(const QStringList &r, const std::vector<GpgME::Key> &k)
0207             : recipients(r)
0208             , keys(k)
0209         {
0210         }
0211 
0212         QStringList recipients;
0213         std::vector<GpgME::Key> keys;
0214     };
0215     /** @return the found distinct sets of items for format \a f.  The
0216         returned vector will contain more than one item only if
0217         secondary recipients have been specified.
0218     */
0219     [[nodiscard]] std::vector<SplitInfo> encryptionItems(CryptoMessageFormat f) const;
0220 
0221     std::vector<GpgME::Key> encryptToSelfKeysFor(CryptoMessageFormat f) const;
0222 
0223     /** If Autocrypt keys are used to find valid PGP Keys
0224      */
0225     void setAutocryptEnabled(bool autocryptEnabled);
0226 
0227     std::map<QByteArray, QString> useAutocrypt() const;
0228 
0229     /** Disable ContactSearchJob in KeyResolver.
0230         A usecase is that ests won't fireup an Akonadi instance only for this feature.
0231         @default is true: The ContactSearchJob is executed.
0232      */
0233     void setAkonadiLookupEnabled(bool akonadiLookupEnabled);
0234 
0235     /** Sets crypto preferences for given email address.
0236      * This is an alternative to setting crypto preferences for a contact when Akonadi
0237      * lookup is disabled - useful mostly for testing cases when it's not possible to
0238      * index contacts on demand.
0239      */
0240     void setContactPreferences(const QString &address, const MessageComposer::ContactPreference &preference);
0241 
0242 private:
0243     void dump() const;
0244     std::vector<Item> getEncryptionItems(const QStringList &recipients);
0245     std::vector<GpgME::Key> getEncryptionKeys(const QString &recipient, bool quiet) const;
0246 
0247     Kleo::Result showKeyApprovalDialog(bool &finalySendUnencrypted);
0248 
0249     bool encryptionPossible() const;
0250     bool signingPossible() const;
0251     Kleo::Result resolveEncryptionKeys(bool signingRequested, bool &finalySendUnencrypted);
0252     Kleo::Result resolveSigningKeysForEncryption();
0253     Kleo::Result resolveSigningKeysForSigningOnly();
0254     void collapseAllSplitInfos();
0255     void addToAllSplitInfos(const std::vector<GpgME::Key> &keys, unsigned int formats);
0256     void addKeys(const std::vector<Item> &items, CryptoMessageFormat f);
0257     void addKeys(const std::vector<Item> &items);
0258     QStringList allRecipients() const;
0259     std::vector<GpgME::Key> signingKeysFor(CryptoMessageFormat f) const;
0260 
0261     std::vector<GpgME::Key> lookup(const QStringList &patterns, bool secret = false) const;
0262 
0263     std::vector<GpgME::Key>
0264     selectKeys(const QString &person, const QString &msg, const std::vector<GpgME::Key> &selectedKeys = std::vector<GpgME::Key>()) const;
0265 
0266     QStringList keysForAddress(const QString &address) const;
0267     void setKeysForAddress(const QString &address, const QStringList &pgpKeyFingerprints, const QStringList &smimeCertFingerprints) const;
0268 
0269     bool encryptToSelf() const;
0270     bool showApprovalDialog() const;
0271 
0272     MessageComposer::ContactPreference lookupContactPreferences(const QString &address) const;
0273     void saveContactPreference(const QString &email, const MessageComposer::ContactPreference &pref) const;
0274 
0275 private:
0276     class EncryptionPreferenceCounter;
0277     friend class ::Kleo::KeyResolver::EncryptionPreferenceCounter;
0278     class SigningPreferenceCounter;
0279     friend class ::Kleo::KeyResolver::SigningPreferenceCounter;
0280 
0281     struct KeyResolverPrivate;
0282     std::unique_ptr<KeyResolverPrivate> const d;
0283 
0284     bool mEncryptToSelf;
0285     const bool mShowApprovalDialog : 1;
0286     const bool mOpportunisticEncyption : 1;
0287     const unsigned int mCryptoMessageFormats;
0288 };
0289 } // namespace Kleo