00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <config-kleopatra.h>
00034
00035 #include "certificateresolver.h"
00036
00037 #include <models/keycache.h>
00038
00039 #include <gpgme++/key.h>
00040
00041 #include <KConfig>
00042 #include <KConfigGroup>
00043
00044 #include <QByteArray>
00045 #include <QHash>
00046 #include <QSet>
00047
00048 #include <boost/bind.hpp>
00049
00050 #include <algorithm>
00051 #include <iterator>
00052
00053 using namespace Kleo;
00054 using namespace Kleo::Crypto;
00055 using namespace boost;
00056 using namespace GpgME;
00057 using namespace KMime::Types;
00058 using namespace KMime::HeaderParsing;
00059
00060 std::vector< std::vector<Key> > CertificateResolver::resolveRecipients( const std::vector<Mailbox> & recipients, Protocol proto ) {
00061 std::vector< std::vector<Key> > result;
00062 std::transform( recipients.begin(), recipients.end(),
00063 std::back_inserter( result ), bind( &resolveRecipient, _1, proto ) );
00064 return result;
00065 }
00066
00067 std::vector<Key> CertificateResolver::resolveRecipient( const Mailbox & recipient, Protocol proto ) {
00068 std::vector<Key> result = KeyCache::instance()->findByEMailAddress( recipient.address() );
00069 std::vector<Key>::iterator end = std::remove_if( result.begin(), result.end(),
00070 !bind( &Key::canEncrypt, _1 ) );
00071
00072 if ( proto != UnknownProtocol )
00073 end = std::remove_if( result.begin(), end,
00074 bind( &Key::protocol, _1 ) != proto );
00075
00076 result.erase( end, result.end() );
00077 return result;
00078 }
00079
00080 std::vector< std::vector<Key> > CertificateResolver::resolveSigners( const std::vector<Mailbox> & signers, Protocol proto ) {
00081 std::vector< std::vector<Key> > result;
00082 std::transform( signers.begin(), signers.end(),
00083 std::back_inserter( result ), bind( &resolveSigner, _1, proto ) );
00084 return result;
00085 }
00086
00087 std::vector<Key> CertificateResolver::resolveSigner( const Mailbox & signer, Protocol proto ) {
00088 std::vector<Key> result = KeyCache::instance()->findByEMailAddress( signer.address() );
00089 std::vector<Key>::iterator end
00090 = std::remove_if( result.begin(), result.end(),
00091 !bind( &Key::hasSecret, _1 ) );
00092 end = std::remove_if( result.begin(), end,
00093 !bind( &Key::canSign, _1 ) );
00094 if ( proto != UnknownProtocol )
00095 end = std::remove_if( result.begin(), end,
00096 bind( &Key::protocol, _1 ) != proto );
00097 result.erase( end, result.end() );
00098 return result;
00099 }
00100
00101 class KConfigBasedRecipientPreferences::Private {
00102 friend class ::Kleo::Crypto::KConfigBasedRecipientPreferences;
00103 KConfigBasedRecipientPreferences* const q;
00104 public:
00105 explicit Private( KSharedConfigPtr config, KConfigBasedRecipientPreferences* qq );
00106 ~Private();
00107
00108 private:
00109 void ensurePrefsParsed() const;
00110 void writePrefs();
00111
00112 private:
00113 KSharedConfigPtr m_config;
00114
00115 mutable QHash<QByteArray, QByteArray> pgpPrefs;
00116 mutable QHash<QByteArray, QByteArray> cmsPrefs;
00117 mutable bool m_parsed;
00118 mutable bool m_dirty;
00119 };
00120
00121 KConfigBasedRecipientPreferences::Private::Private( KSharedConfigPtr config , KConfigBasedRecipientPreferences* qq ) : q( qq ), m_config( config ), m_parsed( false ), m_dirty( false )
00122 {
00123 assert( m_config );
00124 }
00125
00126 KConfigBasedRecipientPreferences::Private::~Private()
00127 {
00128 writePrefs();
00129 }
00130
00131 void KConfigBasedRecipientPreferences::Private::writePrefs()
00132 {
00133 if ( !m_dirty )
00134 return;
00135 const QSet<QByteArray> keys = pgpPrefs.keys().toSet() + cmsPrefs.keys().toSet();
00136
00137 int n = 0;
00138 Q_FOREACH ( const QByteArray& i, keys )
00139 {
00140 KConfigGroup group( m_config, QString( "EncryptionPreference_%1" ).arg( n++ ) );
00141 group.writeEntry( "email", i );
00142 const QByteArray pgp = pgpPrefs.value( i );
00143 if ( !pgp.isEmpty() )
00144 group.writeEntry( "pgpCertificate", pgp );
00145 const QByteArray cms = cmsPrefs.value( i );
00146 if ( !cms.isEmpty() )
00147 group.writeEntry( "cmsCertificate", cms );
00148 }
00149 m_config->sync();
00150 m_dirty = false;
00151 }
00152 void KConfigBasedRecipientPreferences::Private::ensurePrefsParsed() const
00153 {
00154 if ( m_parsed )
00155 return;
00156 const QStringList groups = m_config->groupList().filter( QRegExp( "^EncryptionPreference_\\d+$" ) );
00157
00158 Q_FOREACH ( const QString& i, groups )
00159 {
00160 const KConfigGroup group( m_config, i );
00161 const QByteArray id = group.readEntry( "email", QByteArray() );
00162 if ( id.isEmpty() )
00163 continue;
00164 pgpPrefs.insert( id, group.readEntry( "pgpCertificate", QByteArray() ) );
00165 cmsPrefs.insert( id, group.readEntry( "cmsCertificate", QByteArray() ) );
00166 }
00167 m_parsed = true;
00168 }
00169
00170 KConfigBasedRecipientPreferences::KConfigBasedRecipientPreferences( KSharedConfigPtr config ) : d( new Private( config, this ) )
00171 {
00172 }
00173
00174
00175 KConfigBasedRecipientPreferences::~KConfigBasedRecipientPreferences()
00176 {
00177 d->writePrefs();
00178 }
00179
00180 Key KConfigBasedRecipientPreferences::preferredCertificate( const Mailbox& recipient, Protocol protocol )
00181 {
00182 d->ensurePrefsParsed();
00183
00184 const QByteArray keyId = ( protocol == CMS ? d->cmsPrefs : d->pgpPrefs ).value( recipient.address() );
00185 return KeyCache::instance()->findByKeyIDOrFingerprint( keyId );
00186 }
00187
00188 void KConfigBasedRecipientPreferences::setPreferredCertificate( const Mailbox& recipient, Protocol protocol, const Key& certificate )
00189 {
00190 d->ensurePrefsParsed();
00191 if ( !recipient.hasAddress() )
00192 return;
00193 ( protocol == CMS ? d->cmsPrefs : d->pgpPrefs ).insert( recipient.address(), certificate.keyID() );
00194 d->m_dirty = true;
00195 }
00196
00197 class KConfigBasedSigningPreferences::Private {
00198 friend class ::Kleo::Crypto::KConfigBasedSigningPreferences;
00199 KConfigBasedSigningPreferences* const q;
00200 public:
00201 explicit Private( KSharedConfigPtr config, KConfigBasedSigningPreferences* qq );
00202 ~Private();
00203
00204 private:
00205 void ensurePrefsParsed() const;
00206 void writePrefs();
00207
00208 private:
00209 KSharedConfigPtr m_config;
00210
00211 mutable QByteArray pgpSigningCertificate;
00212 mutable QByteArray cmsSigningCertificate;
00213 mutable bool m_parsed;
00214 mutable bool m_dirty;
00215 };
00216
00217 KConfigBasedSigningPreferences::Private::Private( KSharedConfigPtr config , KConfigBasedSigningPreferences* qq ) : q( qq ), m_config( config ), m_parsed( false ), m_dirty( false )
00218 {
00219 assert( m_config );
00220 }
00221
00222 void KConfigBasedSigningPreferences::Private::ensurePrefsParsed() const
00223 {
00224 if ( m_parsed )
00225 return;
00226 const KConfigGroup group( m_config, "SigningPreferences" );
00227 pgpSigningCertificate = group.readEntry( "pgpSigningCertificate", QByteArray() );
00228 cmsSigningCertificate = group.readEntry( "cmsSigningCertificate", QByteArray() );
00229 m_parsed = true;
00230 }
00231
00232 void KConfigBasedSigningPreferences::Private::writePrefs()
00233 {
00234 if ( !m_dirty )
00235 return;
00236 KConfigGroup group( m_config, "SigningPreferences" );
00237 group.writeEntry( "pgpSigningCertificate", pgpSigningCertificate );
00238 group.writeEntry( "cmsSigningCertificate", cmsSigningCertificate );
00239 m_config->sync();
00240 m_dirty = false;
00241 }
00242
00243 KConfigBasedSigningPreferences::Private::~Private()
00244 {
00245 writePrefs();
00246 }
00247
00248 KConfigBasedSigningPreferences::KConfigBasedSigningPreferences( KSharedConfigPtr config ) : d( new Private( config, this ) )
00249 {
00250 }
00251
00252
00253 KConfigBasedSigningPreferences::~KConfigBasedSigningPreferences()
00254 {
00255 d->writePrefs();
00256 }
00257
00258 Key KConfigBasedSigningPreferences::preferredCertificate( Protocol protocol )
00259 {
00260 d->ensurePrefsParsed();
00261
00262 const QByteArray keyId = ( protocol == CMS ? d->cmsSigningCertificate : d->pgpSigningCertificate );
00263 const Key key = KeyCache::instance()->findByKeyIDOrFingerprint( keyId );
00264 return key.hasSecret() ? key : Key::null;
00265 }
00266
00267 void KConfigBasedSigningPreferences::setPreferredCertificate( Protocol protocol, const Key& certificate )
00268 {
00269 d->ensurePrefsParsed();
00270 ( protocol == CMS ? d->cmsSigningCertificate : d->pgpSigningCertificate ) = certificate.keyID();
00271 d->m_dirty = true;
00272 }
00273