Search in sources :

Example 16 with OnIqPacketReceived

use of eu.siacs.conversations.xmpp.OnIqPacketReceived in project Conversations by siacs.

the class AxolotlService method buildSessionFromPEP.

private void buildSessionFromPEP(final AxolotlAddress address) {
    Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building new session for " + address.toString());
    if (address.equals(getOwnAxolotlAddress())) {
        throw new AssertionError("We should NEVER build a session with ourselves. What happened here?!");
    }
    try {
        IqPacket bundlesPacket = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice(Jid.fromString(address.getName()), address.getDeviceId());
        Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Retrieving bundle: " + bundlesPacket);
        mXmppConnectionService.sendIqPacket(account, bundlesPacket, new OnIqPacketReceived() {

            @Override
            public void onIqPacketReceived(Account account, IqPacket packet) {
                if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
                    fetchStatusMap.put(address, FetchStatus.TIMEOUT);
                } else if (packet.getType() == IqPacket.TYPE.RESULT) {
                    Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received preKey IQ packet, processing...");
                    final IqParser parser = mXmppConnectionService.getIqParser();
                    final List<PreKeyBundle> preKeyBundleList = parser.preKeys(packet);
                    final PreKeyBundle bundle = parser.bundle(packet);
                    if (preKeyBundleList.isEmpty() || bundle == null) {
                        Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "preKey IQ packet invalid: " + packet);
                        fetchStatusMap.put(address, FetchStatus.ERROR);
                        finishBuildingSessionsFromPEP(address);
                        return;
                    }
                    Random random = new Random();
                    final PreKeyBundle preKey = preKeyBundleList.get(random.nextInt(preKeyBundleList.size()));
                    if (preKey == null) {
                        //should never happen
                        fetchStatusMap.put(address, FetchStatus.ERROR);
                        finishBuildingSessionsFromPEP(address);
                        return;
                    }
                    final PreKeyBundle preKeyBundle = new PreKeyBundle(0, address.getDeviceId(), preKey.getPreKeyId(), preKey.getPreKey(), bundle.getSignedPreKeyId(), bundle.getSignedPreKey(), bundle.getSignedPreKeySignature(), bundle.getIdentityKey());
                    try {
                        SessionBuilder builder = new SessionBuilder(axolotlStore, address);
                        builder.process(preKeyBundle);
                        XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, bundle.getIdentityKey());
                        sessions.put(address, session);
                        if (Config.X509_VERIFICATION) {
                            verifySessionWithPEP(session);
                        } else {
                            FingerprintStatus status = getFingerprintTrust(bundle.getIdentityKey().getFingerprint().replaceAll("\\s", ""));
                            FetchStatus fetchStatus;
                            if (status != null && status.isVerified()) {
                                fetchStatus = FetchStatus.SUCCESS_VERIFIED;
                            } else if (status != null && status.isTrusted()) {
                                fetchStatus = FetchStatus.SUCCESS_TRUSTED;
                            } else {
                                fetchStatus = FetchStatus.SUCCESS;
                            }
                            fetchStatusMap.put(address, fetchStatus);
                            finishBuildingSessionsFromPEP(address);
                        }
                    } catch (UntrustedIdentityException | InvalidKeyException e) {
                        Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error building session for " + address + ": " + e.getClass().getName() + ", " + e.getMessage());
                        fetchStatusMap.put(address, FetchStatus.ERROR);
                        finishBuildingSessionsFromPEP(address);
                    }
                } else {
                    fetchStatusMap.put(address, FetchStatus.ERROR);
                    Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while building session:" + packet.findChild("error"));
                    finishBuildingSessionsFromPEP(address);
                }
            }
        });
    } catch (InvalidJidException e) {
        Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Got address with invalid jid: " + address.getName());
    }
}
Also used : Account(eu.siacs.conversations.entities.Account) IqParser(eu.siacs.conversations.parser.IqParser) UntrustedIdentityException(org.whispersystems.libaxolotl.UntrustedIdentityException) OnIqPacketReceived(eu.siacs.conversations.xmpp.OnIqPacketReceived) InvalidJidException(eu.siacs.conversations.xmpp.jid.InvalidJidException) SessionBuilder(org.whispersystems.libaxolotl.SessionBuilder) InvalidKeyException(org.whispersystems.libaxolotl.InvalidKeyException) IqPacket(eu.siacs.conversations.xmpp.stanzas.IqPacket) PreKeyBundle(org.whispersystems.libaxolotl.state.PreKeyBundle) Random(java.util.Random)

