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