From 6c9e41c1b2b0cd9c9ed5630feb7da6b926d9b5fd Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 3 Jul 2018 11:29:51 +0200 Subject: [PATCH] Update OpenPgp fingerprints of contacts --- .../smackx/ox/OpenPgpManager.java | 41 +++++++++++-------- .../smackx/ox/chat/OpenPgpContact.java | 16 ++++++-- .../internal/FingerprintsChangedListener.java | 26 ++++++++++++ 3 files changed, 62 insertions(+), 21 deletions(-) create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/listener/internal/FingerprintsChangedListener.java diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java index 6018fe590..4daf9f3c4 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java @@ -26,6 +26,7 @@ import java.io.InputStream; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -140,15 +141,6 @@ public final class OpenPgpManager extends Manager { this.provider = provider; } - /** - * Return the registered {@link OpenPgpProvider}. - * - * @return provider. - */ - OpenPgpProvider getOpenPgpProvider() { - return provider; - } - /** * Generate a fresh OpenPGP key pair, given we don't have one already. * Publish the public key to the Public Key Node and update the Public Key Metadata Node with our keys fingerprint. @@ -231,12 +223,9 @@ public final class OpenPgpManager extends Manager { * @throws SmackOpenPgpException if something happens while gathering fingerprints. * @throws InterruptedException * @throws XMPPException.XMPPErrorException - * @throws SmackException.NotConnectedException - * @throws SmackException.NoResponseException */ public OpenPgpContact getOpenPgpContact(EntityBareJid jid) throws SmackOpenPgpException, InterruptedException, XMPPException.XMPPErrorException, - SmackException.NotConnectedException, SmackException.NoResponseException, SmackException.NotLoggedInException { throwIfNotAuthenticated(); @@ -245,7 +234,7 @@ public final class OpenPgpManager extends Manager { if (openPgpContact == null) { OpenPgpFingerprints theirKeys = determineContactsKeys(jid); OpenPgpFingerprints ourKeys = determineContactsKeys(connection().getUser().asBareJid()); - openPgpContact = new OpenPgpContact(getOpenPgpProvider(), jid, ourKeys, theirKeys); + openPgpContact = new OpenPgpContact(provider, jid, ourKeys, theirKeys); openPgpCapableContacts.put(jid, openPgpContact); } @@ -434,20 +423,37 @@ public final class OpenPgpManager extends Manager { provider.getStore().setAnnouncedKeysFingerprints(contact, announcedKeys); - Set missingKeys = listElement.getMetadata().keySet(); + Set availableKeys = Collections.emptySet(); try { - missingKeys.removeAll(provider.getStore().getAvailableKeysFingerprints(contact).keySet()); + availableKeys = new HashSet<>(provider.getStore().getAvailableKeysFingerprints(contact).keySet()); + } catch (SmackOpenPgpException e) { + LOGGER.log(Level.WARNING, "Could not determine available keys", e); + } + + Set missingKeys = listElement.getMetadata().keySet(); + Map unfetchable = new HashMap<>(); + try { + missingKeys.removeAll(availableKeys); for (OpenPgpV4Fingerprint missing : missingKeys) { try { PubkeyElement pubkeyElement = fetchPubkey(connection(), contact, missing); - processPublicKey(pubkeyElement, contact); + if (pubkeyElement != null) { + processPublicKey(pubkeyElement, contact); + availableKeys.add(missing); + } } catch (Exception e) { LOGGER.log(Level.WARNING, "Error fetching missing OpenPGP key " + missing.toString(), e); + unfetchable.put(missing, e); } } } catch (Exception e) { LOGGER.log(Level.WARNING, "Error processing OpenPGP metadata update from " + contact + ".", e); } + + OpenPgpFingerprints fingerprints = new OpenPgpFingerprints(contact, announcedKeys.keySet(), availableKeys, unfetchable); + for (OpenPgpContact openPgpContact : openPgpCapableContacts.values()) { + openPgpContact.onFingerprintsChanged(contact, fingerprints); + } } private final IncomingChatMessageListener incomingOpenPgpMessageListener = @@ -464,8 +470,7 @@ public final class OpenPgpManager extends Manager { try { contact = getOpenPgpContact(from); } catch (SmackOpenPgpException | InterruptedException | XMPPException.XMPPErrorException | - SmackException.NotLoggedInException | SmackException.NotConnectedException | - SmackException.NoResponseException e) { + SmackException.NotLoggedInException e) { LOGGER.log(Level.WARNING, "Could not begin encrypted chat with " + from, e); return; } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/chat/OpenPgpContact.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/chat/OpenPgpContact.java index 8cb135cb5..3fff9b4e0 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/chat/OpenPgpContact.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/chat/OpenPgpContact.java @@ -37,17 +37,18 @@ import org.jivesoftware.smackx.ox.element.SigncryptElement; import org.jivesoftware.smackx.ox.exception.MissingOpenPgpKeyPairException; import org.jivesoftware.smackx.ox.exception.MissingOpenPgpPublicKeyException; import org.jivesoftware.smackx.ox.exception.SmackOpenPgpException; +import org.jivesoftware.smackx.ox.listener.internal.FingerprintsChangedListener; import org.jivesoftware.smackx.ox.util.DecryptedBytesAndMetadata; import org.jxmpp.jid.BareJid; import org.jxmpp.jid.Jid; import org.xmlpull.v1.XmlPullParserException; -public class OpenPgpContact { +public class OpenPgpContact implements FingerprintsChangedListener { private final BareJid jid; - private final OpenPgpFingerprints contactsFingerprints; - private final OpenPgpFingerprints ourFingerprints; + private OpenPgpFingerprints contactsFingerprints; + private OpenPgpFingerprints ourFingerprints; private final OpenPgpProvider cryptoProvider; private final OpenPgpV4Fingerprint singingKey; @@ -167,4 +168,13 @@ public class OpenPgpContact { return fingerprints; } + + @Override + public void onFingerprintsChanged(BareJid contact, OpenPgpFingerprints newFingerprints) { + if (ourFingerprints.getJid().equals(contact)) { + this.ourFingerprints = newFingerprints; + } else if (contactsFingerprints.getJid().equals(contact)) { + this.contactsFingerprints = newFingerprints; + } + } } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/listener/internal/FingerprintsChangedListener.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/listener/internal/FingerprintsChangedListener.java new file mode 100644 index 000000000..2974f3878 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/listener/internal/FingerprintsChangedListener.java @@ -0,0 +1,26 @@ +/** + * + * Copyright 2018 Paul Schaub. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smackx.ox.listener.internal; + +import org.jivesoftware.smackx.ox.chat.OpenPgpFingerprints; + +import org.jxmpp.jid.BareJid; + +public interface FingerprintsChangedListener { + + void onFingerprintsChanged(BareJid contact, OpenPgpFingerprints newFingerprints); +}