Example 17 with OnIqPacketReceived

use of eu.siacs.conversations.xmpp.OnIqPacketReceived in project Conversations by siacs.

the class AxolotlService method publishBundlesIfNeeded.

public void publishBundlesIfNeeded(final boolean announce, final boolean wipe) {
    if (pepBroken) {
        Log.d(Config.LOGTAG, getLogprefix(account) + "publishBundlesIfNeeded called, but PEP is broken. Ignoring... ");
        return;
    }
    IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice(account.getJid().toBareJid(), getOwnDeviceId());
    mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {

        @Override
        public void onIqPacketReceived(Account account, IqPacket packet) {
            if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
                //ignore timeout. do nothing
                return;
            }
            if (packet.getType() == IqPacket.TYPE.ERROR) {
                Element error = packet.findChild("error");
                if (error == null || !error.hasChild("item-not-found")) {
                    pepBroken = true;
                    Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "request for device bundles came back with something other than item-not-found" + packet);
                    return;
                }
            }
            PreKeyBundle bundle = mXmppConnectionService.getIqParser().bundle(packet);
            Map<Integer, ECPublicKey> keys = mXmppConnectionService.getIqParser().preKeyPublics(packet);
            boolean flush = false;
            if (bundle == null) {
                Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid bundle:" + packet);
                bundle = new PreKeyBundle(-1, -1, -1, null, -1, null, null, null);
                flush = true;
            }
            if (keys == null) {
                Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid prekeys:" + packet);
            }
            try {
                boolean changed = false;
                // Validate IdentityKey
                IdentityKeyPair identityKeyPair = axolotlStore.getIdentityKeyPair();
                if (flush || !identityKeyPair.getPublicKey().equals(bundle.getIdentityKey())) {
                    Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding own IdentityKey " + identityKeyPair.getPublicKey() + " to PEP.");
                    changed = true;
                }
                // Validate signedPreKeyRecord + ID
                SignedPreKeyRecord signedPreKeyRecord;
                int numSignedPreKeys = axolotlStore.loadSignedPreKeys().size();
                try {
                    signedPreKeyRecord = axolotlStore.loadSignedPreKey(bundle.getSignedPreKeyId());
                    if (flush || !bundle.getSignedPreKey().equals(signedPreKeyRecord.getKeyPair().getPublicKey()) || !Arrays.equals(bundle.getSignedPreKeySignature(), signedPreKeyRecord.getSignature())) {
                        Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding new signedPreKey with ID " + (numSignedPreKeys + 1) + " to PEP.");
                        signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1);
                        axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord);
                        changed = true;
                    }
                } catch (InvalidKeyIdException e) {
                    Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding new signedPreKey with ID " + (numSignedPreKeys + 1) + " to PEP.");
                    signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1);
                    axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord);
                    changed = true;
                }
                // Validate PreKeys
                Set<PreKeyRecord> preKeyRecords = new HashSet<>();
                if (keys != null) {
                    for (Integer id : keys.keySet()) {
                        try {
                            PreKeyRecord preKeyRecord = axolotlStore.loadPreKey(id);
                            if (preKeyRecord.getKeyPair().getPublicKey().equals(keys.get(id))) {
                                preKeyRecords.add(preKeyRecord);
                            }
                        } catch (InvalidKeyIdException ignored) {
                        }
                    }
                }
                int newKeys = NUM_KEYS_TO_PUBLISH - preKeyRecords.size();
                if (newKeys > 0) {
                    List<PreKeyRecord> newRecords = KeyHelper.generatePreKeys(axolotlStore.getCurrentPreKeyId() + 1, newKeys);
                    preKeyRecords.addAll(newRecords);
                    for (PreKeyRecord record : newRecords) {
                        axolotlStore.storePreKey(record.getId(), record);
                    }
                    changed = true;
                    Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding " + newKeys + " new preKeys to PEP.");
                }
                if (changed) {
                    if (account.getPrivateKeyAlias() != null && Config.X509_VERIFICATION) {
                        mXmppConnectionService.publishDisplayName(account);
                        publishDeviceVerificationAndBundle(signedPreKeyRecord, preKeyRecords, announce, wipe);
                    } else {
                        publishDeviceBundle(signedPreKeyRecord, preKeyRecords, announce, wipe);
                    }
                } else {
                    Log.d(Config.LOGTAG, getLogprefix(account) + "Bundle " + getOwnDeviceId() + " in PEP was current");
                    if (wipe) {
                        wipeOtherPepDevices();
                    } else if (announce) {
                        Log.d(Config.LOGTAG, getLogprefix(account) + "Announcing device " + getOwnDeviceId());
                        publishOwnDeviceIdIfNeeded();
                    }
                }
            } catch (InvalidKeyException e) {
                Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Failed to publish bundle " + getOwnDeviceId() + ", reason: " + e.getMessage());
            }
        }
    });
}
Also used : Account(eu.siacs.conversations.entities.Account) Set(java.util.Set) HashSet(java.util.HashSet) OnIqPacketReceived(eu.siacs.conversations.xmpp.OnIqPacketReceived) Element(eu.siacs.conversations.xml.Element) InvalidKeyException(org.whispersystems.libaxolotl.InvalidKeyException) IqPacket(eu.siacs.conversations.xmpp.stanzas.IqPacket) PreKeyBundle(org.whispersystems.libaxolotl.state.PreKeyBundle) SignedPreKeyRecord(org.whispersystems.libaxolotl.state.SignedPreKeyRecord) PreKeyRecord(org.whispersystems.libaxolotl.state.PreKeyRecord) InvalidKeyIdException(org.whispersystems.libaxolotl.InvalidKeyIdException) List(java.util.List) ArrayList(java.util.ArrayList) IdentityKeyPair(org.whispersystems.libaxolotl.IdentityKeyPair) Map(java.util.Map) HashMap(java.util.HashMap) SignedPreKeyRecord(org.whispersystems.libaxolotl.state.SignedPreKeyRecord)

