• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeutils API Reference
  • KDE Home
  • Contact Us
 

kgpg

  • sources
  • kde-4.14
  • kdeutils
  • kgpg
caff.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009,2010,2012,2013,2014 Rolf Eike Beer <kde@opensource.sf-tec.de>
3  */
4 
5 /***************************************************************************
6  * *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  ***************************************************************************/
13 
14 #include "caff.h"
15 #include "caff_p.h"
16 
17 #include "kgpginterface.h"
18 #include "kgpgsettings.h"
19 #include "core/KGpgKeyNode.h"
20 #include "core/KGpgSignableNode.h"
21 #include "transactions/kgpgdeluid.h"
22 #include "transactions/kgpgencrypt.h"
23 #include "transactions/kgpgexport.h"
24 #include "transactions/kgpgimport.h"
25 #include "transactions/kgpgsignuid.h"
26 
27 #include <KDebug>
28 #include <KLocale>
29 #include <KProcess>
30 #include <KTempDir>
31 #include <KTemporaryFile>
32 #include <KToolInvocation>
33 #include <KMessageBox>
34 #include <QDir>
35 #include <QFileInfo>
36 
37 KGpgCaffPrivate::KGpgCaffPrivate(KGpgCaff *parent, const KGpgSignableNode::List &ids, const QStringList &signers,
38  const KGpgCaff::OperationFlags flags, const KGpgSignTransactionHelper::carefulCheck checklevel)
39  : QObject(parent),
40  q_ptr(parent),
41  m_signers(signers),
42  m_flags(flags),
43  m_checklevel(checklevel),
44  m_allids(ids)
45 {
46  const QString gpgCfg = KGpgSettings::gpgConfigPath();
47  const QString secring = KgpgInterface::getGpgSetting(QLatin1String( "secret-keyring" ), gpgCfg);
48 
49  if (!secring.isEmpty()) {
50  m_secringfile = secring;
51  } else {
52  QFileInfo fn(gpgCfg);
53  fn.setFile(fn.dir(), QLatin1String("secring.gpg"));
54  m_secringfile = QDir::toNativeSeparators(fn.absoluteFilePath());
55  }
56 }
57 
58 KGpgCaffPrivate::~KGpgCaffPrivate()
59 {
60 }
61 
62 void
63 KGpgCaffPrivate::reexportKey(const KGpgSignableNode *key)
64 {
65  Q_ASSERT(m_tempdir.isNull());
66 
67  // find out if the given id can be used for encryption
68  const KGpgKeyNode *k;
69  if (key->getType() & KgpgCore::ITYPE_PAIR)
70  k = key->toKeyNode();
71  else
72  k = key->getParentKeyNode()->toKeyNode();
73 
74  // skip if not
75  if (!k->canEncrypt()) {
76  m_noEncIds << key;
77  m_allids.removeFirst();
78  checkNextLoop();
79  return;
80  }
81 
82  m_tempdir.reset(new KTempDir());
83 
84  // export all keys necessary for signing
85  QStringList exportkeys(m_signers);
86  exportkeys << key->getKeyNode()->getId();
87 
88  KGpgImport *imp = new KGpgImport(this);
89 
90  QStringList expOptions(QLatin1String( "--export-options" ));
91  expOptions << QLatin1String( "export-clean,export-attribute" );
92  KGpgExport *exp = new KGpgExport(this, exportkeys, expOptions);
93  exp->setOutputTransaction(imp);
94 
95  imp->setGnuPGHome(m_tempdir->name());
96 
97  connect(imp, SIGNAL(done(int)), SLOT(slotReimportDone(int)));
98  imp->start();
99 }
100 
101 void
102 KGpgCaffPrivate::slotReimportDone(int result)
103 {
104  KGpgImport *imp = qobject_cast<KGpgImport *>(sender());
105 
106  if (result != KGpgTransaction::TS_OK) {
107  abortOperation(result);
108  } else {
109  bool ret = (imp->getImportedIds(0x1).count() == 1 + m_signers.count());
110 
111  if (!ret) {
112  abortOperation(-1);
113  } else {
114  KGpgSignUid *signuid = new KGpgSignUid(this, m_signers.first(), m_allids.first(), false, m_checklevel);
115  signuid->setGnuPGHome(m_tempdir->name());
116  signuid->setSecringFile(m_secringfile);
117  connect(signuid, SIGNAL(done(int)), SLOT(slotSigningFinished(int)));
118 
119  signuid->start();
120  }
121  }
122 
123  sender()->deleteLater();
124 }
125 
126 void
127 KGpgCaffPrivate::abortOperation(int result)
128 {
129  Q_Q(KGpgCaff);
130 
131  kDebug(2100) << "transaction" << sender() << "failed, result" << result;
132  m_tempdir.reset();
133 
134  emit q->aborted();
135 }
136 
137 void
138 KGpgCaffPrivate::checkNextLoop()
139 {
140  Q_Q(KGpgCaff);
141 
142  m_tempdir.reset();
143 
144  if (m_allids.isEmpty()) {
145  if (!m_noEncIds.isEmpty()) {
146  QStringList ids;
147 
148  foreach (const KGpgSignableNode *nd, m_noEncIds)
149  if (nd->getEmail().isEmpty())
150  ids << i18nc("%1 is the key id, %2 is the name and comment of the key or uid",
151  "%1: %2", nd->getId(), nd->getNameComment());
152  else
153  ids << i18nc("%1 is the key id, %2 is the name and comment of the key or uid, %3 is the email address of the uid",
154  "%1: %2 &lt;%3&gt;", nd->getId(), nd->getNameComment(), nd->getEmail());
155 
156  KMessageBox::detailedSorry(qobject_cast<QWidget *>(q->parent()),
157  i18np("No mail was sent for the following user id because it belongs to a key without encryption capability:",
158  "No mail was sent for the following user ids because they belong to keys without encryption capability:",
159  m_noEncIds.count()),
160  ids.join(QLatin1String("\n")));
161  }
162 
163  if (!m_alreadyIds.isEmpty()) {
164  QStringList ids;
165 
166  foreach (const KGpgSignableNode *nd, m_alreadyIds)
167  if (nd->getEmail().isEmpty())
168  ids << i18nc("%1 is the key id, %2 is the name and comment of the key or uid",
169  "%1: %2", nd->getId(), nd->getNameComment());
170  else
171  ids << i18nc("%1 is the key id, %2 is the name and comment of the key or uid, %3 is the email address of the uid",
172  "%1: %2 &lt;%3&gt;", nd->getId(), nd->getNameComment(), nd->getEmail());
173 
174  KMessageBox::detailedSorry(qobject_cast<QWidget *>(q->parent()),
175  i18np("No mail was sent for the following user id because it was already signed:",
176  "No mail was sent for the following user ids because they were already signed:",
177  m_alreadyIds.count()),
178  ids.join(QLatin1String("\n")));
179  }
180 
181  emit q->done();
182  } else {
183  reexportKey(m_allids.first());
184  }
185 }
186 
187 void
188 KGpgCaffPrivate::slotSigningFinished(int result)
189 {
190  sender()->deleteLater();
191 
192  if (result != KGpgTransaction::TS_OK) {
193  if ((result == KGpgSignTransactionHelper::TS_ALREADY_SIGNED) && (m_flags & KGpgCaff::IgnoreAlreadySigned)) {
194  m_alreadyIds << m_allids.takeFirst();
195  checkNextLoop();
196  } else {
197  abortOperation(result);
198  }
199  return;
200  }
201 
202  const KGpgSignableNode *uid = m_allids.first();
203 
204  // if there is no email address we can't send this out anyway, so don't bother.
205  // could be improved: if this is the only selected uid from this key go and select
206  // a proper mail address to send this to
207  if (uid->getEmail().isEmpty()) {
208  m_allids.removeFirst();
209  checkNextLoop();
210  }
211 
212  const KGpgKeyNode *key = uid->getKeyNode();
213 
214  int uidnum;
215 
216  if (uid == key) {
217  uidnum = -1;
218  } else {
219  uidnum = -uid->getId().toInt();
220  }
221 
222  KGpgDelUid::RemoveMode removeMode;
223  switch (KGpgSettings::mailUats()) {
224  case 0:
225  removeMode = KGpgDelUid::RemoveWithEmail;
226  break;
227  case 1:
228  if (uid == key) {
229  removeMode = KGpgDelUid::RemoveWithEmail;
230  } else {
231  // check if this is the first uid with email address
232  const KGpgSignableNode *otherUid;
233  int index = 1;
234  removeMode = KGpgDelUid::RemoveAllOther;
235 
236  while ( (otherUid = key->getUid(index++)) != NULL) {
237  if (otherUid == uid) {
238  removeMode = KGpgDelUid::RemoveWithEmail;
239  break;
240  }
241  if (!otherUid->getEmail().isEmpty())
242  break;
243  }
244  }
245  break;
246  case 2:
247  removeMode = KGpgDelUid::RemoveAllOther;
248  break;
249  default:
250  Q_ASSERT(0);
251  return;
252  }
253 
254  KGpgDelUid *deluid = new KGpgDelUid(this, key, uidnum, removeMode);
255 
256  deluid->setGnuPGHome(m_tempdir->name());
257 
258  connect(deluid, SIGNAL(done(int)), SLOT(slotDelUidFinished(int)));
259 
260  deluid->start();
261 }
262 
263 void
264 KGpgCaffPrivate::slotDelUidFinished(int result)
265 {
266  sender()->deleteLater();
267 
268  const KGpgSignableNode *uid = m_allids.first();
269  const KGpgKeyNode *key = uid->getKeyNode();
270 
271  if (result != KGpgTransaction::TS_OK) {
272  // it's no error if we tried to delete all other ids but there is no other id
273  if ((uid != key) || (result != KGpgDelUid::TS_NO_SUCH_UID)) {
274  abortOperation(result);
275  return;
276  }
277  }
278 
279  QStringList expOptions(QLatin1String( "--export-options" ));
280  expOptions << QLatin1String( "export-attribute" );
281 
282  KGpgExport *exp = new KGpgExport(this, QStringList(key->getId()), expOptions);
283 
284  exp->setGnuPGHome(m_tempdir->name());
285 
286  connect(exp, SIGNAL(done(int)), SLOT(slotExportFinished(int)));
287 
288  exp->start();
289 }
290 
291 void
292 KGpgCaffPrivate::slotExportFinished(int result)
293 {
294  sender()->deleteLater();
295 
296  if (result != KGpgTransaction::TS_OK) {
297  abortOperation(result);
298  return;
299  }
300 
301  const KGpgSignableNode *uid = m_allids.first();
302  const KGpgKeyNode *key = uid->getKeyNode();
303 
304  KGpgExport *exp = qobject_cast<KGpgExport *>(sender());
305  Q_ASSERT(exp != NULL);
306 
307  QString body = KGpgSettings::emailTemplate();
308  body.replace(QLatin1Char( '%' ) + i18nc("Email template placeholder for key id", "KEYID") + QLatin1Char( '%' ), key->getId());
309  body.replace(QLatin1Char( '%' ) + i18nc("Email template placeholder for key id", "UIDNAME") + QLatin1Char( '%' ), uid->getNameComment());
310 
311  body += QLatin1Char( '\n' ) + QLatin1String( exp->getOutputData() );
312 
313  KGpgEncrypt *enc = new KGpgEncrypt(this, QStringList(key->getId()), body, KGpgEncrypt::AsciiArmored | KGpgEncrypt::AllowUntrustedEncryption);
314 
315  // Set the home directory to make sure custom encrypt options
316  // as well as the "always encrypt to" setting are not honored.
317  enc->setGnuPGHome(m_tempdir->name());
318 
319  connect(enc, SIGNAL(done(int)), SLOT(slotTextEncrypted(int)));
320 
321  enc->start();
322 }
323 
324 void
325 KGpgCaffPrivate::slotTextEncrypted(int result)
326 {
327  sender()->deleteLater();
328 
329  switch (result) {
330  case KGpgTransaction::TS_OK: {
331  KGpgEncrypt *enc = qobject_cast<KGpgEncrypt *>(sender());
332  Q_ASSERT(enc != NULL);
333 
334  const QString text = enc->encryptedText().join(QLatin1String("\n"));
335 
336  const KGpgSignableNode *uid = m_allids.takeFirst();
337 
338  const QString email = uid->getEmail();
339  const QString keyid = uid->getKeyNode()->getId();
340 
341  KToolInvocation::invokeMailer(email, QString(), QString(),
342  i18nc("%1 is 64 bit key id (in hex), text is used as email subject", "Your key %1", keyid),
343  text);
344  break;
345  }
346  default:
347  abortOperation(result);
348  break;
349  case KGpgTransaction::TS_USER_ABORTED:
350  m_allids.clear();
351  break;
352  }
353 
354  checkNextLoop();
355 }
356 
357 KGpgCaff::KGpgCaff(QObject *parent, const KGpgSignableNode::List &ids, const QStringList &signids,
358  const int checklevel, const OperationFlags flags)
359  : QObject(parent),
360  d_ptr(new KGpgCaffPrivate(this, ids, signids, flags, static_cast<KGpgSignTransactionHelper::carefulCheck>(checklevel)))
361 {
362 }
363 
364 void
365 KGpgCaff::run()
366 {
367  Q_D(KGpgCaff);
368 
369  d->reexportKey(d->m_allids.first());
370 }
371 
372 #include "caff.moc"
373 #include "caff_p.moc"
KGpgCaff
Definition: caff.h:25
QList::clear
void clear()
caff_p.h
KGpgCaff::run
void run()
Definition: caff.cpp:365
KGpgCaffPrivate::KGpgCaffPrivate
KGpgCaffPrivate(KGpgCaff *parent, const KGpgSignableNode::List &ids, const QStringList &signers, const KGpgCaff::OperationFlags flags, const KGpgSignTransactionHelper::carefulCheck checklevel)
Definition: caff.cpp:37
QDir::toNativeSeparators
QString toNativeSeparators(const QString &pathName)
kgpgimport.h
KGpgSignTransactionHelper
helper class for key signing transactions
Definition: kgpgsigntransactionhelper.h:25
KGpgSettings::mailUats
static int mailUats()
Get Mail_Uats.
Definition: kgpgsettings.h:972
KGpgKeyNode::getUid
const KGpgSignableNode * getUid(const unsigned int index) const
get the user id or user attribute with the given number
Definition: KGpgKeyNode.cpp:312
kgpgdeluid.h
KGpgNode::getParentKeyNode
KGpgExpandableNode * getParentKeyNode() const
Returns the parent node in the key hierarchy.
Definition: KGpgNode.cpp:330
KGpgTransaction::TS_OK
everything went fine
Definition: kgpgtransaction.h:60
KGpgExport::getOutputData
const QByteArray & getOutputData() const
return the data read from standard output
Definition: kgpgexport.cpp:117
KGpgSettings::gpgConfigPath
static QString gpgConfigPath()
Get The path of the gpg configuration file.
Definition: kgpgsettings.h:288
KGpgDelUid::RemoveMode
RemoveMode
Definition: kgpgdeluid.h:37
KGpgEncrypt::AsciiArmored
output the data as printable ASCII as opposed to binary data
Definition: kgpgencrypt.h:38
KGpgExport
export one or more keys from keyring
Definition: kgpgexport.h:32
KGpgNode::getNameComment
virtual QString getNameComment() const
Definition: KGpgNode.cpp:51
KGpgKeyNode::getId
virtual QString getId() const
Definition: KGpgKeyNode.cpp:113
QObject::sender
QObject * sender() const
QFileInfo::setFile
void setFile(const QString &file)
QList::removeFirst
void removeFirst()
KGpgImport
import one or more keys into the keyring
Definition: kgpgimport.h:31
KGpgDelUid::RemoveWithEmail
remove only those other uids that have an email address
Definition: kgpgdeluid.h:40
KGpgCaff::OperationFlags
OperationFlags
Definition: caff.h:33
QStringList::join
QString join(const QString &separator) const
KGpgSignUid
transaction class to sign a single user id of a key
Definition: kgpgsignuid.h:28
KGpgTransaction::start
void start()
Start the operation.
Definition: kgpgtransaction.cpp:390
KGpgDelUid
Definition: kgpgdeluid.h:27
KGpgKeyNode
A public key with or without corresponding secret key.
Definition: KGpgKeyNode.h:33
QScopedPointer::reset
void reset(T *other)
KGpgNode::getType
virtual KgpgCore::KgpgItemType getType() const =0
Returns the item type of this object.
QList::count
int count(const T &value) const
KGpgSignableNode::getKeyNode
virtual KGpgKeyNode * getKeyNode(void)=0
returns the key node this node belongs to
KGpgSettings::emailTemplate
static QString emailTemplate()
Get This is the text of the email sent by the "Sign and Mail User ID" action.
Definition: kgpgsettings.h:953
QObject
KGpgCaff::IgnoreAlreadySigned
uids that are already signed will not be mailed again
Definition: caff.h:35
KGpgSignTransactionHelper::TS_ALREADY_SIGNED
user id is alredy signed by given key
Definition: kgpgsigntransactionhelper.h:46
QString::toInt
int toInt(bool *ok, int base) const
QList::isEmpty
bool isEmpty() const
QFileInfo::absoluteFilePath
QString absoluteFilePath() const
kgpgencrypt.h
QString::isEmpty
bool isEmpty() const
kgpginterface.h
QFileInfo::dir
QDir dir() const
QObject::deleteLater
void deleteLater()
QList::first
T & first()
QString
QList< KGpgSignableNode * >
kgpgexport.h
KGpgCaffPrivate::m_alreadyIds
KGpgSignableNode::const_List m_alreadyIds
ids already signed
Definition: caff_p.h:52
kgpgsignuid.h
QStringList
KGpgDelUid::RemoveAllOther
remove all other uids
Definition: kgpgdeluid.h:38
QFileInfo
KgpgCore::ITYPE_PAIR
key pair
Definition: kgpgkey.h:94
QLatin1Char
KGpgCaffPrivate::m_allids
KGpgSignableNode::List m_allids
Definition: caff_p.h:50
KGpgEncrypt::encryptedText
QStringList encryptedText() const
get decryption result
Definition: kgpgencrypt.cpp:81
KGpgCaffPrivate
Definition: caff_p.h:29
KGpgTransaction::TS_USER_ABORTED
the user aborted the transaction
Definition: kgpgtransaction.h:63
kgpgsettings.h
QScopedPointer::isNull
bool isNull() const
QString::replace
QString & replace(int position, int n, QChar after)
KGpgCaffPrivate::m_noEncIds
KGpgSignableNode::const_List m_noEncIds
keys without encryption capability that were skipped
Definition: caff_p.h:51
KGpgNode::toKeyNode
KGpgKeyNode * toKeyNode()
Definition: KGpgNode.cpp:94
KGpgSignTransactionHelper::setSecringFile
void setSecringFile(const QString &filename)
add a secret keyring file
Definition: kgpgsigntransactionhelper.cpp:136
QList::takeFirst
T takeFirst()
QLatin1String
KGpgCaff::KGpgCaff
KGpgCaff(QObject *parent, const KGpgSignableNode::List &ids, const QStringList &signids, const int checklevel=0, const OperationFlags flags=DefaultMode)
create a new object to sign and mail key ids
Definition: caff.cpp:357
KGpgNode::getId
virtual QString getId() const
Definition: KGpgNode.cpp:318
KGpgKeyNode.h
KGpgNode::getEmail
virtual QString getEmail() const
Definition: KGpgNode.cpp:300
caff.h
KGpgImport::getImportedIds
static QStringList getImportedIds(const QStringList &log, const int reason=-1)
get the full fingerprints of the imported keys
Definition: kgpgimport.cpp:59
KGpgExport::setOutputTransaction
void setOutputTransaction(KGpgTransaction *outt)
set the transaction the output is sent to
Definition: kgpgexport.cpp:102
KGpgSignableNode.h
KGpgDelUid::TS_NO_SUCH_UID
user id does not exist
Definition: kgpgdeluid.h:34
KGpgCaffPrivate::~KGpgCaffPrivate
~KGpgCaffPrivate()
Definition: caff.cpp:58
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KGpgSignTransactionHelper::carefulCheck
carefulCheck
Definition: kgpgsigntransactionhelper.h:38
KGpgEncrypt
encrypt the given text or files
Definition: kgpgencrypt.h:30
KGpgTransaction::setGnuPGHome
void setGnuPGHome(const QString &home)
sets the home directory of GnuPG called for this transaction
Definition: kgpgtransaction.cpp:663
KGpgSignableNode
An object that may have KGpgSignNode children.
Definition: KGpgSignableNode.h:31
KgpgInterface::getGpgSetting
QString getGpgSetting(const QString &name, const QString &configfile)
Definition: kgpginterface.cpp:38
KGpgEncrypt::AllowUntrustedEncryption
allow encryption with untrusted keys, ignored for symmetric encryption
Definition: kgpgencrypt.h:39
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:42:08 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kgpg

Skip menu "kgpg"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeutils API Reference

Skip menu "kdeutils API Reference"
  • ark
  • filelight
  • kcalc
  • kcharselect
  • kdf
  • kfloppy
  • kgpg
  • ktimer
  • kwallet
  • sweeper

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal