1 /* -*- mode: c++; c-basic-offset:4 -*-
2 crypto/certificateresolver.cpp
4 This file is part of Kleopatra, the KDE keymanager
5 Copyright (c) 2007 Klarälvdalens Datakonsult AB
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.
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.
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
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
33 #include <config-kleopatra.h>
35 #include "certificateresolver.h"
37 #include <models/keycache.h>
39 #include <gpgme++/key.h>
42 #include <KConfigGroup>
43 #include <QRegularExpression>
49 #include <boost/bind.hpp>
55 using namespace Kleo::Crypto
;
56 using namespace boost
;
57 using namespace GpgME
;
58 using namespace KMime::Types
;
59 using namespace KMime::HeaderParsing
;
61 std::vector
< std::vector
<Key
> > CertificateResolver::resolveRecipients(const std::vector
<Mailbox
> &recipients
, Protocol proto
)
63 std::vector
< std::vector
<Key
> > result
;
64 std::transform(recipients
.begin(), recipients
.end(),
65 std::back_inserter(result
), boost::bind(&resolveRecipient
, _1
, proto
));
69 std::vector
<Key
> CertificateResolver::resolveRecipient(const Mailbox
&recipient
, Protocol proto
)
71 std::vector
<Key
> result
= KeyCache::instance()->findByEMailAddress(recipient
.address());
72 std::vector
<Key
>::iterator end
= std::remove_if(result
.begin(), result
.end(),
73 !boost::bind(&Key::canEncrypt
, _1
));
75 if (proto
!= UnknownProtocol
)
76 end
= std::remove_if(result
.begin(), end
,
77 boost::bind(&Key::protocol
, _1
) != proto
);
79 result
.erase(end
, result
.end());
83 std::vector
< std::vector
<Key
> > CertificateResolver::resolveSigners(const std::vector
<Mailbox
> &signers
, Protocol proto
)
85 std::vector
< std::vector
<Key
> > result
;
86 std::transform(signers
.begin(), signers
.end(),
87 std::back_inserter(result
), boost::bind(&resolveSigner
, _1
, proto
));
91 std::vector
<Key
> CertificateResolver::resolveSigner(const Mailbox
&signer
, Protocol proto
)
93 std::vector
<Key
> result
= KeyCache::instance()->findByEMailAddress(signer
.address());
94 std::vector
<Key
>::iterator end
95 = std::remove_if(result
.begin(), result
.end(),
96 !boost::bind(&Key::hasSecret
, _1
));
97 end
= std::remove_if(result
.begin(), end
,
98 !boost::bind(&Key::canReallySign
, _1
));
99 if (proto
!= UnknownProtocol
)
100 end
= std::remove_if(result
.begin(), end
,
101 boost::bind(&Key::protocol
, _1
) != proto
);
102 result
.erase(end
, result
.end());
106 class KConfigBasedRecipientPreferences::Private
108 friend class ::Kleo::Crypto::KConfigBasedRecipientPreferences
;
109 KConfigBasedRecipientPreferences
*const q
;
111 explicit Private(const KSharedConfigPtr
&config
, KConfigBasedRecipientPreferences
*qq
);
115 void ensurePrefsParsed() const;
119 KSharedConfigPtr m_config
;
121 mutable QHash
<QByteArray
, QByteArray
> pgpPrefs
;
122 mutable QHash
<QByteArray
, QByteArray
> cmsPrefs
;
123 mutable bool m_parsed
;
124 mutable bool m_dirty
;
127 KConfigBasedRecipientPreferences::Private::Private(const KSharedConfigPtr
&config
, KConfigBasedRecipientPreferences
*qq
) : q(qq
), m_config(config
), m_parsed(false), m_dirty(false)
132 KConfigBasedRecipientPreferences::Private::~Private()
137 void KConfigBasedRecipientPreferences::Private::writePrefs()
142 const QSet
<QByteArray
> keys
= pgpPrefs
.keys().toSet() + cmsPrefs
.keys().toSet();
145 Q_FOREACH (const QByteArray
&i
, keys
) {
146 KConfigGroup
group(m_config
, QStringLiteral("EncryptionPreference_%1").arg(n
++));
147 group
.writeEntry("email", i
);
148 const QByteArray pgp
= pgpPrefs
.value(i
);
149 if (!pgp
.isEmpty()) {
150 group
.writeEntry("pgpCertificate", pgp
);
152 const QByteArray cms
= cmsPrefs
.value(i
);
153 if (!cms
.isEmpty()) {
154 group
.writeEntry("cmsCertificate", cms
);
160 void KConfigBasedRecipientPreferences::Private::ensurePrefsParsed() const
165 const QStringList groups
= m_config
->groupList().filter(QRegularExpression(QStringLiteral("^EncryptionPreference_\\d+$")));
167 Q_FOREACH (const QString
&i
, groups
) {
168 const KConfigGroup
group(m_config
, i
);
169 const QByteArray id
= group
.readEntry("email", QByteArray());
173 pgpPrefs
.insert(id
, group
.readEntry("pgpCertificate", QByteArray()));
174 cmsPrefs
.insert(id
, group
.readEntry("cmsCertificate", QByteArray()));
179 KConfigBasedRecipientPreferences::KConfigBasedRecipientPreferences(const KSharedConfigPtr
&config
) : d(new Private(config
, this))
183 KConfigBasedRecipientPreferences::~KConfigBasedRecipientPreferences()
188 Key
KConfigBasedRecipientPreferences::preferredCertificate(const Mailbox
&recipient
, Protocol protocol
)
190 d
->ensurePrefsParsed();
192 const QByteArray keyId
= (protocol
== CMS
? d
->cmsPrefs
: d
->pgpPrefs
).value(recipient
.address());
193 return KeyCache::instance()->findByKeyIDOrFingerprint(keyId
);
196 void KConfigBasedRecipientPreferences::setPreferredCertificate(const Mailbox
&recipient
, Protocol protocol
, const Key
&certificate
)
198 d
->ensurePrefsParsed();
199 if (!recipient
.hasAddress()) {
202 (protocol
== CMS
? d
->cmsPrefs
: d
->pgpPrefs
).insert(recipient
.address(), certificate
.keyID());
206 class KConfigBasedSigningPreferences::Private
208 friend class ::Kleo::Crypto::KConfigBasedSigningPreferences
;
209 KConfigBasedSigningPreferences
*const q
;
211 explicit Private(const KSharedConfigPtr
&config
, KConfigBasedSigningPreferences
*qq
);
215 void ensurePrefsParsed() const;
219 KSharedConfigPtr m_config
;
221 mutable QByteArray pgpSigningCertificate
;
222 mutable QByteArray cmsSigningCertificate
;
223 mutable bool m_parsed
;
224 mutable bool m_dirty
;
227 KConfigBasedSigningPreferences::Private::Private(const KSharedConfigPtr
&config
, KConfigBasedSigningPreferences
*qq
) : q(qq
), m_config(config
), m_parsed(false), m_dirty(false)
232 void KConfigBasedSigningPreferences::Private::ensurePrefsParsed() const
237 const KConfigGroup
group(m_config
, "SigningPreferences");
238 pgpSigningCertificate
= group
.readEntry("pgpSigningCertificate", QByteArray());
239 cmsSigningCertificate
= group
.readEntry("cmsSigningCertificate", QByteArray());
243 void KConfigBasedSigningPreferences::Private::writePrefs()
248 KConfigGroup
group(m_config
, "SigningPreferences");
249 group
.writeEntry("pgpSigningCertificate", pgpSigningCertificate
);
250 group
.writeEntry("cmsSigningCertificate", cmsSigningCertificate
);
255 KConfigBasedSigningPreferences::Private::~Private()
260 KConfigBasedSigningPreferences::KConfigBasedSigningPreferences(const KSharedConfigPtr
&config
) : d(new Private(config
, this))
264 KConfigBasedSigningPreferences::~KConfigBasedSigningPreferences()
269 Key
KConfigBasedSigningPreferences::preferredCertificate(Protocol protocol
)
271 d
->ensurePrefsParsed();
273 const QByteArray keyId
= (protocol
== CMS
? d
->cmsSigningCertificate
: d
->pgpSigningCertificate
);
274 const Key key
= KeyCache::instance()->findByKeyIDOrFingerprint(keyId
);
275 return key
.hasSecret() ? key
: Key::null
;
278 void KConfigBasedSigningPreferences::setPreferredCertificate(Protocol protocol
, const Key
&certificate
)
280 d
->ensurePrefsParsed();
281 (protocol
== CMS
? d
->cmsSigningCertificate
: d
->pgpSigningCertificate
) = certificate
.keyID();