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

KNewStuff

  • sources
  • kde-4.12
  • kdelibs
  • knewstuff
  • knewstuff3
  • core
knewstuff3/core/security.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KNewStuff2.
3  Copyright (c) 2004, 2005 Andras Mantia <amantia@kde.org>
4  Copyright (c) 2007 Josef Spillner <spillner@kde.org>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either
9  version 2.1 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 //app includes
21 #include "security.h"
22 
23 //qt includes
24 #include <QtCore/QFile>
25 #include <QtCore/QFileInfo>
26 #include <QtCore/QPointer>
27 #include <QtCore/QStringList>
28 #include <QtCore/QTextIStream>
29 #include <QtCore/QTimer>
30 
31 //kde includes
32 #include <kdebug.h>
33 #include <kinputdialog.h>
34 #include <klocale.h>
35 #include <kcodecs.h>
36 #include <kmessagebox.h>
37 #include <kpassworddialog.h>
38 #include <kprocess.h>
39 #include <kstandarddirs.h>
40 
41 using namespace KNS3;
42 
43 static QString gpgExecutable()
44 {
45  QString gpgExe = KStandardDirs::findExe( "gpg" );
46  if ( gpgExe.isEmpty() )
47  gpgExe = KStandardDirs::findExe( "gpg2" );
48  if ( gpgExe.isEmpty() )
49  return QLatin1String( "gpg" );
50  return gpgExe;
51 }
52 
53 Security::Security()
54 {
55  m_keysRead = false;
56  m_gpgRunning = false;
57  readKeys();
58  readSecretKeys();
59 }
60 
61 
62 Security::~Security()
63 {
64 }
65 
66 void Security::readKeys()
67 {
68  if (m_gpgRunning) {
69  QTimer::singleShot(5, this, SLOT(readKeys()));
70  return;
71  }
72  m_runMode = List;
73  m_keys.clear();
74  m_process = new KProcess();
75  *m_process << gpgExecutable()
76  << "--no-secmem-warning"
77  << "--no-tty"
78  << "--with-colon"
79  << "--list-keys";
80  connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)),
81  this, SLOT(slotFinished(int,QProcess::ExitStatus)));
82  connect(m_process, SIGNAL(readyReadStandardOutput()),
83  this, SLOT(slotReadyReadStandardOutput()));
84  m_process->start();
85  if (!m_process->waitForStarted()) {
86  KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and retrieve the available keys. Make sure that <i>gpg</i> is installed, otherwise verification of downloaded resources will not be possible.</qt>"));
87  delete m_process;
88  m_process = 0;
89  } else
90  m_gpgRunning = true;
91 }
92 
93 void Security::readSecretKeys()
94 {
95  if (m_gpgRunning) {
96  QTimer::singleShot(5, this, SLOT(readSecretKeys()));
97  return;
98  }
99  m_runMode = ListSecret;
100  m_process = new KProcess();
101  *m_process << gpgExecutable()
102  << "--no-secmem-warning"
103  << "--no-tty"
104  << "--with-colon"
105  << "--list-secret-keys";
106  connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)),
107  this, SLOT(slotFinished(int,QProcess::ExitStatus)));
108  connect(m_process, SIGNAL(readyReadStandardOutput()),
109  this, SLOT(slotReadyReadStandardOutput()));
110  m_process->start();
111  if (!m_process->waitForStarted()) {
112  delete m_process;
113  m_process = 0;
114  } else
115  m_gpgRunning = true;
116 }
117 
118 void Security::slotFinished(int exitCode, QProcess::ExitStatus exitStatus)
119 {
120  if (exitStatus != QProcess::NormalExit) {
121  m_gpgRunning = false;
122  delete m_process;
123  m_process = 0;
124  return;
125  }
126  switch (m_runMode) {
127  case ListSecret:
128  m_keysRead = true;
129  break;
130  case Verify: emit validityResult(m_result);
131  break;
132  case Sign: emit fileSigned(m_result);
133  break;
134 
135  }
136  m_gpgRunning = false;
137  delete m_process;
138  m_process = 0;
139 
140  Q_UNUSED(exitCode)
141 }
142 
143 void Security::slotReadyReadStandardOutput()
144 {
145  QString data;
146  while (m_process->canReadLine()) {
147  data = QString::fromLocal8Bit(m_process->readLine());
148  switch (m_runMode) {
149  case List:
150  case ListSecret:
151  if (data.startsWith(QLatin1String("pub")) || data.startsWith(QLatin1String("sec"))) {
152  KeyStruct key;
153  if (data.startsWith(QLatin1String("pub")))
154  key.secret = false;
155  else
156  key.secret = true;
157  QStringList line = data.split(':', QString::KeepEmptyParts);
158  key.id = line[4];
159  QString shortId = key.id.right(8);
160  QString trustStr = line[1];
161  key.trusted = false;
162  if (trustStr == "u" || trustStr == "f")
163  key.trusted = true;
164  data = line[9];
165  key.mail = data.section('<', -1, -1);
166  key.mail.truncate(key.mail.length() - 1);
167  key.name = data.section('<', 0, 0);
168  if (key.name.contains("("))
169  key.name = key.name.section('(', 0, 0);
170  m_keys[shortId] = key;
171  }
172  break;
173  case Verify:
174  data = data.section(']', 1, -1).trimmed();
175  if (data.startsWith(QLatin1String("GOODSIG"))) {
176  m_result &= SIGNED_BAD_CLEAR;
177  m_result |= SIGNED_OK;
178  QString id = data.section(' ', 1 , 1).right(8);
179  if (!m_keys.contains(id)) {
180  m_result |= UNKNOWN;
181  } else {
182  m_signatureKey = m_keys[id];
183  }
184  } else
185  if (data.startsWith(QLatin1String("NO_PUBKEY"))) {
186  m_result &= SIGNED_BAD_CLEAR;
187  m_result |= UNKNOWN;
188  } else
189  if (data.startsWith(QLatin1String("BADSIG"))) {
190  m_result |= SIGNED_BAD;
191  QString id = data.section(' ', 1 , 1).right(8);
192  if (!m_keys.contains(id)) {
193  m_result |= UNKNOWN;
194  } else {
195  m_signatureKey = m_keys[id];
196  }
197  } else
198  if (data.startsWith(QLatin1String("TRUST_ULTIMATE"))) {
199  m_result &= SIGNED_BAD_CLEAR;
200  m_result |= TRUSTED;
201  }
202  break;
203 
204  case Sign:
205  if (data.contains("passphrase.enter")) {
206  KeyStruct key = m_keys[m_secretKey];
207  QPointer<KPasswordDialog> dlg = new KPasswordDialog(NULL);
208  dlg->setPrompt(i18n("<qt>Enter passphrase for key <b>0x%1</b>, belonging to<br /><i>%2&lt;%3&gt;</i><br />:</qt>", m_secretKey, key.name, key.mail));
209  if (dlg->exec()) {
210  m_process->write(dlg->password().toLocal8Bit() + '\n');
211  delete dlg;
212  } else {
213  m_result |= BAD_PASSPHRASE;
214  m_process->kill();
215  delete dlg;
216  return;
217  }
218  } else
219  if (data.contains("BAD_PASSPHRASE")) {
220  m_result |= BAD_PASSPHRASE;
221  }
222  break;
223  }
224  }
225 }
226 
227 void Security::checkValidity(const QString& filename)
228 {
229  m_fileName = filename;
230  slotCheckValidity();
231 }
232 
233 void Security::slotCheckValidity()
234 {
235  if (!m_keysRead || m_gpgRunning) {
236  QTimer::singleShot(5, this, SLOT(slotCheckValidity()));
237  return;
238  }
239  if (m_keys.count() == 0) {
240  emit validityResult(-1);
241  return;
242  }
243 
244  m_result = 0;
245  m_runMode = Verify;
246  QFileInfo f(m_fileName);
247  //check the MD5 sum
248  QString md5sum;
249  const char* c = "";
250  KMD5 context(c);
251  QFile file(m_fileName);
252  if (file.open(QIODevice::ReadOnly)) {
253  context.reset();
254  context.update(file);
255  md5sum = context.hexDigest();
256  file.close();
257  }
258  file.setFileName(f.path() + "/md5sum");
259  if (file.open(QIODevice::ReadOnly)) {
260  QByteArray md5sum_file;
261  file.readLine(md5sum_file.data(), 50);
262  if (!md5sum_file.isEmpty() && QString(md5sum_file).startsWith(md5sum))
263  m_result |= MD5_OK;
264  file.close();
265  }
266  m_result |= SIGNED_BAD;
267  m_signatureKey.id = "";
268  m_signatureKey.name = "";
269  m_signatureKey.mail = "";
270  m_signatureKey.trusted = false;
271 
272  //verify the signature
273  m_process = new KProcess();
274  *m_process << gpgExecutable()
275  << "--no-secmem-warning"
276  << "--status-fd=2"
277  << "--command-fd=0"
278  << "--verify"
279  << f.path() + "/signature"
280  << m_fileName;
281  connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)),
282  this, SLOT(slotFinished(int,QProcess::ExitStatus)));
283  connect(m_process, SIGNAL(readyReadStandardOutput()),
284  this, SLOT(slotReadyReadStandardOutput()));
285  m_process->start();
286  if (m_process->waitForStarted())
287  m_gpgRunning = true;
288  else {
289  KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and check the validity of the file. Make sure that <i>gpg</i> is installed, otherwise verification of downloaded resources will not be possible.</qt>"));
290  emit validityResult(0);
291  delete m_process;
292  m_process = 0;
293  }
294 }
295 
296 void Security::signFile(const QString &fileName)
297 {
298  m_fileName = fileName;
299  slotSignFile();
300 }
301 
302 void Security::slotSignFile()
303 {
304  if (!m_keysRead || m_gpgRunning) {
305  QTimer::singleShot(5, this, SLOT(slotSignFile()));
306  return;
307  }
308 
309  QStringList secretKeys;
310  for (QMap<QString, KeyStruct>::Iterator it = m_keys.begin(); it != m_keys.end(); ++it) {
311  if (it.value().secret)
312  secretKeys.append(it.key());
313  }
314 
315  if (secretKeys.count() == 0) {
316  emit fileSigned(-1);
317  return;
318  }
319 
320  m_result = 0;
321  QFileInfo f(m_fileName);
322 
323  //create the MD5 sum
324  QString md5sum;
325  const char* c = "";
326  KMD5 context(c);
327  QFile file(m_fileName);
328  if (file.open(QIODevice::ReadOnly)) {
329  context.reset();
330  context.update(file);
331  md5sum = context.hexDigest();
332  file.close();
333  }
334  file.setFileName(f.path() + "/md5sum");
335  if (file.open(QIODevice::WriteOnly)) {
336  QTextStream stream(&file);
337  stream << md5sum;
338  m_result |= MD5_OK;
339  file.close();
340  }
341 
342  if (secretKeys.count() > 1) {
343  bool ok;
344  secretKeys = KInputDialog::getItemList(i18n("Select Signing Key"), i18n("Key used for signing:"), secretKeys, QStringList(secretKeys[0]), false, &ok);
345  if (ok)
346  m_secretKey = secretKeys[0];
347  else {
348  emit fileSigned(0);
349  return;
350  }
351  } else
352  m_secretKey = secretKeys[0];
353 
354  //verify the signature
355  m_process = new KProcess();
356  *m_process << gpgExecutable()
357  << "--no-secmem-warning"
358  << "--status-fd=2"
359  << "--command-fd=0"
360  << "--no-tty"
361  << "--detach-sign"
362  << "-u"
363  << m_secretKey
364  << "-o"
365  << f.path() + "/signature"
366  << m_fileName;
367  connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)),
368  this, SLOT(slotFinished(int,QProcess::ExitStatus)));
369  connect(m_process, SIGNAL(readyReadStandardOutput()),
370  this, SLOT(slotReadyReadStandardOutput()));
371  m_runMode = Sign;
372  m_process->start();
373  if (m_process->waitForStarted())
374  m_gpgRunning = true;
375  else {
376  KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and sign the file. Make sure that <i>gpg</i> is installed, otherwise signing of the resources will not be possible.</qt>"));
377  emit fileSigned(0);
378  delete m_process;
379  m_process = 0;
380  }
381 }
382 
383 #include "security.moc"
i18n
QString i18n(const char *text)
KNS3::Security::readSecretKeys
void readSecretKeys()
Reads the available secret keys.
Definition: knewstuff3/core/security.cpp:93
KProcess
kdebug.h
KNS3::Security::SIGNED_BAD
The file is signed with a good signature.
Definition: knewstuff3/core/security.h:87
KNS3::Security::~Security
~Security()
Definition: knewstuff3/core/security.cpp:62
KNS3::Security::readKeys
void readKeys()
Reads the available public keys.
Definition: knewstuff3/core/security.cpp:66
QString
klocale.h
KNS3::Security::signFile
void signFile(const QString &fileName)
Creates a signature and an md5sum file for the fileName and packs everything into a gzipped tarball...
Definition: knewstuff3/core/security.cpp:296
KeyStruct
Definition: knewstuff2/core/security.h:27
KNS3::Security::TRUSTED
The file is signed with a bad signature.
Definition: knewstuff3/core/security.h:88
kprocess.h
KNS3::Security::BAD_PASSPHRASE
used to clear the SIGNED_BAD flag
Definition: knewstuff3/core/security.h:91
KInputDialog::getItemList
QStringList getItemList(const QString &caption, const QString &label, const QStringList &list=QStringList(), const QStringList &select=QStringList(), bool multiple=false, bool *ok=0, QWidget *parent=0)
KNS3::Security::MD5_OK
Definition: knewstuff3/core/security.h:85
QStringList
KNS3::Security::fileSigned
void fileSigned(int result)
Sent when the signing is done.
KMD5::update
void update(const char *in, int len=-1)
KeyStruct::id
QString id
Definition: knewstuff2/core/security.h:28
KeyStruct::name
QString name
Definition: knewstuff2/core/security.h:29
KNS3::Security::SIGNED_OK
The MD5 sum check is OK.
Definition: knewstuff3/core/security.h:86
KMD5::hexDigest
QByteArray hexDigest()
KNS3::Security::UNKNOWN
The signature is trusted.
Definition: knewstuff3/core/security.h:89
KNS3::Security::slotSignFile
void slotSignFile()
Creates a signature and an md5sum file for the m_fileName and packs everything into a gzipped tarball...
Definition: knewstuff3/core/security.cpp:302
KProcess::start
void start()
KeyStruct::secret
bool secret
Definition: knewstuff2/core/security.h:32
KMD5
ok
KGuiItem ok()
kinputdialog.h
KPasswordDialog
kpassworddialog.h
KNS3::Security::validityResult
void validityResult(int result)
Sent when the validity check is done.
KNS3::Security::checkValidity
void checkValidity(const QString &fileName)
Verifies the integrity and the signature of a tarball file.
Definition: knewstuff3/core/security.cpp:227
KNS3::Security::slotCheckValidity
void slotCheckValidity()
Verifies the integrity and the signature of a tarball file (see m_fileName).
Definition: knewstuff3/core/security.cpp:233
kstandarddirs.h
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
KMD5::reset
void reset()
KeyStruct::trusted
bool trusted
Definition: knewstuff2/core/security.h:31
security.h
kcodecs.h
gpgExecutable
static QString gpgExecutable()
Definition: knewstuff3/core/security.cpp:43
KNS3::Security::SIGNED_BAD_CLEAR
The key is unknown.
Definition: knewstuff3/core/security.h:90
kmessagebox.h
KMessageBox::error
static void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
QMap
KeyStruct::mail
QString mail
Definition: knewstuff2/core/security.h:30
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:50:49 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KNewStuff

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

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