Example 18 with OnIqPacketReceived

use of eu.siacs.conversations.xmpp.OnIqPacketReceived in project Conversations by siacs.

the class AxolotlService method publishOwnDeviceIdIfNeeded.

public void publishOwnDeviceIdIfNeeded() {
    if (pepBroken) {
        Log.d(Config.LOGTAG, getLogprefix(account) + "publishOwnDeviceIdIfNeeded called, but PEP is broken. Ignoring... ");
        return;
    }
    IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveDeviceIds(account.getJid().toBareJid());
    mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {

        @Override
        public void onIqPacketReceived(Account account, IqPacket packet) {
            if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
                Log.d(Config.LOGTAG, getLogprefix(account) + "Timeout received while retrieving own Device Ids.");
            } else {
                Element item = mXmppConnectionService.getIqParser().getItem(packet);
                Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item);
                Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": retrieved own device list: " + deviceIds);
                registerDevices(account.getJid().toBareJid(), deviceIds);
            }
        }
    });
}
Also used : Account(eu.siacs.conversations.entities.Account) Set(java.util.Set) HashSet(java.util.HashSet) OnIqPacketReceived(eu.siacs.conversations.xmpp.OnIqPacketReceived) Element(eu.siacs.conversations.xml.Element) IqPacket(eu.siacs.conversations.xmpp.stanzas.IqPacket)

Example 19 with OnIqPacketReceived

use of eu.siacs.conversations.xmpp.OnIqPacketReceived in project Conversations by siacs.

the class PushManagementService method enablePushOnServer.

