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