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