private void enablePushOnServer(final Account account, final Jid jid, final String node, final String secret) {
    IqPacket enable = mXmppConnectionService.getIqGenerator().enablePush(jid, node, secret);
    mXmppConnectionService.sendIqPacket(account, enable, new OnIqPacketReceived() {

        @Override
        public void onIqPacketReceived(Account account, IqPacket packet) {
            if (packet.getType() == IqPacket.TYPE.RESULT) {
                Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": successfully enabled push on server");
            } else if (packet.getType() == IqPacket.TYPE.ERROR) {
                Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": enabling push on server failed");
            }
        }
    });
}
Also used : Account(eu.siacs.conversations.entities.Account) OnIqPacketReceived(eu.siacs.conversations.xmpp.OnIqPacketReceived) IqPacket(eu.siacs.conversations.xmpp.stanzas.IqPacket)

Example 20 with OnIqPacketReceived

use of eu.siacs.conversations.xmpp.OnIqPacketReceived in project Conversations by siacs.

the class PushManagementService method registerPushTokenOnServer.

public void registerPushTokenOnServer(final Account account) {
    Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": has push support");
    retrieveGcmInstanceToken(new OnGcmInstanceTokenRetrieved() {

        @Override
        public void onGcmInstanceTokenRetrieved(String token) {
            try {
                final String deviceId = Settings.Secure.getString(mXmppConnectionService.getContentResolver(), Settings.Secure.ANDROID_ID);
                IqPacket packet = mXmppConnectionService.getIqGenerator().pushTokenToAppServer(Jid.fromString(APP_SERVER), token, deviceId);
                mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {

                    @Override
                    public void onIqPacketReceived(Account account, IqPacket packet) {
                        Element command = packet.findChild("command", "http://jabber.org/protocol/commands");
                        if (packet.getType() == IqPacket.TYPE.RESULT && command != null) {
                            Element x = command.findChild("x", "jabber:x:data");
                            if (x != null) {
                                Data data = Data.parse(x);
                                try {
                                    String node = data.getValue("node");
                                    String secret = data.getValue("secret");
                                    Jid jid = Jid.fromString(data.getValue("jid"));
                                    if (node != null && secret != null) {
                                        enablePushOnServer(account, jid, node, secret);
                                    }
                                } catch (InvalidJidException e) {
                                    e.printStackTrace();
                                }
                            }
                        } else {
                            Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": invalid response from app server");
                        }
                    }
                });
            } catch (InvalidJidException ignored) {
            }
        }
    });
}
Also used : Account(eu.siacs.conversations.entities.Account) OnIqPacketReceived(eu.siacs.conversations.xmpp.OnIqPacketReceived) Jid(eu.siacs.conversations.xmpp.jid.Jid) Element(eu.siacs.conversations.xml.Element) InvalidJidException(eu.siacs.conversations.xmpp.jid.InvalidJidException) Data(eu.siacs.conversations.xmpp.forms.Data) IqPacket(eu.siacs.conversations.xmpp.stanzas.IqPacket)

Aggregations

Account (eu.siacs.conversations.entities.Account)33 OnIqPacketReceived (eu.siacs.conversations.xmpp.OnIqPacketReceived)33 IqPacket (eu.siacs.conversations.xmpp.stanzas.IqPacket)33 Element (eu.siacs.conversations.xml.Element)16 Jid (eu.siacs.conversations.xmpp.jid.Jid)9 InvalidJidException (eu.siacs.conversations.xmpp.jid.InvalidJidException)4 InvalidKeyException (org.whispersystems.libaxolotl.InvalidKeyException)4 PreKeyBundle (org.whispersystems.libaxolotl.state.PreKeyBundle)4 Conversation (eu.siacs.conversations.entities.Conversation)3 HashSet (java.util.HashSet)3 InvalidKeyIdException (org.whispersystems.libaxolotl.InvalidKeyIdException)3 UntrustedIdentityException (org.whispersystems.libaxolotl.UntrustedIdentityException)3 Bundle (android.os.Bundle)2 Pair (android.util.Pair)2 Contact (eu.siacs.conversations.entities.Contact)2 Data (eu.siacs.conversations.xmpp.forms.Data)2 Content (eu.siacs.conversations.xmpp.jingle.stanzas.Content)2 JinglePacket (eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket)2 Avatar (eu.siacs.conversations.xmpp.pep.Avatar)2 FileNotFoundException (java.io.FileNotFoundException)2