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