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