Libkleo

enum.cpp
1/*
2 kleo/enum.cpp
3
4 This file is part of libkleopatra, the KDE keymanagement library
5 SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9
10#include <config-libkleo.h>
11
12#include "enum.h"
13
14#include <libkleo/keycache.h>
15
16#include <libkleo_debug.h>
17
18#include <KLazyLocalizedString>
19#include <KLocalizedString>
20
21#include <QEventLoop>
22#include <QString>
23
24#include <gpgme++/key.h>
25#include <gpgme++/tofuinfo.h>
26
27#include <functional>
28
29static const struct {
30 Kleo::CryptoMessageFormat format;
31 const KLazyLocalizedString displayName;
32 const char *configName;
33} cryptoMessageFormats[] = {
34 // clang-format off
35 {Kleo::InlineOpenPGPFormat, kli18n("Inline OpenPGP (deprecated)"), "inline openpgp"},
36 {Kleo::OpenPGPMIMEFormat, kli18n("OpenPGP/MIME"), "openpgp/mime" },
37 {Kleo::SMIMEFormat, kli18n("S/MIME"), "s/mime" },
38 {Kleo::SMIMEOpaqueFormat, kli18n("S/MIME Opaque"), "s/mime opaque" },
39 {Kleo::AnySMIME, kli18n("Any S/MIME"), "any s/mime" },
40 {Kleo::AnyOpenPGP, kli18n("Any OpenPGP"), "any openpgp" },
41 // clang-format on
42};
43static const unsigned int numCryptoMessageFormats = sizeof cryptoMessageFormats / sizeof *cryptoMessageFormats;
44
45const char *Kleo::cryptoMessageFormatToString(Kleo::CryptoMessageFormat f)
46{
47 if (f == AutoFormat) {
48 return "auto";
49 }
50 for (unsigned int i = 0; i < numCryptoMessageFormats; ++i) {
51 if (f == cryptoMessageFormats[i].format) {
52 return cryptoMessageFormats[i].configName;
53 }
54 }
55 return nullptr;
56}
57
58QStringList Kleo::cryptoMessageFormatsToStringList(unsigned int f)
59{
60 QStringList result;
61 for (unsigned int i = 0; i < numCryptoMessageFormats; ++i) {
62 if (f & cryptoMessageFormats[i].format) {
63 result.push_back(QLatin1StringView(cryptoMessageFormats[i].configName));
64 }
65 }
66 return result;
67}
68
69QString Kleo::cryptoMessageFormatToLabel(Kleo::CryptoMessageFormat f)
70{
71 if (f == AutoFormat) {
72 return i18n("Any");
73 }
74 for (unsigned int i = 0; i < numCryptoMessageFormats; ++i) {
75 if (f == cryptoMessageFormats[i].format) {
76 return KLocalizedString(cryptoMessageFormats[i].displayName).toString();
77 }
78 }
79 return QString();
80}
81
82Kleo::CryptoMessageFormat Kleo::stringToCryptoMessageFormat(const QString &s)
83{
84 const QString t = s.toLower();
85 for (unsigned int i = 0; i < numCryptoMessageFormats; ++i) {
86 if (t == QLatin1StringView(cryptoMessageFormats[i].configName)) {
87 return cryptoMessageFormats[i].format;
88 }
89 }
90 return AutoFormat;
91}
92
93unsigned int Kleo::stringListToCryptoMessageFormats(const QStringList &sl)
94{
95 unsigned int result = 0;
96 for (QStringList::const_iterator it = sl.begin(); it != sl.end(); ++it) {
97 result |= stringToCryptoMessageFormat(*it);
98 }
99 return result;
100}
101
102// For the config values used below, see also kaddressbook/editors/cryptowidget.cpp
103
104const char *Kleo::encryptionPreferenceToString(EncryptionPreference pref)
105{
106 switch (pref) {
107 case UnknownPreference:
108 return nullptr;
109 case NeverEncrypt:
110 return "never";
111 case AlwaysEncrypt:
112 return "always";
113 case AlwaysEncryptIfPossible:
114 return "alwaysIfPossible";
115 case AlwaysAskForEncryption:
116 return "askAlways";
117 case AskWheneverPossible:
118 return "askWhenPossible";
119 }
120 return nullptr; // keep the compiler happy
121}
122
123Kleo::EncryptionPreference Kleo::stringToEncryptionPreference(const QString &str)
124{
125 if (str == QLatin1StringView("never")) {
126 return NeverEncrypt;
127 }
128 if (str == QLatin1StringView("always")) {
129 return AlwaysEncrypt;
130 }
131 if (str == QLatin1StringView("alwaysIfPossible")) {
132 return AlwaysEncryptIfPossible;
133 }
134 if (str == QLatin1StringView("askAlways")) {
135 return AlwaysAskForEncryption;
136 }
137 if (str == QLatin1StringView("askWhenPossible")) {
138 return AskWheneverPossible;
139 }
140 return UnknownPreference;
141}
142
143QString Kleo::encryptionPreferenceToLabel(EncryptionPreference pref)
144{
145 switch (pref) {
146 case NeverEncrypt:
147 return i18n("Never Encrypt");
148 case AlwaysEncrypt:
149 return i18n("Always Encrypt");
150 case AlwaysEncryptIfPossible:
151 return i18n("Always Encrypt If Possible");
152 case AlwaysAskForEncryption:
153 return i18n("Ask");
154 case AskWheneverPossible:
155 return i18n("Ask Whenever Possible");
156 default:
157 return xi18nc("no specific preference", "<placeholder>none</placeholder>");
158 }
159}
160
161const char *Kleo::signingPreferenceToString(SigningPreference pref)
162{
163 switch (pref) {
164 case UnknownSigningPreference:
165 return nullptr;
166 case NeverSign:
167 return "never";
168 case AlwaysSign:
169 return "always";
170 case AlwaysSignIfPossible:
171 return "alwaysIfPossible";
172 case AlwaysAskForSigning:
173 return "askAlways";
174 case AskSigningWheneverPossible:
175 return "askWhenPossible";
176 }
177 return nullptr; // keep the compiler happy
178}
179
180Kleo::SigningPreference Kleo::stringToSigningPreference(const QString &str)
181{
182 if (str == QLatin1StringView("never")) {
183 return NeverSign;
184 }
185 if (str == QLatin1StringView("always")) {
186 return AlwaysSign;
187 }
188 if (str == QLatin1StringView("alwaysIfPossible")) {
189 return AlwaysSignIfPossible;
190 }
191 if (str == QLatin1StringView("askAlways")) {
192 return AlwaysAskForSigning;
193 }
194 if (str == QLatin1StringView("askWhenPossible")) {
195 return AskSigningWheneverPossible;
196 }
197 return UnknownSigningPreference;
198}
199
200QString Kleo::signingPreferenceToLabel(SigningPreference pref)
201{
202 switch (pref) {
203 case NeverSign:
204 return i18n("Never Sign");
205 case AlwaysSign:
206 return i18n("Always Sign");
207 case AlwaysSignIfPossible:
208 return i18n("Always Sign If Possible");
209 case AlwaysAskForSigning:
210 return i18n("Ask");
211 case AskSigningWheneverPossible:
212 return i18n("Ask Whenever Possible");
213 default:
214 return i18nc("no specific preference", "<none>");
215 }
216}
217
218Kleo::TrustLevel Kleo::trustLevel(const GpgME::Key &key)
219{
220 TrustLevel maxTl = Level0;
221 for (int i = 0, c = key.numUserIDs(); i < c; ++i) {
222 const auto tl = trustLevel(key.userID(i));
223 maxTl = qMax(maxTl, tl);
224 if (maxTl == Level4) {
225 break;
226 }
227 }
228
229 return maxTl;
230}
231
232namespace
233{
234
235bool hasTrustedSignature(const GpgME::UserID &uid)
236{
237 // lazily initialized cache
238 static std::shared_ptr<const Kleo::KeyCache> keyCache;
239 if (!keyCache) {
240 keyCache = Kleo::KeyCache::instance();
241 }
242
243 const auto signatures = uid.signatures();
244 std::vector<std::string> sigKeyIDs;
245 std::transform(signatures.cbegin(),
246 signatures.cend(),
247 std::back_inserter(sigKeyIDs),
248 std::bind(&GpgME::UserID::Signature::signerKeyID, std::placeholders::_1));
249
250 const auto keys = keyCache->findByKeyIDOrFingerprint(sigKeyIDs);
251 return std::any_of(keys.cbegin(), keys.cend(), [](const GpgME::Key &key) {
252 return key.ownerTrust() == GpgME::Key::Ultimate;
253 });
254}
255
256}
257
258Kleo::TrustLevel Kleo::trustLevel(const GpgME::UserID &uid)
259{
260 // Modelled after https://wiki.gnupg.org/EasyGpg2016/AutomatedEncryption,
261 // but modified to cover all cases, unlike the pseudocode in the document.
262 //
263 // TODO: Check whether the key comes from a trusted source (Cert/PKA/DANE/WKD)
264
265 switch (uid.validity()) {
266 case GpgME::UserID::Unknown:
267 case GpgME::UserID::Undefined:
268 case GpgME::UserID::Never:
269 // Not enough trust -> level 0
270 return Level0;
271
272 case GpgME::UserID::Marginal:
273 // Marginal trust without TOFU data means the key is still trusted
274 // through the Web of Trust -> level 2
275 if (uid.tofuInfo().isNull()) {
276 return Level2;
277 }
278 // Marginal trust with TOFU, level will depend on TOFU history
279 switch (uid.tofuInfo().validity()) {
280 case GpgME::TofuInfo::ValidityUnknown:
281 case GpgME::TofuInfo::Conflict:
282 case GpgME::TofuInfo::NoHistory:
283 // Marginal trust, but not enough history -> level 0
284 return Level0;
285 case GpgME::TofuInfo::LittleHistory:
286 // Marginal trust, but too little history -> level 1
287 return Level1;
288 case GpgME::TofuInfo::BasicHistory:
289 case GpgME::TofuInfo::LargeHistory:
290 // Marginal trust and enough history -> level 2
291 return Level2;
292 }
293 return Level2; // Not reached, but avoids fallthrough warnings
294 case GpgME::UserID::Full:
295 // Full trust, trust level depends whether the UserID is signed with
296 // at least one key with Ultimate ownertrust.
297 return hasTrustedSignature(uid) ? Level4 : Level3;
298
299 case GpgME::UserID::Ultimate:
300 // Ultimate trust -> leve 4
301 return Level4;
302 }
303
304 Q_UNREACHABLE();
305}
QString toString() const
QString xi18nc(const char *context, const char *text, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
iterator begin()
iterator end()
void push_back(parameter_type value)
QString toLower() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 6 2024 12:02:18 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.