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
00034
00035
00036
00037 #ifdef HAVE_CONFIG_H
00038 #include <config.h>
00039 #endif
00040
00041 #include "keyresolver.h"
00042
00043 #include "kcursorsaver.h"
00044 #include "kleo_util.h"
00045
00046 #include <libemailfunctions/email.h>
00047 #include <ui/keyselectiondialog.h>
00048 #include <kleo/cryptobackendfactory.h>
00049 #include <kleo/keylistjob.h>
00050 #include <kleo/dn.h>
00051
00052 #include <gpgmepp/key.h>
00053 #include <gpgmepp/keylistresult.h>
00054
00055 #include <kabc/stdaddressbook.h>
00056 #include <klocale.h>
00057 #include <kdebug.h>
00058 #include <kinputdialog.h>
00059 #include <kmessagebox.h>
00060
00061 #include <qstringlist.h>
00062 #include <qtl.h>
00063
00064 #include <time.h>
00065
00066 #include <algorithm>
00067 #include <memory>
00068 #include <iterator>
00069 #include <functional>
00070 #include <map>
00071 #include <set>
00072 #include <iostream>
00073 #include <cassert>
00074
00075
00076
00077
00078
00079
00080 static inline bool EmptyKeyList( const Kleo::KeyApprovalDialog::Item & item ) {
00081 return item.keys.empty();
00082 }
00083
00084 static inline QString ItemDotAddress( const Kleo::KeyResolver::Item & item ) {
00085 return item.address;
00086 }
00087
00088 static inline bool ApprovalNeeded( const Kleo::KeyResolver::Item & item ) {
00089 return item.pref == Kleo::UnknownPreference || item.pref == Kleo::NeverEncrypt || item.keys.empty() ;
00090 }
00091
00092 static inline Kleo::KeyResolver::Item
00093 CopyKeysAndEncryptionPreferences( const Kleo::KeyResolver::Item & oldItem,
00094 const Kleo::KeyApprovalDialog::Item & newItem ) {
00095 return Kleo::KeyResolver::Item( oldItem.address, newItem.keys, newItem.pref, oldItem.signPref, oldItem.format );
00096 }
00097
00098 static inline bool ByKeyID( const GpgME::Key & left, const GpgME::Key & right ) {
00099 return qstrcmp( left.keyID(), right.keyID() ) < 0 ;
00100 }
00101
00102 static inline bool WithRespectToKeyID( const GpgME::Key & left, const GpgME::Key & right ) {
00103 return qstrcmp( left.keyID(), right.keyID() ) == 0 ;
00104 }
00105
00106 static bool ValidOpenPGPEncryptionKey( const GpgME::Key & key ) {
00107 if ( key.protocol() != GpgME::Context::OpenPGP ) {
00108 return false;
00109 }
00110 #if 0
00111 if ( key.isRevoked() )
00112 kdWarning() << " is revoked" << endl;
00113 if ( key.isExpired() )
00114 kdWarning() << " is expired" << endl;
00115 if ( key.isDisabled() )
00116 kdWarning() << " is disabled" << endl;
00117 if ( !key.canEncrypt() )
00118 kdWarning() << " can't encrypt" << endl;
00119 #endif
00120 if ( key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canEncrypt() )
00121 return false;
00122 return true;
00123 }
00124
00125 static bool ValidTrustedOpenPGPEncryptionKey( const GpgME::Key & key ) {
00126 if ( !ValidOpenPGPEncryptionKey( key ) )
00127 return false;
00128 const std::vector<GpgME::UserID> uids = key.userIDs();
00129 for ( std::vector<GpgME::UserID>::const_iterator it = uids.begin() ; it != uids.end() ; ++it ) {
00130 if ( !it->isRevoked() && it->validity() > GpgME::UserID::Marginal )
00131 return true;
00132 #if 0
00133 else
00134 if ( it->isRevoked() )
00135 kdWarning() << "a userid is revoked" << endl;
00136 else
00137 kdWarning() << "bad validity " << it->validity() << endl;
00138 #endif
00139 }
00140 return false;
00141 }
00142
00143 static bool ValidSMIMEEncryptionKey( const GpgME::Key & key ) {
00144 if ( key.protocol() != GpgME::Context::CMS )
00145 return false;
00146 if ( key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canEncrypt() )
00147 return false;
00148 return true;
00149 }
00150
00151 static bool ValidTrustedSMIMEEncryptionKey( const GpgME::Key & key ) {
00152 if ( !ValidSMIMEEncryptionKey( key ) )
00153 return false;
00154 return true;
00155 }
00156
00157 static inline bool ValidTrustedEncryptionKey( const GpgME::Key & key ) {
00158 switch ( key.protocol() ) {
00159 case GpgME::Context::OpenPGP:
00160 return ValidTrustedOpenPGPEncryptionKey( key );
00161 case GpgME::Context::CMS:
00162 return ValidTrustedSMIMEEncryptionKey( key );
00163 default:
00164 return false;
00165 }
00166 }
00167
00168 static inline bool ValidEncryptionKey( const GpgME::Key & key ) {
00169 switch ( key.protocol() ) {
00170 case GpgME::Context::OpenPGP:
00171 return ValidOpenPGPEncryptionKey( key );
00172 case GpgME::Context::CMS:
00173 return ValidSMIMEEncryptionKey( key );
00174 default:
00175 return false;
00176 }
00177 }
00178
00179 static inline bool ValidSigningKey( const GpgME::Key & key ) {
00180 if ( key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canSign() )
00181 return false;
00182 return key.hasSecret();
00183 }
00184
00185 static inline bool ValidOpenPGPSigningKey( const GpgME::Key & key ) {
00186 return key.protocol() == GpgME::Context::OpenPGP && ValidSigningKey( key );
00187 }
00188
00189 static inline bool ValidSMIMESigningKey( const GpgME::Key & key ) {
00190 return key.protocol() == GpgME::Context::CMS && ValidSigningKey( key );
00191 }
00192
00193 static inline bool NotValidTrustedOpenPGPEncryptionKey( const GpgME::Key & key ) {
00194 return !ValidTrustedOpenPGPEncryptionKey( key );
00195 }
00196
00197 static inline bool NotValidOpenPGPEncryptionKey( const GpgME::Key & key ) {
00198 return !ValidOpenPGPEncryptionKey( key );
00199 }
00200
00201 static inline bool NotValidTrustedSMIMEEncryptionKey( const GpgME::Key & key ) {
00202 return !ValidTrustedSMIMEEncryptionKey( key );
00203 }
00204
00205 static inline bool NotValidSMIMEEncryptionKey( const GpgME::Key & key ) {
00206 return !ValidSMIMEEncryptionKey( key );
00207 }
00208
00209 static inline bool NotValidTrustedEncryptionKey( const GpgME::Key & key ) {
00210 return !ValidTrustedEncryptionKey( key );
00211 }
00212
00213 static inline bool NotValidEncryptionKey( const GpgME::Key & key ) {
00214 return !ValidEncryptionKey( key );
00215 }
00216
00217 static inline bool NotValidSigningKey( const GpgME::Key & key ) {
00218 return !ValidSigningKey( key );
00219 }
00220
00221 static inline bool NotValidOpenPGPSigningKey( const GpgME::Key & key ) {
00222 return !ValidOpenPGPSigningKey( key );
00223 }
00224
00225 static inline bool NotValidSMIMESigningKey( const GpgME::Key & key ) {
00226 return !ValidSMIMESigningKey( key );
00227 }
00228
00229 static QStringList keysAsStrings( const std::vector<GpgME::Key>& keys ) {
00230 QStringList strings;
00231 for ( std::vector<GpgME::Key>::const_iterator it = keys.begin() ; it != keys.end() ; ++it ) {
00232 assert( !(*it).userID(0).isNull() );
00233 QString keyLabel = QString::fromUtf8( (*it).userID(0).email() );
00234 if ( keyLabel.isEmpty() )
00235 keyLabel = QString::fromUtf8( (*it).userID(0).name() );
00236 if ( keyLabel.isEmpty() )
00237 keyLabel = QString::fromUtf8( (*it).userID(0).id() );
00238 strings.append( keyLabel );
00239 }
00240 return strings;
00241 }
00242
00243 static inline std::vector<GpgME::Key> TrustedOrConfirmed( const std::vector<GpgME::Key> & keys ) {
00244
00245 std::vector<GpgME::Key> fishies;
00246 std::vector<GpgME::Key> ickies;
00247 std::vector<GpgME::Key>::const_iterator it = keys.begin();
00248 const std::vector<GpgME::Key>::const_iterator end = keys.end();
00249 for ( ; it != end ; it++ ) {
00250 const GpgME::Key key = *it;
00251 assert( ValidEncryptionKey( key ) );
00252 const std::vector<GpgME::UserID> uids = key.userIDs();
00253 for ( std::vector<GpgME::UserID>::const_iterator it = uids.begin() ; it != uids.end() ; ++it ) {
00254 if ( !it->isRevoked() && it->validity() == GpgME::UserID::Marginal ) {
00255 fishies.push_back( key );
00256 break;
00257 }
00258 if ( !it->isRevoked() && it->validity() < GpgME::UserID::Never ) {
00259 ickies.push_back( key );
00260 break;
00261 }
00262 }
00263 }
00264
00265 if ( fishies.empty() && ickies.empty() )
00266 return keys;
00267
00268
00269 QString msg = i18n("One or more of your configured OpenPGP encryption "
00270 "keys or S/MIME certificates is not fully trusted "
00271 "for encryption.");
00272
00273 if ( !fishies.empty() ) {
00274
00275 msg += i18n( "\nThe following keys are only marginally trusted: \n");
00276 msg += keysAsStrings( fishies ).join(",");
00277 }
00278 if ( !ickies.empty() ) {
00279 msg += i18n( "\nThe following keys or certificates have unknown trust level: \n");
00280 msg += keysAsStrings( ickies ).join(",");
00281 }
00282
00283 if( KMessageBox::warningContinueCancel( 0, msg, i18n("Not Fully Trusted Encryption Keys"),
00284 KStdGuiItem::cont(),
00285 "not fully trusted encryption key warning" )
00286 == KMessageBox::Continue )
00287 return keys;
00288 else
00289 return std::vector<GpgME::Key>();
00290 }
00291
00292 namespace {
00293 struct IsNotForFormat : public std::unary_function<GpgME::Key,bool> {
00294 IsNotForFormat( Kleo::CryptoMessageFormat f ) : format( f ) {}
00295
00296 bool operator()( const GpgME::Key & key ) const {
00297 return
00298 ( isOpenPGP( format ) && key.protocol() != GpgME::Context::OpenPGP ) ||
00299 ( isSMIME( format ) && key.protocol() != GpgME::Context::CMS );
00300 }
00301
00302 const Kleo::CryptoMessageFormat format;
00303 };
00304 }
00305
00306
00307
00308 class Kleo::KeyResolver::SigningPreferenceCounter : public std::unary_function<Kleo::KeyResolver::Item,void> {
00309 public:
00310 SigningPreferenceCounter()
00311 : mTotal( 0 ),
00312 mUnknownSigningPreference( 0 ),
00313 mNeverSign( 0 ),
00314 mAlwaysSign( 0 ),
00315 mAlwaysSignIfPossible( 0 ),
00316 mAlwaysAskForSigning( 0 ),
00317 mAskSigningWheneverPossible( 0 )
00318 {
00319
00320 }
00321 void operator()( const Kleo::KeyResolver::Item & item );
00322 #define make_int_accessor(x) unsigned int num##x() const { return m##x; }
00323 make_int_accessor(UnknownSigningPreference)
00324 make_int_accessor(NeverSign)
00325 make_int_accessor(AlwaysSign)
00326 make_int_accessor(AlwaysSignIfPossible)
00327 make_int_accessor(AlwaysAskForSigning)
00328 make_int_accessor(AskSigningWheneverPossible)
00329 make_int_accessor(Total)
00330 #undef make_int_accessor
00331 private:
00332 unsigned int mTotal;
00333 unsigned int mUnknownSigningPreference, mNeverSign, mAlwaysSign,
00334 mAlwaysSignIfPossible, mAlwaysAskForSigning, mAskSigningWheneverPossible;
00335 };
00336
00337 void Kleo::KeyResolver::SigningPreferenceCounter::operator()( const Kleo::KeyResolver::Item & item ) {
00338 switch ( item.signPref ) {
00339 #define CASE(x) case x: ++m##x; break
00340 CASE(UnknownSigningPreference);
00341 CASE(NeverSign);
00342 CASE(AlwaysSign);
00343 CASE(AlwaysSignIfPossible);
00344 CASE(AlwaysAskForSigning);
00345 CASE(AskSigningWheneverPossible);
00346 #undef CASE
00347 }
00348 ++mTotal;
00349 }
00350
00351
00352
00353 class Kleo::KeyResolver::EncryptionPreferenceCounter : public std::unary_function<Item,void> {
00354 const Kleo::KeyResolver * _this;
00355 public:
00356 EncryptionPreferenceCounter( const Kleo::KeyResolver * kr, EncryptionPreference defaultPreference )
00357 : _this( kr ),
00358 mDefaultPreference( defaultPreference ),
00359 mTotal( 0 ),
00360 mNoKey( 0 ),
00361 mNeverEncrypt( 0 ),
00362 mUnknownPreference( 0 ),
00363 mAlwaysEncrypt( 0 ),
00364 mAlwaysEncryptIfPossible( 0 ),
00365 mAlwaysAskForEncryption( 0 ),
00366 mAskWheneverPossible( 0 )
00367 {
00368
00369 }
00370 void operator()( Item & item );
00371
00372 #define make_int_accessor(x) unsigned int num##x() const { return m##x; }
00373 make_int_accessor(NoKey)
00374 make_int_accessor(NeverEncrypt)
00375 make_int_accessor(UnknownPreference)
00376 make_int_accessor(AlwaysEncrypt)
00377 make_int_accessor(AlwaysEncryptIfPossible)
00378 make_int_accessor(AlwaysAskForEncryption)
00379 make_int_accessor(AskWheneverPossible)
00380 make_int_accessor(Total)
00381 #undef make_int_accessor
00382 private:
00383 EncryptionPreference mDefaultPreference;
00384 unsigned int mTotal;
00385 unsigned int mNoKey;
00386 unsigned int mNeverEncrypt, mUnknownPreference, mAlwaysEncrypt,
00387 mAlwaysEncryptIfPossible, mAlwaysAskForEncryption, mAskWheneverPossible;
00388 };
00389
00390 void Kleo::KeyResolver::EncryptionPreferenceCounter::operator()( Item & item ) {
00391 if ( item.needKeys )
00392 item.keys = _this->getEncryptionKeys( item.address, true );
00393 if ( item.keys.empty() ) {
00394 ++mNoKey;
00395 return;
00396 }
00397 switch ( !item.pref ? mDefaultPreference : item.pref ) {
00398 #define CASE(x) case Kleo::x: ++m##x; break
00399 CASE(NeverEncrypt);
00400 CASE(UnknownPreference);
00401 CASE(AlwaysEncrypt);
00402 CASE(AlwaysEncryptIfPossible);
00403 CASE(AlwaysAskForEncryption);
00404 CASE(AskWheneverPossible);
00405 #undef CASE
00406 }
00407 ++mTotal;
00408 }
00409
00410 namespace {
00411
00412 class FormatPreferenceCounterBase : public std::unary_function<Kleo::KeyResolver::Item,void> {
00413 public:
00414 FormatPreferenceCounterBase()
00415 : mTotal( 0 ),
00416 mInlineOpenPGP( 0 ),
00417 mOpenPGPMIME( 0 ),
00418 mSMIME( 0 ),
00419 mSMIMEOpaque( 0 )
00420 {
00421
00422 }
00423
00424 #define make_int_accessor(x) unsigned int num##x() const { return m##x; }
00425 make_int_accessor(Total)
00426 make_int_accessor(InlineOpenPGP)
00427 make_int_accessor(OpenPGPMIME)
00428 make_int_accessor(SMIME)
00429 make_int_accessor(SMIMEOpaque)
00430 #undef make_int_accessor
00431
00432 unsigned int numOf( Kleo::CryptoMessageFormat f ) const {
00433 switch ( f ) {
00434 #define CASE(x) case Kleo::x##Format: return m##x
00435 CASE(InlineOpenPGP);
00436 CASE(OpenPGPMIME);
00437 CASE(SMIME);
00438 CASE(SMIMEOpaque);
00439 #undef CASE
00440 default: return 0;
00441 }
00442 }
00443
00444 protected:
00445 unsigned int mTotal;
00446 unsigned int mInlineOpenPGP, mOpenPGPMIME, mSMIME, mSMIMEOpaque;
00447 };
00448
00449 class EncryptionFormatPreferenceCounter : public FormatPreferenceCounterBase {
00450 public:
00451 EncryptionFormatPreferenceCounter() : FormatPreferenceCounterBase() {}
00452 void operator()( const Kleo::KeyResolver::Item & item );
00453 };
00454
00455 class SigningFormatPreferenceCounter : public FormatPreferenceCounterBase {
00456 public:
00457 SigningFormatPreferenceCounter() : FormatPreferenceCounterBase() {}
00458 void operator()( const Kleo::KeyResolver::Item & item );
00459 };
00460
00461 #define CASE(x) if ( item.format & Kleo::x##Format ) ++m##x;
00462 void EncryptionFormatPreferenceCounter::operator()( const Kleo::KeyResolver::Item & item ) {
00463 if ( item.format & (Kleo::InlineOpenPGPFormat|Kleo::OpenPGPMIMEFormat) &&
00464 std::find_if( item.keys.begin(), item.keys.end(),
00465 ValidTrustedOpenPGPEncryptionKey ) != item.keys.end() ) {
00466 CASE(OpenPGPMIME);
00467 CASE(InlineOpenPGP);
00468 }
00469 if ( item.format & (Kleo::SMIMEFormat|Kleo::SMIMEOpaqueFormat) &&
00470 std::find_if( item.keys.begin(), item.keys.end(),
00471 ValidTrustedSMIMEEncryptionKey ) != item.keys.end() ) {
00472 CASE(SMIME);
00473 CASE(SMIMEOpaque);
00474 }
00475 ++mTotal;
00476 }
00477
00478 void SigningFormatPreferenceCounter::operator()( const Kleo::KeyResolver::Item & item ) {
00479 CASE(InlineOpenPGP);
00480 CASE(OpenPGPMIME);
00481 CASE(SMIME);
00482 CASE(SMIMEOpaque);
00483 ++mTotal;
00484 }
00485 #undef CASE
00486
00487 }
00488
00489 static QString canonicalAddress( const QString & _address ) {
00490 const QString address = KPIM::getEmailAddress( _address );
00491 if ( address.find('@') == -1 ) {
00492
00493
00494
00495
00496 return address + "@localdomain";
00497 }
00498 else
00499 return address;
00500 }
00501
00502
00503 struct FormatInfo {
00504 std::vector<Kleo::KeyResolver::SplitInfo> splitInfos;
00505 std::vector<GpgME::Key> signKeys;
00506 };
00507
00508 struct Kleo::KeyResolver::Private {
00509 std::set<QCString> alreadyWarnedFingerprints;
00510
00511 std::vector<GpgME::Key> mOpenPGPSigningKeys;
00512 std::vector<GpgME::Key> mSMIMESigningKeys;
00513
00514 std::vector<GpgME::Key> mOpenPGPEncryptToSelfKeys;
00515 std::vector<GpgME::Key> mSMIMEEncryptToSelfKeys;
00516
00517 std::vector<Item> mPrimaryEncryptionKeys;
00518 std::vector<Item> mSecondaryEncryptionKeys;
00519
00520 std::map<CryptoMessageFormat,FormatInfo> mFormatInfoMap;
00521
00522
00523 typedef std::map<QString, ContactPreferences> ContactPreferencesMap;
00524 ContactPreferencesMap mContactPreferencesMap;
00525 };
00526
00527
00528 Kleo::KeyResolver::KeyResolver( bool encToSelf, bool showApproval, bool oppEncryption,
00529 unsigned int f,
00530 int encrWarnThresholdKey, int signWarnThresholdKey,
00531 int encrWarnThresholdRootCert, int signWarnThresholdRootCert,
00532 int encrWarnThresholdChainCert, int signWarnThresholdChainCert )
00533 : mEncryptToSelf( encToSelf ),
00534 mShowApprovalDialog( showApproval ),
00535 mOpportunisticEncyption( oppEncryption ),
00536 mCryptoMessageFormats( f ),
00537 mEncryptKeyNearExpiryWarningThreshold( encrWarnThresholdKey ),
00538 mSigningKeyNearExpiryWarningThreshold( signWarnThresholdKey ),
00539 mEncryptRootCertNearExpiryWarningThreshold( encrWarnThresholdRootCert ),
00540 mSigningRootCertNearExpiryWarningThreshold( signWarnThresholdRootCert ),
00541 mEncryptChainCertNearExpiryWarningThreshold( encrWarnThresholdChainCert ),
00542 mSigningChainCertNearExpiryWarningThreshold( signWarnThresholdChainCert )
00543 {
00544 d = new Private();
00545 }
00546
00547 Kleo::KeyResolver::~KeyResolver() {
00548 delete d; d = 0;
00549 }
00550
00551 Kpgp::Result Kleo::KeyResolver::checkKeyNearExpiry( const GpgME::Key & key, const char * dontAskAgainName,
00552 bool mine, bool sign, bool ca,
00553 int recur_limit, const GpgME::Key & orig ) const {
00554 if ( recur_limit <= 0 ) {
00555 kdDebug() << "Kleo::KeyResolver::checkKeyNearExpiry(): key chain too long (>100 certs)" << endl;
00556 return Kpgp::Ok;
00557 }
00558 const GpgME::Subkey subkey = key.subkey(0);
00559 if ( d->alreadyWarnedFingerprints.count( subkey.fingerprint() ) )
00560 return Kpgp::Ok;
00561
00562 if ( subkey.neverExpires() )
00563 return Kpgp::Ok;
00564 static const double secsPerDay = 24 * 60 * 60;
00565 const double secsTillExpiry = ::difftime( subkey.expirationTime(), time(0) );
00566 if ( secsTillExpiry <= 0 ) {
00567 const int daysSinceExpiry = 1 + int( -secsTillExpiry / secsPerDay );
00568 kdDebug() << "Key 0x" << key.shortKeyID() << " expired less than "
00569 << daysSinceExpiry << " days ago" << endl;
00570 const QString msg =
00571 key.protocol() == GpgME::Context::OpenPGP
00572 ? ( mine ? sign
00573 ? i18n("<p>Your OpenPGP signing key</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00574 "<p>expired less than a day ago.</p>",
00575 "<p>Your OpenPGP signing key</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00576 "<p>expired %n days ago.</p>",
00577 daysSinceExpiry )
00578 : i18n("<p>Your OpenPGP encryption key</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00579 "<p>expired less than a day ago.</p>",
00580 "<p>Your OpenPGP encryption key</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00581 "<p>expired %n days ago.</p>",
00582 daysSinceExpiry )
00583 : i18n("<p>The OpenPGP key for</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00584 "<p>expired less than a day ago.</p>",
00585 "<p>The OpenPGP key for</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00586 "<p>expired %n days ago.</p>",
00587 daysSinceExpiry ) ).arg( QString::fromUtf8( key.userID(0).id() ),
00588 key.shortKeyID() )
00589 : ( ca
00590 ? ( key.isRoot()
00591 ? ( mine ? sign
00592 ? i18n("<p>The root certificate</p><p align=center><b>%3</b></p>"
00593 "<p>for your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00594 "<p>expired less than a day ago.</p>",
00595 "<p>The root certificate</p><p align=center><b>%3</b></p>"
00596 "<p>for your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00597 "<p>expired %n days ago.</p>",
00598 daysSinceExpiry )
00599 : i18n("<p>The root certificate</p><p align=center><b>%3</b></p>"
00600 "<p>for your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00601 "<p>expired less than a day ago.</p>",
00602 "<p>The root certificate</p><p align=center><b>%3</b></p>"
00603 "<p>for your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00604 "<p>expired %n days ago.</p>",
00605 daysSinceExpiry )
00606 : i18n("<p>The root certificate</p><p align=center><b>%3</b></p>"
00607 "<p>for S/MIME certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00608 "<p>expired less than a day ago.</p>",
00609 "<p>The root certificate</p><p align=center><b>%3</b></p>"
00610 "<p>for S/MIME certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00611 "<p>expired %n days ago.</p>",
00612 daysSinceExpiry ) )
00613 : ( mine ? sign
00614 ? i18n("<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00615 "<p>for your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00616 "<p>expired less than a day ago.</p>",
00617 "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00618 "<p>for your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00619 "<p>expired %n days ago.</p>",
00620 daysSinceExpiry )
00621 : i18n("<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00622 "<p>for your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00623 "<p>expired less than a day ago.</p>",
00624 "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00625 "<p>for your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00626 "<p>expired %n days ago.</p>",
00627 daysSinceExpiry )
00628 : i18n("<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00629 "<p>for S/MIME certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00630 "<p>expired less than a day ago.</p>",
00631 "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00632 "<p>for S/MIME certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00633 "<p>expired %n days ago.</p>",
00634 daysSinceExpiry ) ) ).arg( Kleo::DN( orig.userID(0).id() ).prettyDN(),
00635 orig.issuerSerial(),
00636 Kleo::DN( key.userID(0).id() ).prettyDN() )
00637 : ( mine ? sign
00638 ? i18n("<p>Your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00639 "<p>expired less than a day ago.</p>",
00640 "<p>Your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00641 "<p>expired %n days ago.</p>",
00642 daysSinceExpiry )
00643 : i18n("<p>Your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00644 "<p>expired less than a day ago.</p>",
00645 "<p>Your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00646 "<p>expired %n days ago.</p>",
00647 daysSinceExpiry )
00648 : i18n("<p>The S/MIME certificate for</p><p align=center><b>%1</b> (serial number %2)</p>"
00649 "<p>expired less than a day ago.</p>",
00650 "<p>The S/MIME certificate for</p><p align=center><b>%1</b> (serial number %2)</p>"
00651 "<p>expired %n days ago.</p>",
00652 daysSinceExpiry ) ).arg( Kleo::DN( key.userID(0).id() ).prettyDN(),
00653 key.issuerSerial() ) );
00654 d->alreadyWarnedFingerprints.insert( subkey.fingerprint() );
00655 if ( KMessageBox::warningContinueCancel( 0, msg,
00656 key.protocol() == GpgME::Context::OpenPGP
00657 ? i18n("OpenPGP Key Expired" )
00658 : i18n("S/MIME Certificate Expired" ),
00659 KStdGuiItem::cont(), dontAskAgainName ) == KMessageBox::Cancel )
00660 return Kpgp::Canceled;
00661 } else {
00662 const int daysTillExpiry = 1 + int( secsTillExpiry / secsPerDay );
00663 kdDebug() << "Key 0x" << key.shortKeyID() << " expires in less than "
00664 << daysTillExpiry << " days" << endl;
00665 const int threshold =
00666 ca
00667 ? ( key.isRoot()
00668 ? ( sign
00669 ? signingRootCertNearExpiryWarningThresholdInDays()
00670 : encryptRootCertNearExpiryWarningThresholdInDays() )
00671 : ( sign
00672 ? signingChainCertNearExpiryWarningThresholdInDays()
00673 : encryptChainCertNearExpiryWarningThresholdInDays() ) )
00674 : ( sign
00675 ? signingKeyNearExpiryWarningThresholdInDays()
00676 : encryptKeyNearExpiryWarningThresholdInDays() );
00677 if ( threshold > -1 && daysTillExpiry <= threshold ) {
00678 const QString msg =
00679 key.protocol() == GpgME::Context::OpenPGP
00680 ? ( mine ? sign
00681 ? i18n("<p>Your OpenPGP signing key</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00682 "<p>expires in less than a day.</p>",
00683 "<p>Your OpenPGP signing key</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00684 "<p>expires in less than %n days.</p>",
00685 daysTillExpiry )
00686 : i18n("<p>Your OpenPGP encryption key</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00687 "<p>expires in less than a day.</p>",
00688 "<p>Your OpenPGP encryption key</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00689 "<p>expires in less than %n days.</p>",
00690 daysTillExpiry )
00691 : i18n("<p>The OpenPGP key for</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00692 "<p>expires in less than a day.</p>",
00693 "<p>The OpenPGP key for</p><p align=center><b>%1</b> (KeyID 0x%2)</p>"
00694 "<p>expires in less than %n days.</p>",
00695 daysTillExpiry ) ).arg( QString::fromUtf8( key.userID(0).id() ),
00696 key.shortKeyID() )
00697 : ( ca
00698 ? ( key.isRoot()
00699 ? ( mine ? sign
00700 ? i18n("<p>The root certificate</p><p align=center><b>%3</b></p>"
00701 "<p>for your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00702 "<p>expires in less than a day.</p>",
00703 "<p>The root certificate</p><p align=center><b>%3</b></p>"
00704 "<p>for your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00705 "<p>expires in less than %n days.</p>",
00706 daysTillExpiry )
00707 : i18n("<p>The root certificate</p><p align=center><b>%3</b></p>"
00708 "<p>for your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00709 "<p>expires in less than a day.</p>",
00710 "<p>The root certificate</p><p align=center><b>%3</b></p>"
00711 "<p>for your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00712 "<p>expires in less than %n days.</p>",
00713 daysTillExpiry )
00714 : i18n("<p>The root certificate</p><p align=center><b>%3</b></p>"
00715 "<p>for S/MIME certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00716 "<p>expires in less than a day.</p>",
00717 "<p>The root certificate</p><p align=center><b>%3</b></p>"
00718 "<p>for S/MIME certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00719 "<p>expires in less than %n days.</p>",
00720 daysTillExpiry ) )
00721 : ( mine ? sign
00722 ? i18n("<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00723 "<p>for your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00724 "<p>expires in less than a day.</p>",
00725 "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00726 "<p>for your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00727 "<p>expires in less than %n days.</p>",
00728 daysTillExpiry )
00729 : i18n("<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00730 "<p>for your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00731 "<p>expires in less than a day.</p>",
00732 "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00733 "<p>for your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00734 "<p>expires in less than %n days.</p>",
00735 daysTillExpiry )
00736 : i18n("<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00737 "<p>for S/MIME certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00738 "<p>expires in less than a day.</p>",
00739 "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>"
00740 "<p>for S/MIME certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00741 "<p>expires in less than %n days.</p>",
00742 daysTillExpiry ) ) ).arg( Kleo::DN( orig.userID(0).id() ).prettyDN(),
00743 orig.issuerSerial(),
00744 Kleo::DN( key.userID(0).id() ).prettyDN() )
00745 : ( mine ? sign
00746 ? i18n("<p>Your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00747 "<p>expires in less than a day.</p>",
00748 "<p>Your S/MIME signing certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00749 "<p>expires in less than %n days.</p>",
00750 daysTillExpiry )
00751 : i18n("<p>Your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00752 "<p>expires in less than a day.</p>",
00753 "<p>Your S/MIME encryption certificate</p><p align=center><b>%1</b> (serial number %2)</p>"
00754 "<p>expires in less than %n days.</p>",
00755 daysTillExpiry )
00756 : i18n("<p>The S/MIME certificate for</p><p align=center><b>%1</b> (serial number %2)</p>"
00757 "<p>expires in less than a day.</p>",
00758 "<p>The S/MIME certificate for</p><p align=center><b>%1</b> (serial number %2)</p>"
00759 "<p>expires in less than %n days.</p>",
00760 daysTillExpiry ) ).arg( Kleo::DN( key.userID(0).id() ).prettyDN(),
00761 key.issuerSerial() ) );
00762 d->alreadyWarnedFingerprints.insert( subkey.fingerprint() );
00763 if ( KMessageBox::warningContinueCancel( 0, msg,
00764 key.protocol() == GpgME::Context::OpenPGP
00765 ? i18n("OpenPGP Key Expires Soon" )
00766 : i18n("S/MIME Certificate Expires Soon" ),
00767 KStdGuiItem::cont(), dontAskAgainName )
00768 == KMessageBox::Cancel )
00769 return Kpgp::Canceled;
00770 }
00771 }
00772 if ( key.isRoot() )
00773 return Kpgp::Ok;
00774 else if ( const char * chain_id = key.chainID() ) {
00775 const std::vector<GpgME::Key> issuer = lookup( chain_id, false );
00776 if ( issuer.empty() )
00777 return Kpgp::Ok;
00778 else
00779 return checkKeyNearExpiry( issuer.front(), dontAskAgainName, mine, sign,
00780 true, recur_limit-1, ca ? orig : key );
00781 }
00782 return Kpgp::Ok;
00783 }
00784
00785 Kpgp::Result Kleo::KeyResolver::setEncryptToSelfKeys( const QStringList & fingerprints ) {
00786 if ( !encryptToSelf() )
00787 return Kpgp::Ok;
00788
00789 std::vector<GpgME::Key> keys = lookup( fingerprints );
00790 std::remove_copy_if( keys.begin(), keys.end(),
00791 std::back_inserter( d->mOpenPGPEncryptToSelfKeys ),
00792 NotValidTrustedOpenPGPEncryptionKey );
00793 std::remove_copy_if( keys.begin(), keys.end(),
00794 std::back_inserter( d->mSMIMEEncryptToSelfKeys ),
00795 NotValidTrustedSMIMEEncryptionKey );
00796
00797 if ( d->mOpenPGPEncryptToSelfKeys.size() + d->mSMIMEEncryptToSelfKeys.size()
00798 < keys.size() ) {
00799
00800 const QString msg = i18n("One or more of your configured OpenPGP encryption "
00801 "keys or S/MIME certificates is not usable for "
00802 "encryption. Please reconfigure your encryption keys "
00803 "and certificates for this identity in the identity "
00804 "configuration dialog.\n"
00805 "If you choose to continue, and the keys are needed "
00806 "later on, you will be prompted to specify the keys "
00807 "to use.");
00808 return KMessageBox::warningContinueCancel( 0, msg, i18n("Unusable Encryption Keys"),
00809 KStdGuiItem::cont(),
00810 "unusable own encryption key warning" )
00811 == KMessageBox::Continue ? Kpgp::Ok : Kpgp::Canceled ;
00812 }
00813
00814
00815
00816 for ( std::vector<GpgME::Key>::const_iterator it = d->mOpenPGPEncryptToSelfKeys.begin() ; it != d->mOpenPGPEncryptToSelfKeys.end() ; ++it ) {
00817 const Kpgp::Result r = checkKeyNearExpiry( *it, "own encryption key expires soon warning",
00818 true, false );
00819 if ( r != Kpgp::Ok )
00820 return r;
00821 }
00822
00823 for ( std::vector<GpgME::Key>::const_iterator it = d->mSMIMEEncryptToSelfKeys.begin() ; it != d->mSMIMEEncryptToSelfKeys.end() ; ++it ) {
00824 const Kpgp::Result r = checkKeyNearExpiry( *it, "own encryption key expires soon warning",
00825 true, false );
00826 if ( r != Kpgp::Ok )
00827 return r;
00828 }
00829
00830 return Kpgp::Ok;
00831 }
00832
00833 Kpgp::Result Kleo::KeyResolver::setSigningKeys( const QStringList & fingerprints ) {
00834 std::vector<GpgME::Key> keys = lookup( fingerprints, true );
00835 std::remove_copy_if( keys.begin(), keys.end(),
00836 std::back_inserter( d->mOpenPGPSigningKeys ),
00837 NotValidOpenPGPSigningKey );
00838 std::remove_copy_if( keys.begin(), keys.end(),
00839 std::back_inserter( d->mSMIMESigningKeys ),
00840 NotValidSMIMESigningKey );
00841
00842 if ( d->mOpenPGPSigningKeys.size() + d->mSMIMESigningKeys.size() < keys.size() ) {
00843
00844 const QString msg = i18n("One or more of your configured OpenPGP signing keys "
00845 "or S/MIME signing certificates is not usable for "
00846 "signing. Please reconfigure your signing keys "
00847 "and certificates for this identity in the identity "
00848 "configuration dialog.\n"
00849 "If you choose to continue, and the keys are needed "
00850 "later on, you will be prompted to specify the keys "
00851 "to use.");
00852 return KMessageBox::warningContinueCancel( 0, msg, i18n("Unusable Signing Keys"),
00853 KStdGuiItem::cont(),
00854 "unusable signing key warning" )
00855 == KMessageBox::Continue ? Kpgp::Ok : Kpgp::Canceled ;
00856 }
00857
00858
00859
00860 for ( std::vector<GpgME::Key>::const_iterator it = d->mOpenPGPSigningKeys.begin() ; it != d->mOpenPGPSigningKeys.end() ; ++it ) {
00861 const Kpgp::Result r = checkKeyNearExpiry( *it, "signing key expires soon warning",
00862 true, true );
00863 if ( r != Kpgp::Ok )
00864 return r;
00865 }
00866
00867 for ( std::vector<GpgME::Key>::const_iterator it = d->mSMIMESigningKeys.begin() ; it != d->mSMIMESigningKeys.end() ; ++it ) {
00868 const Kpgp::Result r = checkKeyNearExpiry( *it, "signing key expires soon warning",
00869 true, true );
00870 if ( r != Kpgp::Ok )
00871 return r;
00872 }
00873
00874 return Kpgp::Ok;
00875 }
00876
00877 void Kleo::KeyResolver::setPrimaryRecipients( const QStringList & addresses ) {
00878 d->mPrimaryEncryptionKeys = getEncryptionItems( addresses );
00879 }
00880
00881 void Kleo::KeyResolver::setSecondaryRecipients( const QStringList & addresses ) {
00882 d->mSecondaryEncryptionKeys = getEncryptionItems( addresses );
00883 }
00884
00885 std::vector<Kleo::KeyResolver::Item> Kleo::KeyResolver::getEncryptionItems( const QStringList & addresses ) {
00886 std::vector<Item> items;
00887 items.reserve( addresses.size() );
00888 for ( QStringList::const_iterator it = addresses.begin() ; it != addresses.end() ; ++it ) {
00889 QString addr = canonicalAddress( *it ).lower();
00890 const ContactPreferences pref = lookupContactPreferences( addr );
00891
00892 items.push_back( Item( *it,
00893 pref.encryptionPreference,
00894 pref.signingPreference,
00895 pref.cryptoMessageFormat ) );
00896 }
00897 return items;
00898 }
00899
00900 static Kleo::Action action( bool doit, bool ask, bool dont, bool requested ) {
00901 if ( requested && !dont )
00902 return Kleo::DoIt;
00903 if ( doit && !ask && !dont )
00904 return Kleo::DoIt;
00905 if ( !doit && ask && !dont )
00906 return Kleo::Ask;
00907 if ( !doit && !ask && dont )
00908 return requested ? Kleo::Conflict : Kleo::DontDoIt ;
00909 if ( !doit && !ask && !dont )
00910 return Kleo::DontDoIt ;
00911 return Kleo::Conflict;
00912 }
00913
00914 Kleo::Action Kleo::KeyResolver::checkSigningPreferences( bool signingRequested ) const {
00915
00916 if ( signingRequested && d->mOpenPGPSigningKeys.empty() && d->mSMIMESigningKeys.empty() )
00917 return Impossible;
00918
00919 SigningPreferenceCounter count;
00920 count = std::for_each( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
00921 count );
00922 count = std::for_each( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
00923 count );
00924
00925 unsigned int sign = count.numAlwaysSign();
00926 unsigned int ask = count.numAlwaysAskForSigning();
00927 const unsigned int dontSign = count.numNeverSign();
00928 if ( signingPossible() ) {
00929 sign += count.numAlwaysSignIfPossible();
00930 ask += count.numAskSigningWheneverPossible();
00931 }
00932
00933 return action( sign, ask, dontSign, signingRequested );
00934 }
00935
00936 bool Kleo::KeyResolver::signingPossible() const {
00937 return !d->mOpenPGPSigningKeys.empty() || !d->mSMIMESigningKeys.empty() ;
00938 }
00939
00940 Kleo::Action Kleo::KeyResolver::checkEncryptionPreferences( bool encryptionRequested ) const {
00941
00942 if ( d->mPrimaryEncryptionKeys.empty() && d->mSecondaryEncryptionKeys.empty() )
00943 return DontDoIt;
00944
00945 if ( encryptionRequested && encryptToSelf() &&
00946 d->mOpenPGPEncryptToSelfKeys.empty() && d->mSMIMEEncryptToSelfKeys.empty() )
00947 return Impossible;
00948
00949 EncryptionPreferenceCounter count( this, mOpportunisticEncyption ? AskWheneverPossible : UnknownPreference );
00950 count = std::for_each( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
00951 count );
00952 count = std::for_each( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
00953 count );
00954
00955 unsigned int encrypt = count.numAlwaysEncrypt();
00956 unsigned int ask = count.numAlwaysAskForEncryption();
00957 const unsigned int dontEncrypt = count.numNeverEncrypt() + count.numNoKey();
00958 if ( encryptionPossible() ) {
00959 encrypt += count.numAlwaysEncryptIfPossible();
00960 ask += count.numAskWheneverPossible();
00961 }
00962
00963 const Action act = action( encrypt, ask, dontEncrypt, encryptionRequested );
00964 if ( act != Ask ||
00965 std::for_each( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
00966 std::for_each( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
00967 EncryptionPreferenceCounter( this, UnknownPreference ) ) ).numAlwaysAskForEncryption() )
00968 return act;
00969 else
00970 return AskOpportunistic;
00971 }
00972
00973 bool Kleo::KeyResolver::encryptionPossible() const {
00974 return std::find_if( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
00975 EmptyKeyList ) == d->mPrimaryEncryptionKeys.end()
00976 && std::find_if( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
00977 EmptyKeyList ) == d->mSecondaryEncryptionKeys.end() ;
00978 }
00979
00980 Kpgp::Result Kleo::KeyResolver::resolveAllKeys( bool& signingRequested, bool& encryptionRequested ) {
00981 if ( !encryptionRequested && !signingRequested ) {
00982
00983
00984 dump();
00985 d->mFormatInfoMap[OpenPGPMIMEFormat].splitInfos.push_back( SplitInfo( allRecipients() ) );
00986 dump();
00987 return Kpgp::Ok;
00988 }
00989 Kpgp::Result result = Kpgp::Ok;
00990 if ( encryptionRequested )
00991 result = resolveEncryptionKeys( signingRequested );
00992 if ( result != Kpgp::Ok )
00993 return result;
00994 if ( signingRequested )
00995 if ( encryptionRequested )
00996 result = resolveSigningKeysForEncryption();
00997 else {
00998 result = resolveSigningKeysForSigningOnly();
00999 if ( result == Kpgp::Failure ) {
01000 signingRequested = false;
01001 return Kpgp::Ok;
01002 }
01003 }
01004 return result;
01005 }
01006
01007 Kpgp::Result Kleo::KeyResolver::resolveEncryptionKeys( bool signingRequested ) {
01008
01009
01010
01011
01012 for ( std::vector<Item>::iterator it = d->mPrimaryEncryptionKeys.begin() ; it != d->mPrimaryEncryptionKeys.end() ; ++it ) {
01013 if ( !it->needKeys )
01014 continue;
01015 it->keys = getEncryptionKeys( it->address, false );
01016 if ( it->keys.empty() )
01017 return Kpgp::Canceled;
01018 QString addr = canonicalAddress( it->address ).lower();
01019 const ContactPreferences pref = lookupContactPreferences( addr );
01020 it->pref = pref.encryptionPreference;
01021 it->signPref = pref.signingPreference;
01022 it->format = pref.cryptoMessageFormat;
01023 }
01024
01025 for ( std::vector<Item>::iterator it = d->mSecondaryEncryptionKeys.begin() ; it != d->mSecondaryEncryptionKeys.end() ; ++it ) {
01026 if ( !it->needKeys )
01027 continue;
01028 it->keys = getEncryptionKeys( it->address, false );
01029 if ( it->keys.empty() )
01030 return Kpgp::Canceled;
01031 QString addr = canonicalAddress( it->address ).lower();
01032 const ContactPreferences pref = lookupContactPreferences( addr );
01033 it->pref = pref.encryptionPreference;
01034 it->signPref = pref.signingPreference;
01035 it->format = pref.cryptoMessageFormat;
01036 }
01037
01038
01039
01040 const Kpgp::Result res = showKeyApprovalDialog();
01041 if ( res != Kpgp::Ok )
01042 return res;
01043
01044
01045
01046
01047
01048
01049
01050
01051 const EncryptionFormatPreferenceCounter primaryCount
01052 = std::for_each( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01053 EncryptionFormatPreferenceCounter() );
01054
01055 CryptoMessageFormat commonFormat = AutoFormat;
01056 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01057 if ( !( concreteCryptoMessageFormats[i] & mCryptoMessageFormats ) )
01058 continue;
01059 if ( signingRequested && signingKeysFor( concreteCryptoMessageFormats[i] ).empty() )
01060 continue;
01061 if ( encryptToSelf() && encryptToSelfKeysFor( concreteCryptoMessageFormats[i] ).empty() )
01062 continue;
01063 if ( primaryCount.numOf( concreteCryptoMessageFormats[i] ) == primaryCount.numTotal() ) {
01064 commonFormat = concreteCryptoMessageFormats[i];
01065 break;
01066 }
01067 }
01068 if ( commonFormat != AutoFormat )
01069 addKeys( d->mPrimaryEncryptionKeys, commonFormat );
01070 else
01071 addKeys( d->mPrimaryEncryptionKeys );
01072
01073 collapseAllSplitInfos();
01074
01075
01076
01077
01078 const EncryptionFormatPreferenceCounter secondaryCount
01079 = std::for_each( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01080 EncryptionFormatPreferenceCounter() );
01081
01082 if ( commonFormat != AutoFormat &&
01083 secondaryCount.numOf( commonFormat ) == secondaryCount.numTotal() )
01084 addKeys( d->mSecondaryEncryptionKeys, commonFormat );
01085 else
01086 addKeys( d->mSecondaryEncryptionKeys );
01087
01088
01089
01090 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01091 const std::vector<SplitInfo> si_list = encryptionItems( concreteCryptoMessageFormats[i] );
01092 for ( std::vector<SplitInfo>::const_iterator sit = si_list.begin() ; sit != si_list.end() ; ++sit )
01093 for ( std::vector<GpgME::Key>::const_iterator kit = sit->keys.begin() ; kit != sit->keys.end() ; ++kit ) {
01094 const Kpgp::Result r = checkKeyNearExpiry( *kit, "other encryption key near expiry warning",
01095 false, false );
01096 if ( r != Kpgp::Ok )
01097 return r;
01098 }
01099 }
01100
01101
01102
01103 if ( !encryptToSelf() )
01104 return Kpgp::Ok;
01105
01106
01107
01108 if ( !encryptionItems( InlineOpenPGPFormat ).empty() ||
01109 !encryptionItems( OpenPGPMIMEFormat ).empty() ) {
01110
01111 if ( d->mOpenPGPEncryptToSelfKeys.empty() ) {
01112 const QString msg = i18n("Examination of recipient's encryption preferences "
01113 "yielded that the message should be encrypted using "
01114 "OpenPGP, at least for some recipients;\n"
01115 "however, you have not configured valid trusted "
01116 "OpenPGP encryption keys for this identity.\n"
01117 "You may continue without encrypting to yourself, "
01118 "but be aware that you will not be able to read your "
01119 "own messages if you do so.");
01120 if ( KMessageBox::warningContinueCancel( 0, msg,
01121 i18n("Unusable Encryption Keys"),
01122 KStdGuiItem::cont(),
01123 "encrypt-to-self will fail warning" )
01124 == KMessageBox::Cancel )
01125 return Kpgp::Canceled;
01126
01127 }
01128 addToAllSplitInfos( d->mOpenPGPEncryptToSelfKeys,
01129 InlineOpenPGPFormat|OpenPGPMIMEFormat );
01130 }
01131
01132
01133
01134 if ( !encryptionItems( SMIMEFormat ).empty() ||
01135 !encryptionItems( SMIMEOpaqueFormat ).empty() ) {
01136
01137 if ( d->mSMIMEEncryptToSelfKeys.empty() ) {
01138
01139 const QString msg = i18n("Examination of recipient's encryption preferences "
01140 "yielded that the message should be encrypted using "
01141 "S/MIME, at least for some recipients;\n"
01142 "however, you have not configured valid "
01143 "S/MIME encryption certificates for this identity.\n"
01144 "You may continue without encrypting to yourself, "
01145 "but be aware that you will not be able to read your "
01146 "own messages if you do so.");
01147 if ( KMessageBox::warningContinueCancel( 0, msg,
01148 i18n("Unusable Encryption Keys"),
01149 KStdGuiItem::cont(),
01150 "encrypt-to-self will fail warning" )
01151 == KMessageBox::Cancel )
01152 return Kpgp::Canceled;
01153
01154 }
01155 addToAllSplitInfos( d->mSMIMEEncryptToSelfKeys,
01156 SMIMEFormat|SMIMEOpaqueFormat );
01157 }
01158
01159
01160
01161
01162 return Kpgp::Ok;
01163 }
01164
01165 Kpgp::Result Kleo::KeyResolver::resolveSigningKeysForEncryption() {
01166 if ( ( !encryptionItems( InlineOpenPGPFormat ).empty() ||
01167 !encryptionItems( OpenPGPMIMEFormat ).empty() )
01168 && d->mOpenPGPSigningKeys.empty() ) {
01169 const QString msg = i18n("Examination of recipient's signing preferences "
01170 "yielded that the message should be signed using "
01171 "OpenPGP, at least for some recipients;\n"
01172 "however, you have not configured valid "
01173 "OpenPGP signing certificates for this identity.");
01174 if ( KMessageBox::warningContinueCancel( 0, msg,
01175 i18n("Unusable Signing Keys"),
01176 i18n("Do Not OpenPGP-Sign"),
01177 "signing will fail warning" )
01178 == KMessageBox::Cancel )
01179 return Kpgp::Canceled;
01180
01181 }
01182 if ( ( !encryptionItems( SMIMEFormat ).empty() ||
01183 !encryptionItems( SMIMEOpaqueFormat ).empty() )
01184 && d->mSMIMESigningKeys.empty() ) {
01185 const QString msg = i18n("Examination of recipient's signing preferences "
01186 "yielded that the message should be signed using "
01187 "S/MIME, at least for some recipients;\n"
01188 "however, you have not configured valid "
01189 "S/MIME signing certificates for this identity.");
01190 if ( KMessageBox::warningContinueCancel( 0, msg,
01191 i18n("Unusable Signing Keys"),
01192 i18n("Do Not S/MIME-Sign"),
01193 "signing will fail warning" )
01194 == KMessageBox::Cancel )
01195 return Kpgp::Canceled;
01196
01197 }
01198
01199
01200
01201
01202 for ( std::map<CryptoMessageFormat,FormatInfo>::iterator it = d->mFormatInfoMap.begin() ; it != d->mFormatInfoMap.end() ; ++it )
01203 if ( !it->second.splitInfos.empty() ) {
01204 dump();
01205 it->second.signKeys = signingKeysFor( it->first );
01206 dump();
01207 }
01208
01209 return Kpgp::Ok;
01210 }
01211
01212 Kpgp::Result Kleo::KeyResolver::resolveSigningKeysForSigningOnly() {
01213
01214
01215
01216
01217 SigningFormatPreferenceCounter count;
01218 count = std::for_each( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01219 count );
01220 count = std::for_each( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01221 count );
01222
01223
01224
01225 CryptoMessageFormat commonFormat = AutoFormat;
01226
01227 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01228 if ( !(mCryptoMessageFormats & concreteCryptoMessageFormats[i]) )
01229 continue;
01230 if ( signingKeysFor( concreteCryptoMessageFormats[i] ).empty() )
01231 continue;
01232 if ( count.numOf( concreteCryptoMessageFormats[i] ) == count.numTotal() ) {
01233 commonFormat = concreteCryptoMessageFormats[i];
01234 break;
01235 }
01236 }
01237
01238 if ( commonFormat != AutoFormat ) {
01239 dump();
01240 FormatInfo & fi = d->mFormatInfoMap[ commonFormat ];
01241 fi.signKeys = signingKeysFor( commonFormat );
01242 fi.splitInfos.resize( 1 );
01243 fi.splitInfos.front() = SplitInfo( allRecipients() );
01244 dump();
01245 return Kpgp::Ok;
01246 }
01247
01248 const QString msg = i18n("Examination of recipient's signing preferences "
01249 "showed no common type of signature matching your "
01250 "available signing keys.\n"
01251 "Send message without signing?" );
01252 if ( KMessageBox::warningContinueCancel( 0, msg, i18n("No signing possible"),
01253 KStdGuiItem::cont() )
01254 == KMessageBox::Continue ) {
01255 d->mFormatInfoMap[OpenPGPMIMEFormat].splitInfos.push_back( SplitInfo( allRecipients() ) );
01256 return Kpgp::Failure;
01257 }
01258 return Kpgp::Canceled;
01259 }
01260
01261 std::vector<GpgME::Key> Kleo::KeyResolver::signingKeysFor( CryptoMessageFormat f ) const {
01262 if ( isOpenPGP( f ) )
01263 return d->mOpenPGPSigningKeys;
01264 if ( isSMIME( f ) )
01265 return d->mSMIMESigningKeys;
01266 return std::vector<GpgME::Key>();
01267 }
01268
01269 std::vector<GpgME::Key> Kleo::KeyResolver::encryptToSelfKeysFor( CryptoMessageFormat f ) const {
01270 if ( isOpenPGP( f ) )
01271 return d->mOpenPGPEncryptToSelfKeys;
01272 if ( isSMIME( f ) )
01273 return d->mSMIMEEncryptToSelfKeys;
01274 return std::vector<GpgME::Key>();
01275 }
01276
01277 QStringList Kleo::KeyResolver::allRecipients() const {
01278 QStringList result;
01279 std::transform( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01280 std::back_inserter( result ), ItemDotAddress );
01281 std::transform( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01282 std::back_inserter( result ), ItemDotAddress );
01283 return result;
01284 }
01285
01286 void Kleo::KeyResolver::collapseAllSplitInfos() {
01287 dump();
01288 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01289 std::map<CryptoMessageFormat,FormatInfo>::iterator pos =
01290 d->mFormatInfoMap.find( concreteCryptoMessageFormats[i] );
01291 if ( pos == d->mFormatInfoMap.end() )
01292 continue;
01293 std::vector<SplitInfo> & v = pos->second.splitInfos;
01294 if ( v.size() < 2 )
01295 continue;
01296 SplitInfo & si = v.front();
01297 for ( std::vector<SplitInfo>::const_iterator it = v.begin() + 1; it != v.end() ; ++it ) {
01298 si.keys.insert( si.keys.end(), it->keys.begin(), it->keys.end() );
01299 qCopy( it->recipients.begin(), it->recipients.end(), std::back_inserter( si.recipients ) );
01300 }
01301 v.resize( 1 );
01302 }
01303 dump();
01304 }
01305
01306 void Kleo::KeyResolver::addToAllSplitInfos( const std::vector<GpgME::Key> & keys, unsigned int f ) {
01307 dump();
01308 if ( !f || keys.empty() )
01309 return;
01310 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01311 if ( !( f & concreteCryptoMessageFormats[i] ) )
01312 continue;
01313 std::map<CryptoMessageFormat,FormatInfo>::iterator pos =
01314 d->mFormatInfoMap.find( concreteCryptoMessageFormats[i] );
01315 if ( pos == d->mFormatInfoMap.end() )
01316 continue;
01317 std::vector<SplitInfo> & v = pos->second.splitInfos;
01318 for ( std::vector<SplitInfo>::iterator it = v.begin() ; it != v.end() ; ++it )
01319 it->keys.insert( it->keys.end(), keys.begin(), keys.end() );
01320 }
01321 dump();
01322 }
01323
01324 void Kleo::KeyResolver::dump() const {
01325 #ifndef NDEBUG
01326 if ( d->mFormatInfoMap.empty() )
01327 std::cerr << "Keyresolver: Format info empty" << std::endl;
01328 for ( std::map<CryptoMessageFormat,FormatInfo>::const_iterator it = d->mFormatInfoMap.begin() ; it != d->mFormatInfoMap.end() ; ++it ) {
01329 std::cerr << "Format info for " << Kleo::cryptoMessageFormatToString( it->first )
01330 << ":" << std::endl
01331 << " Signing keys: ";
01332 for ( std::vector<GpgME::Key>::const_iterator sit = it->second.signKeys.begin() ; sit != it->second.signKeys.end() ; ++sit )
01333 std::cerr << sit->shortKeyID() << " ";
01334 std::cerr << std::endl;
01335 unsigned int i = 0;
01336 for ( std::vector<SplitInfo>::const_iterator sit = it->second.splitInfos.begin() ; sit != it->second.splitInfos.end() ; ++sit, ++i ) {
01337 std::cerr << " SplitInfo #" << i << " encryption keys: ";
01338 for ( std::vector<GpgME::Key>::const_iterator kit = sit->keys.begin() ; kit != sit->keys.end() ; ++kit )
01339 std::cerr << kit->shortKeyID() << " ";
01340 std::cerr << std::endl
01341 << " SplitInfo #" << i << " recipients: "
01342 << sit->recipients.join(", ").utf8() << std::endl;
01343 }
01344 }
01345 #endif
01346 }
01347
01348 Kpgp::Result Kleo::KeyResolver::showKeyApprovalDialog() {
01349 const bool showKeysForApproval = showApprovalDialog()
01350 || std::find_if( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01351 ApprovalNeeded ) != d->mPrimaryEncryptionKeys.end()
01352 || std::find_if( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01353 ApprovalNeeded ) != d->mSecondaryEncryptionKeys.end() ;
01354
01355 if ( !showKeysForApproval )
01356 return Kpgp::Ok;
01357
01358 std::vector<Kleo::KeyApprovalDialog::Item> items;
01359 items.reserve( d->mPrimaryEncryptionKeys.size() +
01360 d->mSecondaryEncryptionKeys.size() );
01361 std::copy( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01362 std::back_inserter( items ) );
01363 std::copy( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01364 std::back_inserter( items ) );
01365
01366 std::vector<GpgME::Key> senderKeys;
01367 senderKeys.reserve( d->mOpenPGPEncryptToSelfKeys.size() +
01368 d->mSMIMEEncryptToSelfKeys.size() );
01369 std::copy( d->mOpenPGPEncryptToSelfKeys.begin(), d->mOpenPGPEncryptToSelfKeys.end(),
01370 std::back_inserter( senderKeys ) );
01371 std::copy( d->mSMIMEEncryptToSelfKeys.begin(), d->mSMIMEEncryptToSelfKeys.end(),
01372 std::back_inserter( senderKeys ) );
01373
01374 const KCursorSaver idle( KBusyPtr::idle() );
01375
01376 Kleo::KeyApprovalDialog dlg( items, senderKeys );
01377
01378 if ( dlg.exec() == QDialog::Rejected )
01379 return Kpgp::Canceled;
01380
01381 items = dlg.items();
01382 senderKeys = dlg.senderKeys();
01383
01384 if ( dlg.preferencesChanged() ) {
01385 for ( uint i = 0; i < items.size(); ++i ) {
01386 ContactPreferences pref = lookupContactPreferences( items[i].address );
01387 pref.encryptionPreference = items[i].pref;
01388 pref.pgpKeyFingerprints.clear();
01389 pref.smimeCertFingerprints.clear();
01390 const std::vector<GpgME::Key> & keys = items[i].keys;
01391 for ( std::vector<GpgME::Key>::const_iterator it = keys.begin(), end = keys.end() ; it != end ; ++it ) {
01392 if ( it->protocol() == GpgME::Context::OpenPGP ) {
01393 if ( const char * fpr = it->primaryFingerprint() )
01394 pref.pgpKeyFingerprints.push_back( fpr );
01395 } else if ( it->protocol() == GpgME::Context::CMS ) {
01396 if ( const char * fpr = it->primaryFingerprint() )
01397 pref.smimeCertFingerprints.push_back( fpr );
01398 }
01399 }
01400 saveContactPreference( items[i].address, pref );
01401 }
01402 }
01403
01404
01405
01406 if ( encryptToSelf() && senderKeys.empty() ) {
01407 const QString msg = i18n("You did not select an encryption key for yourself "
01408 "(encrypt to self). You will not be able to decrypt "
01409 "your own message if you encrypt it.");
01410 if ( KMessageBox::warningContinueCancel( 0, msg,
01411 i18n("Missing Key Warning"),
01412 i18n("&Encrypt") )
01413 == KMessageBox::Cancel )
01414 return Kpgp::Canceled;
01415 else
01416 mEncryptToSelf = false;
01417 }
01418
01419
01420 const unsigned int emptyListCount =
01421 std::count_if( items.begin(), items.end(), EmptyKeyList );
01422
01423
01424
01425 if ( items.size() == emptyListCount ) {
01426 const QString msg = ( d->mPrimaryEncryptionKeys.size() +
01427 d->mSecondaryEncryptionKeys.size() == 1 )
01428 ? i18n("You did not select an encryption key for the "
01429 "recipient of this message; therefore, the message "
01430 "will not be encrypted.")
01431 : i18n("You did not select an encryption key for any of the "
01432 "recipients of this message; therefore, the message "
01433 "will not be encrypted.");
01434 if ( KMessageBox::warningContinueCancel( 0, msg,
01435 i18n("Missing Key Warning"),
01436 i18n("Send &Unencrypted") )
01437 == KMessageBox::Cancel )
01438 return Kpgp::Canceled;
01439 } else if ( emptyListCount > 0 ) {
01440 const QString msg = ( emptyListCount == 1 )
01441 ? i18n("You did not select an encryption key for one of "
01442 "the recipients: this person will not be able to "
01443 "decrypt the message if you encrypt it.")
01444 : i18n("You did not select encryption keys for some of "
01445 "the recipients: these persons will not be able to "
01446 "decrypt the message if you encrypt it." );
01447 KCursorSaver idle( KBusyPtr::idle() );
01448 if ( KMessageBox::warningContinueCancel( 0, msg,
01449 i18n("Missing Key Warning"),
01450 i18n("&Encrypt") )
01451 == KMessageBox::Cancel )
01452 return Kpgp::Canceled;
01453 }
01454
01455 std::transform( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01456 items.begin(),
01457 d->mPrimaryEncryptionKeys.begin(),
01458 CopyKeysAndEncryptionPreferences );
01459 std::transform( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01460 items.begin() + d->mPrimaryEncryptionKeys.size(),
01461 d->mSecondaryEncryptionKeys.begin(),
01462 CopyKeysAndEncryptionPreferences );
01463
01464 d->mOpenPGPEncryptToSelfKeys.clear();
01465 d->mSMIMEEncryptToSelfKeys.clear();
01466
01467 std::remove_copy_if( senderKeys.begin(), senderKeys.end(),
01468 std::back_inserter( d->mOpenPGPEncryptToSelfKeys ),
01469 NotValidTrustedOpenPGPEncryptionKey );
01470 std::remove_copy_if( senderKeys.begin(), senderKeys.end(),
01471 std::back_inserter( d->mSMIMEEncryptToSelfKeys ),
01472 NotValidTrustedSMIMEEncryptionKey );
01473
01474 return Kpgp::Ok;
01475 }
01476
01477 std::vector<Kleo::KeyResolver::SplitInfo> Kleo::KeyResolver::encryptionItems( Kleo::CryptoMessageFormat f ) const {
01478 dump();
01479 std::map<CryptoMessageFormat,FormatInfo>::const_iterator it =
01480 d->mFormatInfoMap.find( f );
01481 return it != d->mFormatInfoMap.end() ? it->second.splitInfos : std::vector<SplitInfo>() ;
01482 }
01483
01484 std::vector<GpgME::Key> Kleo::KeyResolver::signingKeys( CryptoMessageFormat f ) const {
01485 dump();
01486 std::map<CryptoMessageFormat,FormatInfo>::const_iterator it =
01487 d->mFormatInfoMap.find( f );
01488 return it != d->mFormatInfoMap.end() ? it->second.signKeys : std::vector<GpgME::Key>() ;
01489 }
01490
01491
01492
01493
01494
01495
01496
01497
01498 std::vector<GpgME::Key> Kleo::KeyResolver::selectKeys( const QString & person, const QString & msg, const std::vector<GpgME::Key> & selectedKeys ) const {
01499 Kleo::KeySelectionDialog dlg( i18n("Encryption Key Selection"),
01500 msg, selectedKeys,
01501 Kleo::KeySelectionDialog::ValidEncryptionKeys,
01502 true, true );
01503
01504 if ( dlg.exec() != QDialog::Accepted )
01505 return std::vector<GpgME::Key>();
01506 std::vector<GpgME::Key> keys = dlg.selectedKeys();
01507 keys.erase( std::remove_if( keys.begin(), keys.end(),
01508 NotValidTrustedEncryptionKey ),
01509 keys.end() );
01510 if ( !keys.empty() && dlg.rememberSelection() )
01511 setKeysForAddress( person, dlg.pgpKeyFingerprints(), dlg.smimeFingerprints() );
01512 return keys;
01513 }
01514
01515
01516 std::vector<GpgME::Key> Kleo::KeyResolver::getEncryptionKeys( const QString & person, bool quiet ) const {
01517
01518 const QString address = canonicalAddress( person ).lower();
01519
01520
01521 const QStringList fingerprints = keysForAddress( address );
01522
01523 if ( !fingerprints.empty() ) {
01524 kdDebug() << "Using encryption keys 0x"
01525 << fingerprints.join( ", 0x" )
01526 << " for " << person << endl;
01527 std::vector<GpgME::Key> keys = lookup( fingerprints );
01528 if ( !keys.empty() ) {
01529
01530 if ( std::find_if( keys.begin(), keys.end(),
01531 NotValidTrustedEncryptionKey ) != keys.end() ) {
01532
01533
01534
01535
01536 keys = selectKeys( person,
01537 i18n("if in your language something like "
01538 "'key(s)' isn't possible please "
01539 "use the plural in the translation",
01540 "There is a problem with the "
01541 "encryption key(s) for \"%1\".\n\n"
01542 "Please re-select the key(s) which should "
01543 "be used for this recipient.").arg(person),
01544 keys );
01545 }
01546 keys = TrustedOrConfirmed( keys );
01547
01548 if ( !keys.empty() )
01549 return keys;
01550
01551 }
01552 }
01553
01554
01555 std::vector<GpgME::Key> matchingKeys = lookup( person );
01556 matchingKeys.erase( std::remove_if( matchingKeys.begin(), matchingKeys.end(),
01557 NotValidEncryptionKey ),
01558 matchingKeys.end() );
01559
01560
01561 if ( matchingKeys.empty() ) {
01562 matchingKeys = lookup( address );
01563 matchingKeys.erase( std::remove_if( matchingKeys.begin(), matchingKeys.end(),
01564 NotValidEncryptionKey ),
01565 matchingKeys.end() );
01566 }
01567
01568
01569
01570
01571 if ( !quiet )
01572 matchingKeys = TrustedOrConfirmed( matchingKeys );
01573 if ( quiet || matchingKeys.size() == 1 )
01574 return matchingKeys;
01575
01576
01577
01578
01579 return TrustedOrConfirmed( selectKeys( person,
01580 matchingKeys.empty()
01581 ? i18n("if in your language something like "
01582 "'key(s)' isn't possible please "
01583 "use the plural in the translation",
01584 "<qt>No valid and trusted encryption key was "
01585 "found for \"%1\".<br/><br/>"
01586 "Select the key(s) which should "
01587 "be used for this recipient. If there is no suitable key in the list "
01588 "you can also <a href=\"%2\">search for external keys</a>.</qt>")
01589 .arg( QStyleSheet::escape(person), KURL::encode_string( KPIM::getEmailAddress(person) ) )
01590 : i18n("if in your language something like "
01591 "'key(s)' isn't possible please "
01592 "use the plural in the translation",
01593 "More than one key matches \"%1\".\n\n"
01594 "Select the key(s) which should "
01595 "be used for this recipient.").arg(person),
01596 matchingKeys ) );
01597 }
01598
01599
01600 std::vector<GpgME::Key> Kleo::KeyResolver::lookup( const QStringList & patterns, bool secret ) const {
01601 if ( patterns.empty() )
01602 return std::vector<GpgME::Key>();
01603 kdDebug() << "Kleo::KeyResolver::lookup( \"" << patterns.join( "\", \"" )
01604 << "\", " << secret << " )" << endl;
01605 std::vector<GpgME::Key> result;
01606 if ( mCryptoMessageFormats & (InlineOpenPGPFormat|OpenPGPMIMEFormat) )
01607 if ( const Kleo::CryptoBackend::Protocol * p = Kleo::CryptoBackendFactory::instance()->openpgp() ) {
01608 std::auto_ptr<Kleo::KeyListJob> job( p->keyListJob( false, false, true ) );
01609 if ( job.get() ) {
01610 std::vector<GpgME::Key> keys;
01611 job->exec( patterns, secret, keys );
01612 result.insert( result.end(), keys.begin(), keys.end() );
01613 }
01614 }
01615 if ( mCryptoMessageFormats & (SMIMEFormat|SMIMEOpaqueFormat) )
01616 if ( const Kleo::CryptoBackend::Protocol * p = Kleo::CryptoBackendFactory::instance()->smime() ) {
01617 std::auto_ptr<Kleo::KeyListJob> job( p->keyListJob( false, false, true ) );
01618 if ( job.get() ) {
01619 std::vector<GpgME::Key> keys;
01620 job->exec( patterns, secret, keys );
01621 result.insert( result.end(), keys.begin(), keys.end() );
01622 }
01623 }
01624 kdDebug() << " returned " << result.size() << " keys" << endl;
01625 return result;
01626 }
01627
01628 void Kleo::KeyResolver::addKeys( const std::vector<Item> & items, CryptoMessageFormat f ) {
01629 dump();
01630 for ( std::vector<Item>::const_iterator it = items.begin() ; it != items.end() ; ++it ) {
01631 SplitInfo si( it->address );
01632 std::remove_copy_if( it->keys.begin(), it->keys.end(),
01633 std::back_inserter( si.keys ), IsNotForFormat( f ) );
01634 dump();
01635 kdWarning( si.keys.empty() )
01636 << "Kleo::KeyResolver::addKeys(): Fix EncryptionFormatPreferenceCounter. "
01637 << "It detected a common format, but the list of such keys for recipient \""
01638 << it->address << "\" is empty!" << endl;
01639 d->mFormatInfoMap[ f ].splitInfos.push_back( si );
01640 }
01641 dump();
01642 }
01643
01644 void Kleo::KeyResolver::addKeys( const std::vector<Item> & items ) {
01645 dump();
01646 for ( std::vector<Item>::const_iterator it = items.begin() ; it != items.end() ; ++it ) {
01647 SplitInfo si( it->address );
01648 CryptoMessageFormat f = AutoFormat;
01649 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01650 if ( concreteCryptoMessageFormats[i] & it->format ) {
01651 f = concreteCryptoMessageFormats[i];
01652 break;
01653 }
01654 }
01655 if ( f == AutoFormat )
01656 kdWarning() << "Kleo::KeyResolver::addKeys(): Something went wrong. Didn't find a format for \""
01657 << it->address << "\"" << endl;
01658 else
01659 std::remove_copy_if( it->keys.begin(), it->keys.end(),
01660 std::back_inserter( si.keys ), IsNotForFormat( f ) );
01661 d->mFormatInfoMap[ f ].splitInfos.push_back( si );
01662 }
01663 dump();
01664 }
01665
01666 Kleo::KeyResolver::ContactPreferences Kleo::KeyResolver::lookupContactPreferences( const QString& address ) const
01667 {
01668 const Private::ContactPreferencesMap::iterator it =
01669 d->mContactPreferencesMap.find( address );
01670 if ( it != d->mContactPreferencesMap.end() )
01671 return it->second;
01672
01673 KABC::AddressBook *ab = KABC::StdAddressBook::self( true );
01674 const KABC::Addressee::List res = ab->findByEmail( address );
01675 ContactPreferences pref;
01676 if ( !res.isEmpty() ) {
01677 KABC::Addressee addr = res.first();
01678 QString encryptPref = addr.custom( "KADDRESSBOOK", "CRYPTOENCRYPTPREF" );
01679 pref.encryptionPreference = Kleo::stringToEncryptionPreference( encryptPref );
01680 QString signPref = addr.custom( "KADDRESSBOOK", "CRYPTOSIGNPREF" );
01681 pref.signingPreference = Kleo::stringToSigningPreference( signPref );
01682 QString cryptoFormats = addr.custom( "KADDRESSBOOK", "CRYPTOPROTOPREF" );
01683 pref.cryptoMessageFormat = Kleo::stringToCryptoMessageFormat( cryptoFormats );
01684 pref.pgpKeyFingerprints = QStringList::split( ',', addr.custom( "KADDRESSBOOK", "OPENPGPFP" ) );
01685 pref.smimeCertFingerprints = QStringList::split( ',', addr.custom( "KADDRESSBOOK", "SMIMEFP" ) );
01686 }
01687
01688 d->mContactPreferencesMap.insert( std::make_pair( address, pref ) );
01689 return pref;
01690 }
01691
01692 void Kleo::KeyResolver::saveContactPreference( const QString& email, const ContactPreferences& pref ) const
01693 {
01694 d->mContactPreferencesMap.insert( std::make_pair( email, pref ) );
01695 KABC::AddressBook *ab = KABC::StdAddressBook::self( true );
01696 KABC::Addressee::List res = ab->findByEmail( email );
01697
01698 KABC::Addressee addr;
01699 if ( res.isEmpty() ) {
01700 bool ok = true;
01701 QString fullName = KInputDialog::getText( i18n( "Name Selection" ), i18n( "Which name shall the contact '%1' have in your addressbook?" ).arg( email ), QString::null, &ok );
01702 if ( ok ) {
01703 addr.setNameFromString( fullName );
01704 addr.insertEmail( email, true );
01705 } else
01706 return;
01707 } else
01708 addr = res.first();
01709
01710 addr.insertCustom( "KADDRESSBOOK", "CRYPTOENCRYPTPREF", Kleo::encryptionPreferenceToString( pref.encryptionPreference ) );
01711 addr.insertCustom( "KADDRESSBOOK", "CRYPTOSIGNPREF", Kleo::signingPreferenceToString( pref.signingPreference ) );
01712 addr.insertCustom( "KADDRESSBOOK", "CRYPTOPROTOPREF", cryptoMessageFormatToString( pref.cryptoMessageFormat ) );
01713 addr.insertCustom( "KADDRESSBOOK", "OPENPGPFP", pref.pgpKeyFingerprints.join( "," ) );
01714 addr.insertCustom( "KADDRESSBOOK", "SMIMEFP", pref.smimeCertFingerprints.join( "," ) );
01715
01716 ab->insertAddressee( addr );
01717 KABC::Ticket *ticket = ab->requestSaveTicket( addr.resource() );
01718 if ( ticket )
01719 ab->save( ticket );
01720
01721
01722 }
01723
01724 Kleo::KeyResolver::ContactPreferences::ContactPreferences()
01725 : encryptionPreference( UnknownPreference ),
01726 signingPreference( UnknownSigningPreference ),
01727 cryptoMessageFormat( AutoFormat )
01728 {
01729 }
01730
01731 QStringList Kleo::KeyResolver::keysForAddress( const QString & address ) const {
01732 if( address.isEmpty() ) {
01733 return QStringList();
01734 }
01735 QString addr = canonicalAddress( address ).lower();
01736 const ContactPreferences pref = lookupContactPreferences( addr );
01737 return pref.pgpKeyFingerprints + pref.smimeCertFingerprints;
01738 }
01739
01740 void Kleo::KeyResolver::setKeysForAddress( const QString& address, const QStringList& pgpKeyFingerprints, const QStringList& smimeCertFingerprints ) const {
01741 if( address.isEmpty() ) {
01742 return;
01743 }
01744 QString addr = canonicalAddress( address ).lower();
01745 ContactPreferences pref = lookupContactPreferences( addr );
01746 pref.pgpKeyFingerprints = pgpKeyFingerprints;
01747 pref.smimeCertFingerprints = smimeCertFingerprints;
01748 saveContactPreference( addr, pref );
01749 }