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