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

kleopatra

  • sources
  • kde-4.12
  • kdepim
  • kleopatra
  • commands
changeroottrustcommand.cpp
Go to the documentation of this file.
1 /* -*- mode: c++; c-basic-offset:4 -*-
2  commands/changeroottrustcommand.cpp
3 
4  This file is part of Kleopatra, the KDE keymanager
5  Copyright (c) 2010 Klarälvdalens Datakonsult AB
6 
7  Kleopatra 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  Kleopatra is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21  In addition, as a special exception, the copyright holders give
22  permission to link the code of this program with any edition of
23  the Qt library by Trolltech AS, Norway (or with modified versions
24  of Qt that use the same license as Qt), and distribute linked
25  combinations including the two. You must obey the GNU General
26  Public License in all respects for all of the code used other than
27  Qt. If you modify this file, you may extend this exception to
28  your version of the file, but you are not obligated to do so. If
29  you do not wish to do so, delete this exception statement from
30  your version.
31 */
32 
33 #include <config-kleopatra.h>
34 
35 #include "changeroottrustcommand.h"
36 #include "command_p.h"
37 
38 #include <models/keycache.h>
39 
40 #include <utils/gnupg-helper.h>
41 
42 #include <KDebug>
43 #include <KLocale>
44 #include <KSaveFile>
45 
46 #include <QRegExp>
47 #include <QThread>
48 #include <QMutex>
49 #include <QMutexLocker>
50 #include <QString>
51 #include <QStringList>
52 #include <QByteArray>
53 #include <QFile>
54 #include <QDir>
55 #include <QProcess>
56 
57 #include <gpgme++/key.h>
58 
59 #include <cassert>
60 
61 using namespace Kleo;
62 using namespace Kleo::Commands;
63 using namespace GpgME;
64 
65 class ChangeRootTrustCommand::Private : public QThread, public Command::Private {
66  Q_OBJECT
67 private:
68  friend class ::Kleo::Commands::ChangeRootTrustCommand;
69  ChangeRootTrustCommand * q_func() const { return static_cast<ChangeRootTrustCommand*>( q ); }
70 public:
71  explicit Private( ChangeRootTrustCommand * qq, KeyListController * c )
72  : QThread(), Command::Private( qq, c ),
73  mutex(),
74  trust( Key::Ultimate ),
75  trustListFile( QDir( gnupgHomeDirectory() ).absoluteFilePath( QLatin1String("trustlist.txt") ) ),
76  canceled( false )
77  {
78 
79  }
80 
81 private:
82  void init() {
83  q->setWarnWhenRunningAtShutdown( false );
84  connect( this, SIGNAL(finished()), q_func(), SLOT(slotOperationFinished()) );
85  }
86 
87  /* reimp */ void run();
88 
89 private:
90  void slotOperationFinished() {
91  KeyCache::mutableInstance()->enableFileSystemWatcher( true );
92  if ( error.isEmpty() )
93  KeyCache::mutableInstance()->reload( GpgME::CMS );
94  else
95  Command::Private::error( i18n("Failed to update the trust database:\n"
96  "%1", error ),
97  i18n("Root Trust Update Failed") );
98  Command::Private::finished();
99  }
100 
101 private:
102  mutable QMutex mutex;
103  Key::OwnerTrust trust;
104  QString trustListFile;
105  QString gpgConfPath;
106  QString error;
107  volatile bool canceled;
108 };
109 
110 ChangeRootTrustCommand::Private * ChangeRootTrustCommand::d_func() { return static_cast<Private*>( d.get() ); }
111 const ChangeRootTrustCommand::Private * ChangeRootTrustCommand::d_func() const { return static_cast<const Private*>( d.get() ); }
112 
113 #define q q_func()
114 #define d d_func()
115 
116 ChangeRootTrustCommand::ChangeRootTrustCommand( KeyListController * p )
117  : Command( new Private( this, p ) )
118 {
119  d->init();
120 }
121 
122 ChangeRootTrustCommand::ChangeRootTrustCommand( QAbstractItemView * v, KeyListController * p )
123  : Command( v, new Private( this, p ) )
124 {
125  d->init();
126 }
127 
128 ChangeRootTrustCommand::ChangeRootTrustCommand( const Key & key, KeyListController * p )
129  : Command( new Private( this, p ) )
130 {
131  assert( !key.isNull() );
132  d->init();
133  setKey( key );
134 }
135 
136 ChangeRootTrustCommand::ChangeRootTrustCommand( const Key & key, QAbstractItemView * v, KeyListController * p )
137  : Command( v, new Private( this, p ) )
138 {
139  assert( !key.isNull() );
140  d->init();
141  setKey( key );
142 }
143 
144 ChangeRootTrustCommand::~ChangeRootTrustCommand() {}
145 
146 void ChangeRootTrustCommand::setTrust( Key::OwnerTrust trust ) {
147  assert( !d->isRunning() );
148  const QMutexLocker locker( &d->mutex );
149  d->trust = trust;
150 }
151 
152 Key::OwnerTrust ChangeRootTrustCommand::trust() const {
153  const QMutexLocker locker( &d->mutex );
154  return d->trust;
155 }
156 
157 void ChangeRootTrustCommand::setTrustListFile( const QString & trustListFile ) {
158  assert( !d->isRunning() );
159  const QMutexLocker locker( &d->mutex );
160  d->trustListFile = trustListFile;
161 }
162 
163 QString ChangeRootTrustCommand::trustListFile() const {
164  const QMutexLocker locker( &d->mutex );
165  return d->trustListFile;
166 }
167 
168 void ChangeRootTrustCommand::doStart() {
169  const std::vector<Key> keys = d->keys();
170  Key key;
171  if ( keys.size() == 1 )
172  key = keys.front();
173  else
174  kWarning() << "can only work with one certificate at a time";
175 
176  if ( key.isNull() ) {
177  d->Command::Private::finished();
178  return;
179  }
180 
181  d->gpgConfPath = gpgConfPath();
182  KeyCache::mutableInstance()->enableFileSystemWatcher( false );
183  d->start();
184 }
185 
186 
187 void ChangeRootTrustCommand::doCancel() {
188  const QMutexLocker locker( &d->mutex );
189  d->canceled = true;
190 }
191 
192 static QString change_trust_file( const QString & trustListFile, const QString & key, Key::OwnerTrust trust );
193 static QString run_gpgconf_reload_gpg_agent( const QString & gpgConfPath );
194 
195 void ChangeRootTrustCommand::Private::run() {
196 
197  QMutexLocker locker( &mutex );
198 
199  const QString key = QString::fromLatin1( keys().front().primaryFingerprint() );
200  const Key::OwnerTrust trust = this->trust;
201  const QString trustListFile = this->trustListFile;
202  const QString gpgConfPath = this->gpgConfPath;
203 
204  locker.unlock();
205 
206  QString err = change_trust_file( trustListFile, key, trust );
207  if ( err.isEmpty() )
208  err = run_gpgconf_reload_gpg_agent( gpgConfPath );
209 
210  locker.relock();
211 
212  this->error = err;
213 
214 }
215 
216 static QString add_colons( const QString & fpr ) {
217  QString result;
218  result.reserve( fpr.size() / 2 * 3 + 1 );
219  bool needColon = false;
220  Q_FOREACH( QChar ch, fpr ) {
221  result += ch;
222  if ( needColon )
223  result += QLatin1Char(':') ;
224  needColon = !needColon;
225  }
226  if ( result.endsWith( QLatin1Char(':') ) )
227  result.chop(1);
228  return result;
229 }
230 
231 namespace {
232 
233  // fix stupid default-finalize behaviour...
234  class KFixedSaveFile : public KSaveFile {
235  public:
236  explicit KFixedSaveFile( const QString & fileName )
237  : KSaveFile( fileName ) {}
238  ~KFixedSaveFile() {
239  abort();
240  }
241 
242  };
243 
244 }
245 
246 // static
247 QString change_trust_file( const QString & trustListFile, const QString & key, Key::OwnerTrust trust )
248 {
249  QList<QByteArray> trustListFileContents;
250 
251  {
252  QFile in( trustListFile );
253  if ( in.exists() ) // non-existence is not fatal...
254  if ( in.open( QIODevice::ReadOnly ) )
255  trustListFileContents = in.readAll().split( '\n' );
256  else // ...but failure to open an existing file _is_
257  return i18n( "Cannot open existing file \"%1\" for reading: %2",
258  trustListFile, in.errorString() );
259  // close, so KSaveFile doesn't clobber the original
260  }
261 
262 
263  KFixedSaveFile out( trustListFile );
264  if ( !out.open() )
265  return i18n("Cannot open file \"%1\" for reading and writing: %2",
266  out.QFile::fileName() /*sic!*/, out.errorString() );
267 
268  if ( !out.setPermissions( QFile::ReadOwner|QFile::WriteOwner ) )
269  return i18n("Cannot set restrictive permissions on file %1: %2",
270  out.QFile::fileName() /*sic!*/, out.errorString() );
271 
272  const QString keyColon = add_colons( key );
273 
274  kDebug() << qPrintable( key ) << " -> " << qPrintable( keyColon );
275 
276  // ( 1) ( 2 ) ( 3 )( 4)
277  QRegExp rx( QLatin1String("\\s*(!?)\\s*([a-fA-F0-9]{40}|(?:[a-fA-F0-9]{2}:){19}[a-fA-F0-9]{2})\\s*([SsPp*])(.*)") );
278  bool found = false;
279 
280  Q_FOREACH( const QByteArray & rawLine, trustListFileContents ) {
281 
282  const QString line = QString::fromLatin1( rawLine.data(), rawLine.size() );
283  if ( !rx.exactMatch( line ) ) {
284  kDebug() << "line \"" << rawLine.data() << "\" does not match";
285  out.write( rawLine + '\n' );
286  continue;
287  }
288  const QString cap2 = rx.cap(2);
289  if ( cap2 != key && cap2 != keyColon ) {
290  kDebug() << qPrintable( key ) << " != "
291  << qPrintable( cap2 ) << " != "
292  << qPrintable( keyColon );
293  out.write( rawLine + '\n' );
294  continue;
295  }
296  found = true;
297  const bool disabled = rx.cap(1) == QLatin1String("!");
298  const QByteArray flags = rx.cap(3).toLatin1();
299  const QByteArray rests = rx.cap(4).toLatin1();
300  if ( trust == Key::Ultimate )
301  if ( !disabled ) // unchanged
302  out.write( rawLine + '\n' );
303  else
304  out.write( keyColon.toLatin1() + ' ' + flags + rests + '\n' );
305  else if ( trust == Key::Never )
306  if ( disabled ) // unchanged
307  out.write( rawLine + '\n' );
308  else
309  out.write( '!' + keyColon.toLatin1() + ' ' + flags + rests + '\n' );
310  // else: trust == Key::Unknown
311  // -> don't write - ie.erase
312  }
313 
314  if ( !found ) // add
315  if ( trust == Key::Ultimate )
316  out.write( keyColon.toLatin1() + ' ' + 'S' + '\n' );
317  else if ( trust == Key::Never )
318  out.write( '!' + keyColon.toLatin1() + ' ' + 'S' + '\n' );
319 
320  if ( !out.finalize() )
321  return i18n( "Failed to move file %1 to its final destination, %2: %3",
322  out.QFile::fileName(), trustListFile, out.errorString() );
323 
324  return QString();
325 
326 }
327 
328 // static
329 QString run_gpgconf_reload_gpg_agent( const QString & gpgConfPath )
330 {
331  if ( gpgConfPath.isEmpty() )
332  return i18n("Could not find gpgconf executable");
333 
334  QProcess p;
335  p.start( gpgConfPath, QStringList() << QLatin1String("--reload") << QLatin1String("gpg-agent") );
336  kDebug() << "starting " << qPrintable( gpgConfPath )
337  << " --reload gpg-agent";
338  p.waitForFinished( -1 );
339  kDebug() << "done";
340  if ( p.error() == QProcess::UnknownError )
341  return QString();
342  else
343  return i18n("\"gpgconf --reload gpg-agent\" failed: %1", p.errorString() );
344 }
345 
346 #undef q_func
347 #undef d_func
348 
349 #include "moc_changeroottrustcommand.cpp"
350 #include "changeroottrustcommand.moc"
flags
static const char * flags[]
Definition: readerstatus.cpp:115
Kleo::Command::Private
Definition: commands/command_p.h:52
Kleo::gnupgHomeDirectory
QString gnupgHomeDirectory()
Definition: gnupg-helper.cpp:56
change_trust_file
static QString change_trust_file(const QString &trustListFile, const QString &key, Key::OwnerTrust trust)
Definition: changeroottrustcommand.cpp:247
Kleo::Commands::ChangeRootTrustCommand::ChangeRootTrustCommand
ChangeRootTrustCommand(KeyListController *parent)
Definition: changeroottrustcommand.cpp:116
changeroottrustcommand.h
Kleo::KeyListController
Definition: keylistcontroller.h:55
Kleo::Commands::ChangeRootTrustCommand::trustListFile
QString trustListFile() const
Definition: changeroottrustcommand.cpp:163
q
#define q
Definition: changeroottrustcommand.cpp:113
Kleo::Command::d
kdtools::pimpl_ptr< Private > d
Definition: commands/command.h:129
Kleo::Commands::ChangeRootTrustCommand::setTrust
void setTrust(GpgME::Key::OwnerTrust trust)
Definition: changeroottrustcommand.cpp:146
Kleo::Commands::ChangeRootTrustCommand
Definition: changeroottrustcommand.h:43
add_colons
static QString add_colons(const QString &fpr)
Definition: changeroottrustcommand.cpp:216
Kleo::Class::CMS
Definition: classify.h:48
Kleo::Commands::ChangeRootTrustCommand::~ChangeRootTrustCommand
~ChangeRootTrustCommand()
Definition: changeroottrustcommand.cpp:144
mutex
static QMutex mutex
Definition: sessiondata.cpp:48
run_gpgconf_reload_gpg_agent
static QString run_gpgconf_reload_gpg_agent(const QString &gpgConfPath)
Definition: changeroottrustcommand.cpp:329
Kleo::Command::setKey
void setKey(const GpgME::Key &key)
Definition: commands/command.cpp:172
gnupg-helper.h
command_p.h
Kleo::Commands::ChangeRootTrustCommand::trust
GpgME::Key::OwnerTrust trust() const
Definition: changeroottrustcommand.cpp:152
Kleo::Commands::ChangeRootTrustCommand::setTrustListFile
void setTrustListFile(const QString &file)
Definition: changeroottrustcommand.cpp:157
Kleo::Command::Private::finished
void finished()
Definition: commands/command_p.h:72
Kleo::gpgConfPath
QString gpgConfPath()
Definition: gnupg-helper.cpp:78
Kleo::Formatting::OwnerTrust
Definition: formatting.h:79
keycache.h
d
#define d
Definition: changeroottrustcommand.cpp:114
Kleo::Command
Definition: commands/command.h:58
QList
Definition: commands/command.h:46
Kleo::KeyCache::mutableInstance
static boost::shared_ptr< KeyCache > mutableInstance()
Definition: keycache.cpp:193
Kleo::Command::Private::error
void error(const QString &text, const QString &caption=QString(), KMessageBox::Options options=KMessageBox::Notify) const
Definition: commands/command_p.h:83
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:56:40 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kleopatra

Skip menu "kleopatra"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

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