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