Commit ff7dbb41 authored by Ingo Klöcker's avatar Ingo Klöcker
Browse files

Common overrides override protocol-specific resolution

If the common overrides for an address consist of OpenPGP and S/MIME keys,
then leave the protocol-specific resolutions of the address empty.
If, OTOH, the common overrides for an address contain only keys for
one protocol, then use those for the protocol-specific resolution.

GnuPG-bug-id: 5283
parent 7455e56a
......@@ -363,6 +363,24 @@ private Q_SLOTS:
QCOMPARE(resolver.encryptionKeys().value(UnknownProtocol).value("sender-smime@example.net")[0].primaryFingerprint(), override);
}
void test_mixed_protocol_common_overrides_override_protocol_specific_resolution()
{
const QString override1 = testKey("prefer-openpgp@example.net", OpenPGP).primaryFingerprint();
const QString override2 = testKey("prefer-smime@example.net", CMS).primaryFingerprint();
KeyResolverCore resolver(/*encrypt=*/ true, /*sign=*/ true);
resolver.setSender(QStringLiteral("sender-mixed@example.net"));
resolver.setOverrideKeys({{UnknownProtocol, {{QStringLiteral("sender-mixed@example.net"), {override1, override2}}}}});
const bool success = resolver.resolve();
QVERIFY(success);
QCOMPARE(resolver.encryptionKeys().value(OpenPGP).size(), 0);
QCOMPARE(resolver.encryptionKeys().value(CMS).size(), 0);
QCOMPARE(resolver.encryptionKeys().value(UnknownProtocol).value("sender-mixed@example.net").size(), 2);
QCOMPARE(resolver.encryptionKeys().value(UnknownProtocol).value("sender-mixed@example.net")[0].primaryFingerprint(), override1);
QCOMPARE(resolver.encryptionKeys().value(UnknownProtocol).value("sender-mixed@example.net")[1].primaryFingerprint(), override2);
}
private:
Key testKey(const char *email, Protocol protocol = UnknownProtocol)
{
......
......@@ -68,6 +68,11 @@ static int minimumValidity(const std::vector<Key> &keys, const QString &address)
return minValidity <= UserID::Ultimate ? static_cast<UserID::Validity>(minValidity) : UserID::Unknown;
}
bool allKeysHaveProtocol(const std::vector<Key> &keys, Protocol protocol)
{
return std::all_of(keys.cbegin(), keys.cend(), [protocol] (const Key &key) { return key.protocol() == protocol; });
}
} // namespace
class KeyResolverCore::Private
......@@ -244,6 +249,7 @@ void KeyResolverCore::Private::resolveOverrides()
// Skip overrides for the wrong format
continue;
}
std::vector<Key> keys;
for (const auto &fprOrId: fingerprints) {
const Key key = mCache->findByKeyIDOrFingerprint(fprOrId.toUtf8().constData());
if (key.isNull()) {
......@@ -256,16 +262,10 @@ void KeyResolverCore::Private::resolveOverrides()
<< address;
continue;
}
Protocol resolvedFmt = protocol;
if (protocol == UnknownProtocol) {
// Take the format from the key.
resolvedFmt = key.protocol();
}
mEncKeys[address][resolvedFmt].push_back(key);
qCDebug(LIBKLEO_LOG) << "Override" << address << Formatting::displayName(resolvedFmt) << fprOrId;
qCDebug(LIBKLEO_LOG) << "Using key" << Formatting::summaryLine(key) << "as" << Formatting::displayName(protocol) << "override for" << address;
keys.push_back(key);
}
mEncKeys[address][protocol] = keys;
}
}
}
......@@ -357,8 +357,20 @@ void KeyResolverCore::Private::resolveEnc(Protocol proto)
const QString &address = it.key();
auto &protocolKeysMap = it.value();
if (!protocolKeysMap[proto].empty()) {
// already resolved for current protocol (by override)
continue;
}
const std::vector<Key> &commonOverride = protocolKeysMap[UnknownProtocol];
if (!commonOverride.empty()) {
// there is a common override; use it for current protocol if possible
if (allKeysHaveProtocol(commonOverride, proto)) {
protocolKeysMap[proto] = commonOverride;
continue;
} else {
qCDebug(LIBKLEO_LOG) << "Common override for" << address << "is unusable for" << Formatting::displayName(proto);
continue;
}
}
protocolKeysMap[proto] = resolveRecipient(address, proto);
}
}
......@@ -439,15 +451,20 @@ bool KeyResolverCore::Private::resolve()
if (mAllowMixed && mFormat == UnknownProtocol) {
mergeEncryptionKeys();
}
const QStringList unresolvedMerged = unresolvedRecipients(UnknownProtocol);
// Check if we need the user to select different keys.
bool needsUser = false;
if (!pgpOnly && !cmsOnly) {
for (const auto &unresolved: unresolvedPGP) {
if (unresolvedCMS.contains(unresolved)) {
// We have at least one unresolvable key.
needsUser = true;
break;
if (mAllowMixed && mFormat == UnknownProtocol) {
needsUser = !unresolvedMerged.empty();
} else {
for (const auto &unresolved: unresolvedPGP) {
if (unresolvedCMS.contains(unresolved)) {
// We have at least one unresolvable key.
needsUser = true;
break;
}
}
}
if (mSign) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment