Libkleo

compliance.cpp
1 /* -*- mode: c++; c-basic-offset:4 -*-
2  utils/compliance.cpp
3 
4  This file is part of libkleopatra
5  SPDX-FileCopyrightText: 2022 g10 Code GmbH
6  SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
7 
8  SPDX-License-Identifier: GPL-2.0-or-later
9 */
10 
11 #include <config-libkleo.h>
12 
13 #include "compliance.h"
14 
15 #include "algorithm.h"
16 #include "cryptoconfig.h"
17 #include "gnupg.h"
18 #include "keyhelpers.h"
19 #include "stringutils.h"
20 #include "systeminfo.h"
21 
22 #include <libkleo/debug.h>
23 #include <libkleo/keyfiltermanager.h>
24 
25 #include <libkleo_debug.h>
26 
27 #include <KColorScheme>
28 #include <KLocalizedString>
29 
30 #include <QPushButton>
31 
32 #include <gpgme++/key.h>
33 
34 bool Kleo::DeVSCompliance::isActive()
35 {
36  return getCryptoConfigStringValue("gpg", "compliance") == QLatin1StringView{"de-vs"};
37 }
38 
39 bool Kleo::DeVSCompliance::isCompliant()
40 {
41  if (!isActive()) {
42  return false;
43  }
44  // The pseudo option compliance_de_vs was fully added in 2.2.34;
45  // For versions between 2.2.28 and 2.2.33 there was a broken config
46  // value with a wrong type. So for them we add an extra check. This
47  // can be removed in future versions because for GnuPG we could assume
48  // non-compliance for older versions as versions of Kleopatra for
49  // which this matters are bundled with new enough versions of GnuPG anyway.
50  if (engineIsVersion(2, 2, 28) && !engineIsVersion(2, 2, 34)) {
51  return true;
52  }
53  return getCryptoConfigIntValue("gpg", "compliance_de_vs", 0) != 0;
54 }
55 
56 bool Kleo::DeVSCompliance::algorithmIsCompliant(std::string_view algo)
57 {
58  return !isActive() || Kleo::contains(compliantAlgorithms(), algo);
59 }
60 
61 bool Kleo::DeVSCompliance::allSubkeysAreCompliant(const GpgME::Key &key)
62 {
63  if (!isActive()) {
64  return true;
65  }
66  // there is at least one usable subkey
67  const auto usableSubkeys = Kleo::count_if(key.subkeys(), [](const auto &sub) {
68  return !sub.isExpired() && !sub.isRevoked();
69  });
70  if (usableSubkeys == 0) {
71  qCDebug(LIBKLEO_LOG) << __func__ << "No usable subkeys found for key" << key;
72  return false;
73  }
74  // and all usable subkeys are compliant
75  return Kleo::all_of(key.subkeys(), [](const auto &sub) {
76  return sub.isDeVs() || sub.isExpired() || sub.isRevoked();
77  });
78 }
79 
80 bool Kleo::DeVSCompliance::userIDIsCompliant(const GpgME::UserID &id)
81 {
82  if (!isActive()) {
83  return true;
84  }
85  return (id.parent().keyListMode() & GpgME::Validate) //
86  && !id.isRevoked() //
87  && id.validity() >= GpgME::UserID::Full //
88  && allSubkeysAreCompliant(id.parent());
89 }
90 
91 bool Kleo::DeVSCompliance::keyIsCompliant(const GpgME::Key &key)
92 {
93  if (!isActive()) {
94  return true;
95  }
96  return (key.keyListMode() & GpgME::Validate) //
97  && allUserIDsHaveFullValidity(key) //
98  && allSubkeysAreCompliant(key);
99 }
100 
101 const std::vector<std::string> &Kleo::DeVSCompliance::compliantAlgorithms()
102 {
103  static const std::vector<std::string> compliantAlgos = {
104  "brainpoolP256r1",
105  "brainpoolP384r1",
106  "brainpoolP512r1",
107  "rsa3072",
108  "rsa4096",
109  };
110  return isActive() ? compliantAlgos : Kleo::availableAlgorithms();
111 }
112 
113 const std::vector<std::string> &Kleo::DeVSCompliance::preferredCompliantAlgorithms()
114 {
115  static std::vector<std::string> result;
116  if (result.empty()) {
117  const auto &preferredAlgos = Kleo::preferredAlgorithms();
118  result.reserve(preferredAlgos.size());
119  Kleo::copy_if(preferredAlgos, std::back_inserter(result), Kleo::DeVSCompliance::algorithmIsCompliant);
120  }
121  return result;
122 }
123 
124 void Kleo::DeVSCompliance::decorate(QPushButton *button)
125 {
126  decorate(button, isCompliant());
127 }
128 
129 void Kleo::DeVSCompliance::decorate(QPushButton *button, bool compliant)
130 {
131  if (!button) {
132  return;
133  }
134  if (compliant) {
135  button->setIcon(QIcon::fromTheme(QStringLiteral("security-high")));
136  if (!SystemInfo::isHighContrastModeActive()) {
138  button->setStyleSheet(QStringLiteral("QPushButton { background-color: %1; };").arg(bgColor));
139  }
140  } else {
141  button->setIcon(QIcon::fromTheme(QStringLiteral("security-medium")));
142  if (!SystemInfo::isHighContrastModeActive()) {
144  button->setStyleSheet(QStringLiteral("QPushButton { background-color: %1; };").arg(bgColor));
145  }
146  }
147 }
148 
149 QString Kleo::DeVSCompliance::name()
150 {
151  return name(isCompliant());
152 }
153 
154 QString Kleo::DeVSCompliance::name(bool compliant)
155 {
156  const auto filterId = compliant ? QStringLiteral("de-vs-filter") : QStringLiteral("not-de-vs-filter");
157  if (auto filter = KeyFilterManager::instance()->keyFilterByID(filterId)) {
158  return filter->name();
159  }
160  return compliant ? i18n("VS-NfD compliant") : i18n("Not VS-NfD compliant");
161 }
const QColor & color() const const
QString name() const const
QBrush background(BackgroundRole=NormalBackground) const
QIcon fromTheme(const QString &name)
void setStyleSheet(const QString &styleSheet)
QString i18n(const char *text, const TYPE &arg...)
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
void setIcon(const QIcon &icon)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Thu Feb 15 2024 03:56:14 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.