File indexing completed on 2024-06-23 05:13:37
0001 /* -*- mode: c++; c-basic-offset:4 -*- 0002 commands/changeownertrustcommand.cpp 0003 0004 This file is part of Kleopatra, the KDE keymanager 0005 SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB 0006 SPDX-FileCopyrightText: 2022 g10 Code GmbH 0007 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de> 0008 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 0012 #include <config-kleopatra.h> 0013 0014 #include "changeownertrustcommand.h" 0015 0016 #include "command_p.h" 0017 0018 #include <Libkleo/Compliance> 0019 #include <Libkleo/Formatting> 0020 #include <Libkleo/KeyCache> 0021 0022 #include <KLocalizedString> 0023 0024 #include <QGpgME/ChangeOwnerTrustJob> 0025 #include <QGpgME/Protocol> 0026 0027 #include <gpgme++/key.h> 0028 0029 #include "kleopatra_debug.h" 0030 0031 using namespace Kleo; 0032 using namespace Kleo::Commands; 0033 using namespace GpgME; 0034 using namespace QGpgME; 0035 0036 class ChangeOwnerTrustCommand::Private : public Command::Private 0037 { 0038 friend class ::Kleo::Commands::ChangeOwnerTrustCommand; 0039 ChangeOwnerTrustCommand *q_func() const 0040 { 0041 return static_cast<ChangeOwnerTrustCommand *>(q); 0042 } 0043 0044 public: 0045 Private(ChangeOwnerTrustCommand *qq, KeyListController *c); 0046 0047 private: 0048 void startJob(Key::OwnerTrust trust); 0049 void createJob(); 0050 void slotResult(const Error &err); 0051 void showErrorDialog(const Error &error); 0052 void showSuccessDialog(); 0053 0054 private: 0055 QPointer<ChangeOwnerTrustJob> job; 0056 Key::OwnerTrust trustToSet = Key::OwnerTrust::Unknown; 0057 }; 0058 0059 ChangeOwnerTrustCommand::Private *ChangeOwnerTrustCommand::d_func() 0060 { 0061 return static_cast<Private *>(d.get()); 0062 } 0063 const ChangeOwnerTrustCommand::Private *ChangeOwnerTrustCommand::d_func() const 0064 { 0065 return static_cast<const Private *>(d.get()); 0066 } 0067 0068 #define d d_func() 0069 #define q q_func() 0070 0071 ChangeOwnerTrustCommand::Private::Private(ChangeOwnerTrustCommand *qq, KeyListController *c) 0072 : Command::Private{qq, c} 0073 { 0074 } 0075 0076 ChangeOwnerTrustCommand::ChangeOwnerTrustCommand(QAbstractItemView *v, KeyListController *c) 0077 : Command{v, new Private{this, c}} 0078 { 0079 } 0080 0081 ChangeOwnerTrustCommand::~ChangeOwnerTrustCommand() 0082 { 0083 qCDebug(KLEOPATRA_LOG) << this << __func__; 0084 } 0085 0086 void ChangeOwnerTrustCommand::doStart() 0087 { 0088 if (d->keys().size() != 1) { 0089 d->finished(); 0090 return; 0091 } 0092 0093 const Key key = d->key(); 0094 if (key.protocol() != GpgME::OpenPGP) { 0095 d->finished(); 0096 return; 0097 } 0098 0099 const auto keyInfo = Formatting::formatForComboBox(key); 0100 0101 if (key.hasSecret()) { 0102 const auto answer = KMessageBox::questionTwoActionsCancel(d->parentWidgetOrView(), 0103 xi18nc("@info", "Is '%1' your own certificate?", keyInfo), 0104 i18nc("@title:window", "Mark Own Certificate"), 0105 KGuiItem(i18nc("@action:button", "Yes, it's mine")), 0106 KGuiItem(i18nc("@action:button", "No, it's not mine")), 0107 KStandardGuiItem::cancel()); 0108 switch (answer) { 0109 case KMessageBox::ButtonCode::PrimaryAction: { 0110 if (key.ownerTrust() < Key::Ultimate) { 0111 d->startJob(Key::OwnerTrust::Ultimate); 0112 } 0113 return; 0114 } 0115 case KMessageBox::ButtonCode::SecondaryAction: { 0116 if (key.ownerTrust() == Key::Ultimate) { 0117 d->startJob(Key::OwnerTrust::Unknown); 0118 return; 0119 } 0120 // else ask next question 0121 break; 0122 } 0123 case KMessageBox::Cancel: { 0124 d->canceled(); 0125 return; 0126 } 0127 default:; // cannot happen 0128 } 0129 } 0130 0131 if (key.ownerTrust() < Key::OwnerTrust::Full) { 0132 const auto text = (DeVSCompliance::isCompliant() && DeVSCompliance::allSubkeysAreCompliant(key)) 0133 ? xi18nc("@info %1: a certificate, %2: name of a compliance mode", 0134 "<para>Do you want to grant '%1' the power to mark certificates as %2 for you?</para>" 0135 "<para><emphasis>This means that the owner of this certificate properly checks fingerprints " 0136 "and confirms the identities of others.</emphasis></para>", 0137 keyInfo, 0138 DeVSCompliance::name()) 0139 : xi18nc("@info %1: a certificate", 0140 "<para>Do you want to grant '%1' the power to mark certificates as valid for you?</para>" 0141 "<para><emphasis>This means that the owner of this certificate properly checks fingerprints " 0142 "and confirms the identities of others.</emphasis></para>", 0143 keyInfo); 0144 const auto answer = KMessageBox::questionTwoActions(d->parentWidgetOrView(), 0145 text, 0146 i18nc("@title:window", "Grant Certification Power"), 0147 KGuiItem(i18nc("@action:button", "Grant Power")), 0148 KStandardGuiItem::cancel()); 0149 if (answer == KMessageBox::ButtonCode::PrimaryAction) { 0150 d->startJob(Key::OwnerTrust::Full); 0151 } else { 0152 d->canceled(); 0153 } 0154 } else { 0155 const auto text = (DeVSCompliance::isCompliant() && DeVSCompliance::allSubkeysAreCompliant(key)) 0156 ? xi18nc("@info %1: a certificate, %2: name of a compliance mode", 0157 "<para>The certificate '%1' is empowered to mark other certificates as %2 for you.</para>" 0158 "<para>Do you want to revoke this power?</para>", 0159 keyInfo, 0160 DeVSCompliance::name()) 0161 : xi18nc("@info %1: a certificate", 0162 "<para>The certificate '%1' is empowered to mark other certificates as valid for you.</para>" 0163 "<para>Do you want to revoke this power?</para>", 0164 keyInfo); 0165 const auto answer = KMessageBox::questionTwoActions(d->parentWidgetOrView(), 0166 text, 0167 i18nc("@title:window", "Revoke Certification Power"), 0168 KGuiItem(i18nc("@action:button", "Revoke Power")), 0169 KStandardGuiItem::cancel()); 0170 if (answer == KMessageBox::ButtonCode::PrimaryAction) { 0171 d->startJob(Key::OwnerTrust::Unknown); 0172 } else { 0173 d->canceled(); 0174 } 0175 } 0176 } 0177 0178 void ChangeOwnerTrustCommand::Private::startJob(Key::OwnerTrust trust) 0179 { 0180 trustToSet = trust; 0181 0182 createJob(); 0183 Q_ASSERT(job); 0184 0185 if (const Error err = job->start(key(), trust)) { 0186 showErrorDialog(err); 0187 finished(); 0188 } 0189 } 0190 0191 void ChangeOwnerTrustCommand::Private::slotResult(const Error &err) 0192 { 0193 if (err.isCanceled()) 0194 ; 0195 else if (err) { 0196 showErrorDialog(err); 0197 } else { 0198 showSuccessDialog(); 0199 } 0200 finished(); 0201 } 0202 0203 void ChangeOwnerTrustCommand::doCancel() 0204 { 0205 qCDebug(KLEOPATRA_LOG) << this << __func__; 0206 if (d->job) { 0207 d->job->slotCancel(); 0208 } 0209 } 0210 0211 void ChangeOwnerTrustCommand::Private::createJob() 0212 { 0213 Q_ASSERT(!job); 0214 0215 ChangeOwnerTrustJob *const j = QGpgME::openpgp()->changeOwnerTrustJob(); 0216 if (!j) { 0217 return; 0218 } 0219 0220 connect(j, &QGpgME::Job::jobProgress, q, &Command::progress); 0221 connect(j, &ChangeOwnerTrustJob::result, q, [this](const GpgME::Error &result) { 0222 slotResult(result); 0223 }); 0224 0225 job = j; 0226 } 0227 0228 void ChangeOwnerTrustCommand::Private::showErrorDialog(const Error &err) 0229 { 0230 const auto keyInfo = Formatting::formatForComboBox(key()); 0231 switch (trustToSet) { 0232 case Key::OwnerTrust::Ultimate: 0233 error(xi18nc("@info", 0234 "<para>An error occurred while marking certificate '%1' as your certificate.</para>" 0235 "<para><message>%2</message></para>", 0236 keyInfo, 0237 Formatting::errorAsString(err))); 0238 break; 0239 case Key::OwnerTrust::Full: 0240 error(xi18nc("@info", 0241 "<para>An error occurred while granting certification power to '%1'.</para>" 0242 "<para><message>%2</message></para>", 0243 keyInfo, 0244 Formatting::errorAsString(err))); 0245 break; 0246 default: 0247 error(xi18nc("@info", 0248 "<para>An error occurred while revoking the certification power of '%1'.</para>" 0249 "<para><message>%2</message></para>", 0250 keyInfo, 0251 Formatting::errorAsString(err))); 0252 } 0253 } 0254 0255 void ChangeOwnerTrustCommand::Private::showSuccessDialog() 0256 { 0257 auto updatedKey = key(); 0258 updatedKey.update(); 0259 KeyCache::mutableInstance()->insert(updatedKey); 0260 0261 const auto keyInfo = Formatting::formatForComboBox(updatedKey); 0262 switch (updatedKey.ownerTrust()) { 0263 case Key::OwnerTrust::Ultimate: 0264 success(i18nc("@info", "Certificate '%1' was marked as your certificate.", keyInfo)); 0265 break; 0266 case Key::OwnerTrust::Full: 0267 success(i18nc("@info", "Certification power was granted to '%1'.", keyInfo)); 0268 break; 0269 default: 0270 success(i18nc("@info", "The certification power of '%1' was revoked.", keyInfo)); 0271 } 0272 } 0273 0274 #undef d 0275 #undef q 0276 0277 #include "moc_changeownertrustcommand.cpp"