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 }
01063 else {
01064 result = resolveSigningKeysForSigningOnly();
01065 if ( result == Kpgp::Failure ) {
01066 signingRequested = false;
01067 return Kpgp::Ok;
01068 }
01069 }
01070 }
01071 return result;
01072 }
01073
01074 Kpgp::Result Kleo::KeyResolver::resolveEncryptionKeys( bool signingRequested ) {
01075
01076
01077
01078
01079 for ( std::vector<Item>::iterator it = d->mPrimaryEncryptionKeys.begin() ; it != d->mPrimaryEncryptionKeys.end() ; ++it ) {
01080 if ( !it->needKeys )
01081 continue;
01082 it->keys = getEncryptionKeys( it->address, false );
01083 if ( it->keys.empty() )
01084 return Kpgp::Canceled;
01085 QString addr = canonicalAddress( it->address ).lower();
01086 const ContactPreferences pref = lookupContactPreferences( addr );
01087 it->pref = pref.encryptionPreference;
01088 it->signPref = pref.signingPreference;
01089 it->format = pref.cryptoMessageFormat;
01090 }
01091
01092 for ( std::vector<Item>::iterator it = d->mSecondaryEncryptionKeys.begin() ; it != d->mSecondaryEncryptionKeys.end() ; ++it ) {
01093 if ( !it->needKeys )
01094 continue;
01095 it->keys = getEncryptionKeys( it->address, false );
01096 if ( it->keys.empty() )
01097 return Kpgp::Canceled;
01098 QString addr = canonicalAddress( it->address ).lower();
01099 const ContactPreferences pref = lookupContactPreferences( addr );
01100 it->pref = pref.encryptionPreference;
01101 it->signPref = pref.signingPreference;
01102 it->format = pref.cryptoMessageFormat;
01103 }
01104
01105
01106
01107 const Kpgp::Result res = showKeyApprovalDialog();
01108 if ( res != Kpgp::Ok )
01109 return res;
01110
01111
01112
01113
01114
01115
01116
01117
01118 const EncryptionFormatPreferenceCounter primaryCount
01119 = std::for_each( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01120 EncryptionFormatPreferenceCounter() );
01121
01122 CryptoMessageFormat commonFormat = AutoFormat;
01123 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01124 if ( !( concreteCryptoMessageFormats[i] & mCryptoMessageFormats ) )
01125 continue;
01126 if ( signingRequested && signingKeysFor( concreteCryptoMessageFormats[i] ).empty() )
01127 continue;
01128 if ( encryptToSelf() && encryptToSelfKeysFor( concreteCryptoMessageFormats[i] ).empty() )
01129 continue;
01130 if ( primaryCount.numOf( concreteCryptoMessageFormats[i] ) == primaryCount.numTotal() ) {
01131 commonFormat = concreteCryptoMessageFormats[i];
01132 break;
01133 }
01134 }
01135 if ( commonFormat != AutoFormat )
01136 addKeys( d->mPrimaryEncryptionKeys, commonFormat );
01137 else
01138 addKeys( d->mPrimaryEncryptionKeys );
01139
01140 collapseAllSplitInfos();
01141
01142
01143
01144
01145 const EncryptionFormatPreferenceCounter secondaryCount
01146 = std::for_each( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01147 EncryptionFormatPreferenceCounter() );
01148
01149 if ( commonFormat != AutoFormat &&
01150 secondaryCount.numOf( commonFormat ) == secondaryCount.numTotal() )
01151 addKeys( d->mSecondaryEncryptionKeys, commonFormat );
01152 else
01153 addKeys( d->mSecondaryEncryptionKeys );
01154
01155
01156
01157 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01158 const std::vector<SplitInfo> si_list = encryptionItems( concreteCryptoMessageFormats[i] );
01159 for ( std::vector<SplitInfo>::const_iterator sit = si_list.begin() ; sit != si_list.end() ; ++sit )
01160 for ( std::vector<GpgME::Key>::const_iterator kit = sit->keys.begin() ; kit != sit->keys.end() ; ++kit ) {
01161 const Kpgp::Result r = checkKeyNearExpiry( *kit, "other encryption key near expiry warning",
01162 false, false );
01163 if ( r != Kpgp::Ok )
01164 return r;
01165 }
01166 }
01167
01168
01169
01170 if ( !encryptToSelf() )
01171 return Kpgp::Ok;
01172
01173
01174
01175 if ( !encryptionItems( InlineOpenPGPFormat ).empty() ||
01176 !encryptionItems( OpenPGPMIMEFormat ).empty() ) {
01177
01178 if ( d->mOpenPGPEncryptToSelfKeys.empty() ) {
01179 const QString msg = i18n("Examination of recipient's encryption preferences "
01180 "yielded that the message should be encrypted using "
01181 "OpenPGP, at least for some recipients;\n"
01182 "however, you have not configured valid trusted "
01183 "OpenPGP encryption keys for this identity.\n"
01184 "You may continue without encrypting to yourself, "
01185 "but be aware that you will not be able to read your "
01186 "own messages if you do so.");
01187 if ( KMessageBox::warningContinueCancel( 0, msg,
01188 i18n("Unusable Encryption Keys"),
01189 KStdGuiItem::cont(),
01190 "encrypt-to-self will fail warning" )
01191 == KMessageBox::Cancel )
01192 return Kpgp::Canceled;
01193
01194 }
01195 addToAllSplitInfos( d->mOpenPGPEncryptToSelfKeys,
01196 InlineOpenPGPFormat|OpenPGPMIMEFormat );
01197 }
01198
01199
01200
01201 if ( !encryptionItems( SMIMEFormat ).empty() ||
01202 !encryptionItems( SMIMEOpaqueFormat ).empty() ) {
01203
01204 if ( d->mSMIMEEncryptToSelfKeys.empty() ) {
01205
01206 const QString msg = i18n("Examination of recipient's encryption preferences "
01207 "yielded that the message should be encrypted using "
01208 "S/MIME, at least for some recipients;\n"
01209 "however, you have not configured valid "
01210 "S/MIME encryption certificates for this identity.\n"
01211 "You may continue without encrypting to yourself, "
01212 "but be aware that you will not be able to read your "
01213 "own messages if you do so.");
01214 if ( KMessageBox::warningContinueCancel( 0, msg,
01215 i18n("Unusable Encryption Keys"),
01216 KStdGuiItem::cont(),
01217 "encrypt-to-self will fail warning" )
01218 == KMessageBox::Cancel )
01219 return Kpgp::Canceled;
01220
01221 }
01222 addToAllSplitInfos( d->mSMIMEEncryptToSelfKeys,
01223 SMIMEFormat|SMIMEOpaqueFormat );
01224 }
01225
01226
01227
01228
01229 return Kpgp::Ok;
01230 }
01231
01232 Kpgp::Result Kleo::KeyResolver::resolveSigningKeysForEncryption() {
01233 if ( ( !encryptionItems( InlineOpenPGPFormat ).empty() ||
01234 !encryptionItems( OpenPGPMIMEFormat ).empty() )
01235 && d->mOpenPGPSigningKeys.empty() ) {
01236 const QString msg = i18n("Examination of recipient's signing preferences "
01237 "yielded that the message should be signed using "
01238 "OpenPGP, at least for some recipients;\n"
01239 "however, you have not configured valid "
01240 "OpenPGP signing certificates for this identity.");
01241 if ( KMessageBox::warningContinueCancel( 0, msg,
01242 i18n("Unusable Signing Keys"),
01243 i18n("Do Not OpenPGP-Sign"),
01244 "signing will fail warning" )
01245 == KMessageBox::Cancel )
01246 return Kpgp::Canceled;
01247
01248 }
01249 if ( ( !encryptionItems( SMIMEFormat ).empty() ||
01250 !encryptionItems( SMIMEOpaqueFormat ).empty() )
01251 && d->mSMIMESigningKeys.empty() ) {
01252 const QString msg = i18n("Examination of recipient's signing preferences "
01253 "yielded that the message should be signed using "
01254 "S/MIME, at least for some recipients;\n"
01255 "however, you have not configured valid "
01256 "S/MIME signing certificates for this identity.");
01257 if ( KMessageBox::warningContinueCancel( 0, msg,
01258 i18n("Unusable Signing Keys"),
01259 i18n("Do Not S/MIME-Sign"),
01260 "signing will fail warning" )
01261 == KMessageBox::Cancel )
01262 return Kpgp::Canceled;
01263
01264 }
01265
01266
01267
01268
01269 for ( std::map<CryptoMessageFormat,FormatInfo>::iterator it = d->mFormatInfoMap.begin() ; it != d->mFormatInfoMap.end() ; ++it )
01270 if ( !it->second.splitInfos.empty() ) {
01271 dump();
01272 it->second.signKeys = signingKeysFor( it->first );
01273 dump();
01274 }
01275
01276 return Kpgp::Ok;
01277 }
01278
01279 Kpgp::Result Kleo::KeyResolver::resolveSigningKeysForSigningOnly() {
01280
01281
01282
01283
01284 SigningFormatPreferenceCounter count;
01285 count = std::for_each( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01286 count );
01287 count = std::for_each( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01288 count );
01289
01290
01291
01292 CryptoMessageFormat commonFormat = AutoFormat;
01293
01294 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01295 if ( !(mCryptoMessageFormats & concreteCryptoMessageFormats[i]) )
01296 continue;
01297 if ( signingKeysFor( concreteCryptoMessageFormats[i] ).empty() )
01298 continue;
01299 if ( count.numOf( concreteCryptoMessageFormats[i] ) == count.numTotal() ) {
01300 commonFormat = concreteCryptoMessageFormats[i];
01301 break;
01302 }
01303 }
01304
01305 if ( commonFormat != AutoFormat ) {
01306 dump();
01307 FormatInfo & fi = d->mFormatInfoMap[ commonFormat ];
01308 fi.signKeys = signingKeysFor( commonFormat );
01309 fi.splitInfos.resize( 1 );
01310 fi.splitInfos.front() = SplitInfo( allRecipients() );
01311 dump();
01312 return Kpgp::Ok;
01313 }
01314
01315 const QString msg = i18n("Examination of recipient's signing preferences "
01316 "showed no common type of signature matching your "
01317 "available signing keys.\n"
01318 "Send message without signing?" );
01319 if ( KMessageBox::warningContinueCancel( 0, msg, i18n("No signing possible"),
01320 KStdGuiItem::cont() )
01321 == KMessageBox::Continue ) {
01322 d->mFormatInfoMap[OpenPGPMIMEFormat].splitInfos.push_back( SplitInfo( allRecipients() ) );
01323 return Kpgp::Failure;
01324 }
01325 return Kpgp::Canceled;
01326 }
01327
01328 std::vector<GpgME::Key> Kleo::KeyResolver::signingKeysFor( CryptoMessageFormat f ) const {
01329 if ( isOpenPGP( f ) )
01330 return d->mOpenPGPSigningKeys;
01331 if ( isSMIME( f ) )
01332 return d->mSMIMESigningKeys;
01333 return std::vector<GpgME::Key>();
01334 }
01335
01336 std::vector<GpgME::Key> Kleo::KeyResolver::encryptToSelfKeysFor( CryptoMessageFormat f ) const {
01337 if ( isOpenPGP( f ) )
01338 return d->mOpenPGPEncryptToSelfKeys;
01339 if ( isSMIME( f ) )
01340 return d->mSMIMEEncryptToSelfKeys;
01341 return std::vector<GpgME::Key>();
01342 }
01343
01344 QStringList Kleo::KeyResolver::allRecipients() const {
01345 QStringList result;
01346 std::transform( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01347 std::back_inserter( result ), ItemDotAddress );
01348 std::transform( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01349 std::back_inserter( result ), ItemDotAddress );
01350 return result;
01351 }
01352
01353 void Kleo::KeyResolver::collapseAllSplitInfos() {
01354 dump();
01355 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01356 std::map<CryptoMessageFormat,FormatInfo>::iterator pos =
01357 d->mFormatInfoMap.find( concreteCryptoMessageFormats[i] );
01358 if ( pos == d->mFormatInfoMap.end() )
01359 continue;
01360 std::vector<SplitInfo> & v = pos->second.splitInfos;
01361 if ( v.size() < 2 )
01362 continue;
01363 SplitInfo & si = v.front();
01364 for ( std::vector<SplitInfo>::const_iterator it = v.begin() + 1; it != v.end() ; ++it ) {
01365 si.keys.insert( si.keys.end(), it->keys.begin(), it->keys.end() );
01366 qCopy( it->recipients.begin(), it->recipients.end(), std::back_inserter( si.recipients ) );
01367 }
01368 v.resize( 1 );
01369 }
01370 dump();
01371 }
01372
01373 void Kleo::KeyResolver::addToAllSplitInfos( const std::vector<GpgME::Key> & keys, unsigned int f ) {
01374 dump();
01375 if ( !f || keys.empty() )
01376 return;
01377 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01378 if ( !( f & concreteCryptoMessageFormats[i] ) )
01379 continue;
01380 std::map<CryptoMessageFormat,FormatInfo>::iterator pos =
01381 d->mFormatInfoMap.find( concreteCryptoMessageFormats[i] );
01382 if ( pos == d->mFormatInfoMap.end() )
01383 continue;
01384 std::vector<SplitInfo> & v = pos->second.splitInfos;
01385 for ( std::vector<SplitInfo>::iterator it = v.begin() ; it != v.end() ; ++it )
01386 it->keys.insert( it->keys.end(), keys.begin(), keys.end() );
01387 }
01388 dump();
01389 }
01390
01391 void Kleo::KeyResolver::dump() const {
01392 #ifndef NDEBUG
01393 if ( d->mFormatInfoMap.empty() )
01394 std::cerr << "Keyresolver: Format info empty" << std::endl;
01395 for ( std::map<CryptoMessageFormat,FormatInfo>::const_iterator it = d->mFormatInfoMap.begin() ; it != d->mFormatInfoMap.end() ; ++it ) {
01396 std::cerr << "Format info for " << Kleo::cryptoMessageFormatToString( it->first )
01397 << ":" << std::endl
01398 << " Signing keys: ";
01399 for ( std::vector<GpgME::Key>::const_iterator sit = it->second.signKeys.begin() ; sit != it->second.signKeys.end() ; ++sit )
01400 std::cerr << sit->shortKeyID() << " ";
01401 std::cerr << std::endl;
01402 unsigned int i = 0;
01403 for ( std::vector<SplitInfo>::const_iterator sit = it->second.splitInfos.begin() ; sit != it->second.splitInfos.end() ; ++sit, ++i ) {
01404 std::cerr << " SplitInfo #" << i << " encryption keys: ";
01405 for ( std::vector<GpgME::Key>::const_iterator kit = sit->keys.begin() ; kit != sit->keys.end() ; ++kit )
01406 std::cerr << kit->shortKeyID() << " ";
01407 std::cerr << std::endl
01408 << " SplitInfo #" << i << " recipients: "
01409 << sit->recipients.join(", ").utf8() << std::endl;
01410 }
01411 }
01412 #endif
01413 }
01414
01415 Kpgp::Result Kleo::KeyResolver::showKeyApprovalDialog() {
01416 const bool showKeysForApproval = showApprovalDialog()
01417 || std::find_if( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01418 ApprovalNeeded ) != d->mPrimaryEncryptionKeys.end()
01419 || std::find_if( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01420 ApprovalNeeded ) != d->mSecondaryEncryptionKeys.end() ;
01421
01422 if ( !showKeysForApproval )
01423 return Kpgp::Ok;
01424
01425 std::vector<Kleo::KeyApprovalDialog::Item> items;
01426 items.reserve( d->mPrimaryEncryptionKeys.size() +
01427 d->mSecondaryEncryptionKeys.size() );
01428 std::copy( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01429 std::back_inserter( items ) );
01430 std::copy( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01431 std::back_inserter( items ) );
01432
01433 std::vector<GpgME::Key> senderKeys;
01434 senderKeys.reserve( d->mOpenPGPEncryptToSelfKeys.size() +
01435 d->mSMIMEEncryptToSelfKeys.size() );
01436 std::copy( d->mOpenPGPEncryptToSelfKeys.begin(), d->mOpenPGPEncryptToSelfKeys.end(),
01437 std::back_inserter( senderKeys ) );
01438 std::copy( d->mSMIMEEncryptToSelfKeys.begin(), d->mSMIMEEncryptToSelfKeys.end(),
01439 std::back_inserter( senderKeys ) );
01440
01441 const KCursorSaver idle( KBusyPtr::idle() );
01442
01443 Kleo::KeyApprovalDialog dlg( items, senderKeys );
01444
01445 if ( dlg.exec() == QDialog::Rejected )
01446 return Kpgp::Canceled;
01447
01448 items = dlg.items();
01449 senderKeys = dlg.senderKeys();
01450
01451 if ( dlg.preferencesChanged() ) {
01452 for ( uint i = 0; i < items.size(); ++i ) {
01453 ContactPreferences pref = lookupContactPreferences( items[i].address );
01454 pref.encryptionPreference = items[i].pref;
01455 pref.pgpKeyFingerprints.clear();
01456 pref.smimeCertFingerprints.clear();
01457 const std::vector<GpgME::Key> & keys = items[i].keys;
01458 for ( std::vector<GpgME::Key>::const_iterator it = keys.begin(), end = keys.end() ; it != end ; ++it ) {
01459 if ( it->protocol() == GpgME::Context::OpenPGP ) {
01460 if ( const char * fpr = it->primaryFingerprint() )
01461 pref.pgpKeyFingerprints.push_back( fpr );
01462 } else if ( it->protocol() == GpgME::Context::CMS ) {
01463 if ( const char * fpr = it->primaryFingerprint() )
01464 pref.smimeCertFingerprints.push_back( fpr );
01465 }
01466 }
01467 saveContactPreference( items[i].address, pref );
01468 }
01469 }
01470
01471
01472
01473 if ( encryptToSelf() && senderKeys.empty() ) {
01474 const QString msg = i18n("You did not select an encryption key for yourself "
01475 "(encrypt to self). You will not be able to decrypt "
01476 "your own message if you encrypt it.");
01477 if ( KMessageBox::warningContinueCancel( 0, msg,
01478 i18n("Missing Key Warning"),
01479 i18n("&Encrypt") )
01480 == KMessageBox::Cancel )
01481 return Kpgp::Canceled;
01482 else
01483 mEncryptToSelf = false;
01484 }
01485
01486
01487 const unsigned int emptyListCount =
01488 std::count_if( items.begin(), items.end(), EmptyKeyList );
01489
01490
01491
01492 if ( items.size() == emptyListCount ) {
01493 const QString msg = ( d->mPrimaryEncryptionKeys.size() +
01494 d->mSecondaryEncryptionKeys.size() == 1 )
01495 ? i18n("You did not select an encryption key for the "
01496 "recipient of this message; therefore, the message "
01497 "will not be encrypted.")
01498 : i18n("You did not select an encryption key for any of the "
01499 "recipients of this message; therefore, the message "
01500 "will not be encrypted.");
01501 if ( KMessageBox::warningContinueCancel( 0, msg,
01502 i18n("Missing Key Warning"),
01503 i18n("Send &Unencrypted") )
01504 == KMessageBox::Cancel )
01505 return Kpgp::Canceled;
01506 } else if ( emptyListCount > 0 ) {
01507 const QString msg = ( emptyListCount == 1 )
01508 ? i18n("You did not select an encryption key for one of "
01509 "the recipients: this person will not be able to "
01510 "decrypt the message if you encrypt it.")
01511 : i18n("You did not select encryption keys for some of "
01512 "the recipients: these persons will not be able to "
01513 "decrypt the message if you encrypt it." );
01514 KCursorSaver idle( KBusyPtr::idle() );
01515 if ( KMessageBox::warningContinueCancel( 0, msg,
01516 i18n("Missing Key Warning"),
01517 i18n("&Encrypt") )
01518 == KMessageBox::Cancel )
01519 return Kpgp::Canceled;
01520 }
01521
01522 std::transform( d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(),
01523 items.begin(),
01524 d->mPrimaryEncryptionKeys.begin(),
01525 CopyKeysAndEncryptionPreferences );
01526 std::transform( d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(),
01527 items.begin() + d->mPrimaryEncryptionKeys.size(),
01528 d->mSecondaryEncryptionKeys.begin(),
01529 CopyKeysAndEncryptionPreferences );
01530
01531 d->mOpenPGPEncryptToSelfKeys.clear();
01532 d->mSMIMEEncryptToSelfKeys.clear();
01533
01534 std::remove_copy_if( senderKeys.begin(), senderKeys.end(),
01535 std::back_inserter( d->mOpenPGPEncryptToSelfKeys ),
01536 NotValidTrustedOpenPGPEncryptionKey );
01537 std::remove_copy_if( senderKeys.begin(), senderKeys.end(),
01538 std::back_inserter( d->mSMIMEEncryptToSelfKeys ),
01539 NotValidTrustedSMIMEEncryptionKey );
01540
01541 return Kpgp::Ok;
01542 }
01543
01544 std::vector<Kleo::KeyResolver::SplitInfo> Kleo::KeyResolver::encryptionItems( Kleo::CryptoMessageFormat f ) const {
01545 dump();
01546 std::map<CryptoMessageFormat,FormatInfo>::const_iterator it =
01547 d->mFormatInfoMap.find( f );
01548 return it != d->mFormatInfoMap.end() ? it->second.splitInfos : std::vector<SplitInfo>() ;
01549 }
01550
01551 std::vector<GpgME::Key> Kleo::KeyResolver::signingKeys( CryptoMessageFormat f ) const {
01552 dump();
01553 std::map<CryptoMessageFormat,FormatInfo>::const_iterator it =
01554 d->mFormatInfoMap.find( f );
01555 return it != d->mFormatInfoMap.end() ? it->second.signKeys : std::vector<GpgME::Key>() ;
01556 }
01557
01558
01559
01560
01561
01562
01563
01564
01565 std::vector<GpgME::Key> Kleo::KeyResolver::selectKeys( const QString & person, const QString & msg, const std::vector<GpgME::Key> & selectedKeys ) const {
01566 const bool opgp = containsOpenPGP( mCryptoMessageFormats );
01567 const bool x509 = containsSMIME( mCryptoMessageFormats );
01568
01569 Kleo::KeySelectionDialog dlg( i18n("Encryption Key Selection"),
01570 msg, selectedKeys,
01571 Kleo::KeySelectionDialog::ValidEncryptionKeys
01572 & ~(opgp ? 0 : Kleo::KeySelectionDialog::OpenPGPKeys)
01573 & ~(x509 ? 0 : Kleo::KeySelectionDialog::SMIMEKeys),
01574 true, true );
01575
01576 if ( dlg.exec() != QDialog::Accepted )
01577 return std::vector<GpgME::Key>();
01578 std::vector<GpgME::Key> keys = dlg.selectedKeys();
01579 keys.erase( std::remove_if( keys.begin(), keys.end(),
01580 NotValidTrustedEncryptionKey ),
01581 keys.end() );
01582 if ( !keys.empty() && dlg.rememberSelection() )
01583 setKeysForAddress( person, dlg.pgpKeyFingerprints(), dlg.smimeFingerprints() );
01584 return keys;
01585 }
01586
01587
01588 std::vector<GpgME::Key> Kleo::KeyResolver::getEncryptionKeys( const QString & person, bool quiet ) const {
01589
01590 const QString address = canonicalAddress( person ).lower();
01591
01592
01593 const QStringList fingerprints = keysForAddress( address );
01594
01595 if ( !fingerprints.empty() ) {
01596 kdDebug() << "Using encryption keys 0x"
01597 << fingerprints.join( ", 0x" )
01598 << " for " << person << endl;
01599 std::vector<GpgME::Key> keys = lookup( fingerprints );
01600 if ( !keys.empty() ) {
01601
01602 if ( std::find_if( keys.begin(), keys.end(),
01603 NotValidTrustedEncryptionKey ) != keys.end() ) {
01604
01605
01606
01607
01608 keys = selectKeys( person,
01609 i18n("if in your language something like "
01610 "'key(s)' isn't possible please "
01611 "use the plural in the translation",
01612 "There is a problem with the "
01613 "encryption key(s) for \"%1\".\n\n"
01614 "Please re-select the key(s) which should "
01615 "be used for this recipient.").arg(person),
01616 keys );
01617 }
01618 keys = TrustedOrConfirmed( keys, address );
01619
01620 if ( !keys.empty() )
01621 return keys;
01622
01623 }
01624 }
01625
01626
01627 std::vector<GpgME::Key> matchingKeys = lookup( person );
01628 matchingKeys.erase( std::remove_if( matchingKeys.begin(), matchingKeys.end(),
01629 NotValidEncryptionKey ),
01630 matchingKeys.end() );
01631
01632
01633 if ( matchingKeys.empty() ) {
01634 matchingKeys = lookup( address );
01635 matchingKeys.erase( std::remove_if( matchingKeys.begin(), matchingKeys.end(),
01636 NotValidEncryptionKey ),
01637 matchingKeys.end() );
01638 }
01639
01640
01641
01642
01643 if ( !quiet )
01644 matchingKeys = TrustedOrConfirmed( matchingKeys, address );
01645 if ( quiet || matchingKeys.size() == 1 )
01646 return matchingKeys;
01647
01648
01649
01650
01651 return TrustedOrConfirmed( selectKeys( person,
01652 matchingKeys.empty()
01653 ? i18n("if in your language something like "
01654 "'key(s)' isn't possible please "
01655 "use the plural in the translation",
01656 "<qt>No valid and trusted encryption key was "
01657 "found for \"%1\".<br/><br/>"
01658 "Select the key(s) which should "
01659 "be used for this recipient. If there is no suitable key in the list "
01660 "you can also <a href=\"%2\">search for external keys</a>.</qt>")
01661 .arg( QStyleSheet::escape(person), KURL::encode_string( KPIM::getEmailAddress(person) ) )
01662 : i18n("if in your language something like "
01663 "'key(s)' isn't possible please "
01664 "use the plural in the translation",
01665 "More than one key matches \"%1\".\n\n"
01666 "Select the key(s) which should "
01667 "be used for this recipient.").arg(person),
01668 matchingKeys ), address );
01669 }
01670
01671
01672 std::vector<GpgME::Key> Kleo::KeyResolver::lookup( const QStringList & patterns, bool secret ) const {
01673 if ( patterns.empty() )
01674 return std::vector<GpgME::Key>();
01675 kdDebug() << "Kleo::KeyResolver::lookup( \"" << patterns.join( "\", \"" )
01676 << "\", " << secret << " )" << endl;
01677 std::vector<GpgME::Key> result;
01678 if ( mCryptoMessageFormats & (InlineOpenPGPFormat|OpenPGPMIMEFormat) )
01679 if ( const Kleo::CryptoBackend::Protocol * p = Kleo::CryptoBackendFactory::instance()->openpgp() ) {
01680 std::auto_ptr<Kleo::KeyListJob> job( p->keyListJob( false, false, true ) );
01681 if ( job.get() ) {
01682 std::vector<GpgME::Key> keys;
01683 job->exec( patterns, secret, keys );
01684 result.insert( result.end(), keys.begin(), keys.end() );
01685 }
01686 }
01687 if ( mCryptoMessageFormats & (SMIMEFormat|SMIMEOpaqueFormat) )
01688 if ( const Kleo::CryptoBackend::Protocol * p = Kleo::CryptoBackendFactory::instance()->smime() ) {
01689 std::auto_ptr<Kleo::KeyListJob> job( p->keyListJob( false, false, true ) );
01690 if ( job.get() ) {
01691 std::vector<GpgME::Key> keys;
01692 job->exec( patterns, secret, keys );
01693 result.insert( result.end(), keys.begin(), keys.end() );
01694 }
01695 }
01696 kdDebug() << " returned " << result.size() << " keys" << endl;
01697 return result;
01698 }
01699
01700 void Kleo::KeyResolver::addKeys( const std::vector<Item> & items, CryptoMessageFormat f ) {
01701 dump();
01702 for ( std::vector<Item>::const_iterator it = items.begin() ; it != items.end() ; ++it ) {
01703 SplitInfo si( it->address );
01704 std::remove_copy_if( it->keys.begin(), it->keys.end(),
01705 std::back_inserter( si.keys ), IsNotForFormat( f ) );
01706 dump();
01707 kdWarning( si.keys.empty() )
01708 << "Kleo::KeyResolver::addKeys(): Fix EncryptionFormatPreferenceCounter. "
01709 << "It detected a common format, but the list of such keys for recipient \""
01710 << it->address << "\" is empty!" << endl;
01711 d->mFormatInfoMap[ f ].splitInfos.push_back( si );
01712 }
01713 dump();
01714 }
01715
01716 void Kleo::KeyResolver::addKeys( const std::vector<Item> & items ) {
01717 dump();
01718 for ( std::vector<Item>::const_iterator it = items.begin() ; it != items.end() ; ++it ) {
01719 SplitInfo si( it->address );
01720 CryptoMessageFormat f = AutoFormat;
01721 for ( unsigned int i = 0 ; i < numConcreteCryptoMessageFormats ; ++i ) {
01722 if ( concreteCryptoMessageFormats[i] & it->format ) {
01723 f = concreteCryptoMessageFormats[i];
01724 break;
01725 }
01726 }
01727 if ( f == AutoFormat )
01728 kdWarning() << "Kleo::KeyResolver::addKeys(): Something went wrong. Didn't find a format for \""
01729 << it->address << "\"" << endl;
01730 else
01731 std::remove_copy_if( it->keys.begin(), it->keys.end(),
01732 std::back_inserter( si.keys ), IsNotForFormat( f ) );
01733 d->mFormatInfoMap[ f ].splitInfos.push_back( si );
01734 }
01735 dump();
01736 }
01737
01738 Kleo::KeyResolver::ContactPreferences Kleo::KeyResolver::lookupContactPreferences( const QString& address ) const
01739 {
01740 const Private::ContactPreferencesMap::iterator it =
01741 d->mContactPreferencesMap.find( address );
01742 if ( it != d->mContactPreferencesMap.end() )
01743 return it->second;
01744
01745 KABC::AddressBook *ab = KABC::StdAddressBook::self( true );
01746 const KABC::Addressee::List res = ab->findByEmail( address );
01747 ContactPreferences pref;
01748 if ( !res.isEmpty() ) {
01749 KABC::Addressee addr = res.first();
01750 QString encryptPref = addr.custom( "KADDRESSBOOK", "CRYPTOENCRYPTPREF" );
01751 pref.encryptionPreference = Kleo::stringToEncryptionPreference( encryptPref );
01752 QString signPref = addr.custom( "KADDRESSBOOK", "CRYPTOSIGNPREF" );
01753 pref.signingPreference = Kleo::stringToSigningPreference( signPref );
01754 QString cryptoFormats = addr.custom( "KADDRESSBOOK", "CRYPTOPROTOPREF" );
01755 pref.cryptoMessageFormat = Kleo::stringToCryptoMessageFormat( cryptoFormats );
01756 pref.pgpKeyFingerprints = QStringList::split( ',', addr.custom( "KADDRESSBOOK", "OPENPGPFP" ) );
01757 pref.smimeCertFingerprints = QStringList::split( ',', addr.custom( "KADDRESSBOOK", "SMIMEFP" ) );
01758 }
01759
01760 d->mContactPreferencesMap.insert( std::make_pair( address, pref ) );
01761 return pref;
01762 }
01763
01764 void Kleo::KeyResolver::saveContactPreference( const QString& email, const ContactPreferences& pref ) const
01765 {
01766 d->mContactPreferencesMap.insert( std::make_pair( email, pref ) );
01767 KABC::AddressBook *ab = KABC::StdAddressBook::self( true );
01768 KABC::Addressee::List res = ab->findByEmail( email );
01769
01770 KABC::Addressee addr;
01771 if ( res.isEmpty() ) {
01772 bool ok = true;
01773 QString fullName = KInputDialog::getText( i18n( "Name Selection" ), i18n( "Which name shall the contact '%1' have in your addressbook?" ).arg( email ), QString::null, &ok );
01774 if ( ok ) {
01775 addr.setNameFromString( fullName );
01776 addr.insertEmail( email, true );
01777 } else
01778 return;
01779 } else
01780 addr = res.first();
01781
01782 addr.insertCustom( "KADDRESSBOOK", "CRYPTOENCRYPTPREF", Kleo::encryptionPreferenceToString( pref.encryptionPreference ) );
01783 addr.insertCustom( "KADDRESSBOOK", "CRYPTOSIGNPREF", Kleo::signingPreferenceToString( pref.signingPreference ) );
01784 addr.insertCustom( "KADDRESSBOOK", "CRYPTOPROTOPREF", cryptoMessageFormatToString( pref.cryptoMessageFormat ) );
01785 addr.insertCustom( "KADDRESSBOOK", "OPENPGPFP", pref.pgpKeyFingerprints.join( "," ) );
01786 addr.insertCustom( "KADDRESSBOOK", "SMIMEFP", pref.smimeCertFingerprints.join( "," ) );
01787
01788 ab->insertAddressee( addr );
01789 KABC::Ticket *ticket = ab->requestSaveTicket( addr.resource() );
01790 if ( ticket )
01791 ab->save( ticket );
01792
01793
01794 }
01795
01796 Kleo::KeyResolver::ContactPreferences::ContactPreferences()
01797 : encryptionPreference( UnknownPreference ),
01798 signingPreference( UnknownSigningPreference ),
01799 cryptoMessageFormat( AutoFormat )
01800 {
01801 }
01802
01803 QStringList Kleo::KeyResolver::keysForAddress( const QString & address ) const {
01804 if( address.isEmpty() ) {
01805 return QStringList();
01806 }
01807 QString addr = canonicalAddress( address ).lower();
01808 const ContactPreferences pref = lookupContactPreferences( addr );
01809 return pref.pgpKeyFingerprints + pref.smimeCertFingerprints;
01810 }
01811
01812 void Kleo::KeyResolver::setKeysForAddress( const QString& address, const QStringList& pgpKeyFingerprints, const QStringList& smimeCertFingerprints ) const {
01813 if( address.isEmpty() ) {
01814 return;
01815 }
01816 QString addr = canonicalAddress( address ).lower();
01817 ContactPreferences pref = lookupContactPreferences( addr );
01818 pref.pgpKeyFingerprints = pgpKeyFingerprints;
01819 pref.smimeCertFingerprints = smimeCertFingerprints;
01820 saveContactPreference( addr, pref );
01821 }