introduced code to verify omemo device keys with x509 certificates.
cleaned up TrustKeysActivity to automatically close if there is nothing to do
This commit is contained in:
parent
fb7359e6a3
commit
cfeb67d71d
|
@ -1,10 +1,10 @@
|
|||
package eu.siacs.conversations.crypto.axolotl;
|
||||
|
||||
import android.security.KeyChain;
|
||||
import android.security.KeyChainException;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.whispersystems.libaxolotl.AxolotlAddress;
|
||||
|
@ -20,11 +20,9 @@ import org.whispersystems.libaxolotl.state.PreKeyRecord;
|
|||
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
|
||||
import org.whispersystems.libaxolotl.util.KeyHelper;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Security;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
@ -43,12 +41,13 @@ import eu.siacs.conversations.parser.IqParser;
|
|||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
|
||||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
|
||||
public class AxolotlService {
|
||||
public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
||||
|
||||
public static final String PEP_PREFIX = "eu.siacs.conversations.axolotl";
|
||||
public static final String PEP_DEVICE_LIST = PEP_PREFIX + ".devicelist";
|
||||
|
@ -71,6 +70,15 @@ public class AxolotlService {
|
|||
private int numPublishTriesOnEmptyPep = 0;
|
||||
private boolean pepBroken = false;
|
||||
|
||||
@Override
|
||||
public void onAdvancedStreamFeaturesAvailable(Account account) {
|
||||
if (account.getXmppConnection().getFeatures().pep()) {
|
||||
publishBundlesIfNeeded(true, false);
|
||||
} else {
|
||||
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": skipping OMEMO initialization");
|
||||
}
|
||||
}
|
||||
|
||||
private static class AxolotlAddressMap<T> {
|
||||
protected Map<String, Map<Integer, T>> map;
|
||||
protected final Object MAP_LOCK = new Object();
|
||||
|
@ -402,7 +410,6 @@ public class AxolotlService {
|
|||
byte[] signature = verifier.sign();
|
||||
IqPacket packet = mXmppConnectionService.getIqGenerator().publishVerification(signature, chain, getOwnDeviceId());
|
||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + ": publish verification for device "+getOwnDeviceId());
|
||||
Log.d(Config.LOGTAG,"verification : "+packet.toString());
|
||||
mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
|
@ -565,6 +572,50 @@ public class AxolotlService {
|
|||
axolotlStore.setFingerprintTrust(fingerprint, trust);
|
||||
}
|
||||
|
||||
private void verifySessionWithPEP(final XmppAxolotlSession session, final IdentityKey identityKey) {
|
||||
final AxolotlAddress address = session.getRemoteAddress();
|
||||
try {
|
||||
IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveVerificationForDevice(Jid.fromString(address.getName()), address.getDeviceId());
|
||||
mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
Pair<X509Certificate[],byte[]> verification = mXmppConnectionService.getIqParser().verification(packet);
|
||||
if (verification != null) {
|
||||
try {
|
||||
Signature verifier = Signature.getInstance("sha256WithRSA");
|
||||
verifier.initVerify(verification.first[0]);
|
||||
verifier.update(identityKey.serialize());
|
||||
if (verifier.verify(verification.second)) {
|
||||
try {
|
||||
mXmppConnectionService.getMemorizingTrustManager().getNonInteractive().checkClientTrusted(verification.first, "RSA");
|
||||
Log.d(Config.LOGTAG, "verified session with x.509 signature");
|
||||
setFingerprintTrust(session.getFingerprint(), XmppAxolotlSession.Trust.TRUSTED);
|
||||
} catch (Exception e) {
|
||||
Log.d(Config.LOGTAG,"could not verify certificate");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d(Config.LOGTAG, "error during verification " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, " unable to parse verification");
|
||||
}
|
||||
finishBuildingSessionsFromPEP(address);
|
||||
}
|
||||
});
|
||||
} catch (InvalidJidException e) {
|
||||
finishBuildingSessionsFromPEP(address);
|
||||
}
|
||||
}
|
||||
|
||||
private void finishBuildingSessionsFromPEP(final AxolotlAddress address) {
|
||||
AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toString(), 0);
|
||||
if (!fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING)
|
||||
&& !fetchStatusMap.getAll(address).containsValue(FetchStatus.PENDING)) {
|
||||
mXmppConnectionService.keyStatusUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
private void buildSessionFromPEP(final AxolotlAddress address) {
|
||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building new sesstion for " + address.toString());
|
||||
if (address.getDeviceId() == getOwnDeviceId()) {
|
||||
|
@ -576,13 +627,6 @@ public class AxolotlService {
|
|||
Jid.fromString(address.getName()), address.getDeviceId());
|
||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Retrieving bundle: " + bundlesPacket);
|
||||
mXmppConnectionService.sendIqPacket(account, bundlesPacket, new OnIqPacketReceived() {
|
||||
private void finish() {
|
||||
AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toString(), 0);
|
||||
if (!fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING)
|
||||
&& !fetchStatusMap.getAll(address).containsValue(FetchStatus.PENDING)) {
|
||||
mXmppConnectionService.keyStatusUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
|
@ -594,7 +638,7 @@ public class AxolotlService {
|
|||
if (preKeyBundleList.isEmpty() || bundle == null) {
|
||||
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "preKey IQ packet invalid: " + packet);
|
||||
fetchStatusMap.put(address, FetchStatus.ERROR);
|
||||
finish();
|
||||
finishBuildingSessionsFromPEP(address);
|
||||
return;
|
||||
}
|
||||
Random random = new Random();
|
||||
|
@ -602,7 +646,7 @@ public class AxolotlService {
|
|||
if (preKey == null) {
|
||||
//should never happen
|
||||
fetchStatusMap.put(address, FetchStatus.ERROR);
|
||||
finish();
|
||||
finishBuildingSessionsFromPEP(address);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -617,17 +661,21 @@ public class AxolotlService {
|
|||
XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, bundle.getIdentityKey().getFingerprint().replaceAll("\\s", ""));
|
||||
sessions.put(address, session);
|
||||
fetchStatusMap.put(address, FetchStatus.SUCCESS);
|
||||
if (Config.X509_VERIFICATION) {
|
||||
verifySessionWithPEP(session, bundle.getIdentityKey());
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
finish();
|
||||
} else {
|
||||
fetchStatusMap.put(address, FetchStatus.ERROR);
|
||||
Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while building session:" + packet.findChild("error"));
|
||||
finish();
|
||||
finishBuildingSessionsFromPEP(address);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -699,9 +747,9 @@ public class AxolotlService {
|
|||
return newSessions;
|
||||
}
|
||||
|
||||
public boolean hasPendingKeyFetches(Conversation conversation) {
|
||||
public boolean hasPendingKeyFetches(Account account, Contact contact) {
|
||||
AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toString(), 0);
|
||||
AxolotlAddress foreignAddress = new AxolotlAddress(conversation.getJid().toBareJid().toString(), 0);
|
||||
AxolotlAddress foreignAddress = new AxolotlAddress(contact.getJid().toBareJid().toString(), 0);
|
||||
return fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING)
|
||||
|| fetchStatusMap.getAll(foreignAddress).containsValue(FetchStatus.PENDING);
|
||||
|
||||
|
|
|
@ -297,6 +297,9 @@ public class Account extends AbstractEntity {
|
|||
public void initAccountServices(final XmppConnectionService context) {
|
||||
this.mOtrService = new OtrService(context, this);
|
||||
this.axolotlService = new AxolotlService(this, context);
|
||||
if (xmppConnection != null) {
|
||||
xmppConnection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService);
|
||||
}
|
||||
}
|
||||
|
||||
public OtrService getOtrService() {
|
||||
|
|
|
@ -137,9 +137,13 @@ public class IqGenerator extends AbstractGenerator {
|
|||
|
||||
public IqPacket retrieveBundlesForDevice(final Jid to, final int deviceid) {
|
||||
final IqPacket packet = retrieve(AxolotlService.PEP_BUNDLES+":"+deviceid, null);
|
||||
if(to != null) {
|
||||
packet.setTo(to);
|
||||
}
|
||||
packet.setTo(to);
|
||||
return packet;
|
||||
}
|
||||
|
||||
public IqPacket retrieveVerificationForDevice(final Jid to, final int deviceid) {
|
||||
final IqPacket packet = retrieve(AxolotlService.PEP_VERIFICATION+":"+deviceid, null);
|
||||
packet.setTo(to);
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package eu.siacs.conversations.parser;
|
|||
import android.support.annotation.NonNull;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.whispersystems.libaxolotl.IdentityKey;
|
||||
import org.whispersystems.libaxolotl.InvalidKeyException;
|
||||
|
@ -10,6 +11,10 @@ import org.whispersystems.libaxolotl.ecc.Curve;
|
|||
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
|
||||
import org.whispersystems.libaxolotl.state.PreKeyBundle;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
@ -204,6 +209,30 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
|
|||
return preKeyRecords;
|
||||
}
|
||||
|
||||
public Pair<X509Certificate[],byte[]> verification(final IqPacket packet) {
|
||||
Element item = getItem(packet);
|
||||
Element verification = item != null ? item.findChild("verification",AxolotlService.PEP_PREFIX) : null;
|
||||
Element chain = verification != null ? verification.findChild("chain") : null;
|
||||
Element signature = verification != null ? verification.findChild("signature") : null;
|
||||
if (chain != null && signature != null) {
|
||||
List<Element> certElements = chain.getChildren();
|
||||
X509Certificate[] certificates = new X509Certificate[certElements.size()];
|
||||
try {
|
||||
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
||||
int i = 0;
|
||||
for(Element cert : certElements) {
|
||||
certificates[i] = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(Base64.decode(cert.getContent(),Base64.DEFAULT)));
|
||||
++i;
|
||||
}
|
||||
return new Pair<>(certificates,Base64.decode(signature.getContent(),Base64.DEFAULT));
|
||||
} catch (CertificateException e) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public PreKeyBundle bundle(final IqPacket bundle) {
|
||||
Element bundleItem = getItem(bundle);
|
||||
if(bundleItem == null) {
|
||||
|
|
|
@ -60,6 +60,7 @@ import de.duenndns.ssl.MemorizingTrustManager;
|
|||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.PgpEngine;
|
||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Blockable;
|
||||
|
@ -256,7 +257,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
|||
mMessageArchiveService.executePendingQueries(account);
|
||||
mJingleConnectionManager.cancelInTransmission();
|
||||
syncDirtyContacts(account);
|
||||
account.getAxolotlService().publishBundlesIfNeeded(true, false);
|
||||
}
|
||||
};
|
||||
private OnStatusChanged statusListener = new OnStatusChanged() {
|
||||
|
@ -459,7 +459,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
|||
final String action = intent == null ? null : intent.getAction();
|
||||
boolean interactive = false;
|
||||
if (action != null) {
|
||||
Log.d(Config.LOGTAG, "action: " + action);
|
||||
switch (action) {
|
||||
case ConnectivityManager.CONNECTIVITY_ACTION:
|
||||
if (hasInternetConnection() && Config.RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE) {
|
||||
|
@ -760,6 +759,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
|||
connection.setOnBindListener(this.mOnBindListener);
|
||||
connection.setOnMessageAcknowledgeListener(this.mOnMessageAcknowledgedListener);
|
||||
connection.addOnAdvancedStreamFeaturesAvailableListener(this.mMessageArchiveService);
|
||||
AxolotlService axolotlService = account.getAxolotlService();
|
||||
if (axolotlService != null) {
|
||||
connection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService);
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
|
@ -1066,8 +1069,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
|||
public void run() {
|
||||
Log.d(Config.LOGTAG, "restoring roster");
|
||||
for (Account account : accounts) {
|
||||
databaseBackend.readRoster(account.getRoster());
|
||||
account.initAccountServices(XmppConnectionService.this);
|
||||
databaseBackend.readRoster(account.getRoster());
|
||||
}
|
||||
getBitmapCache().evictAll();
|
||||
Looper.prepare();
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.widget.Button;
|
|||
import android.widget.CompoundButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.whispersystems.libaxolotl.IdentityKey;
|
||||
|
||||
|
@ -16,6 +17,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
|
@ -27,11 +29,11 @@ import eu.siacs.conversations.xmpp.jid.Jid;
|
|||
public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdated {
|
||||
private Jid accountJid;
|
||||
private Jid contactJid;
|
||||
private boolean hasOtherTrustedKeys = false;
|
||||
private boolean hasPendingFetches = false;
|
||||
|
||||
private boolean hasNoTrustedKeys = true;
|
||||
|
||||
private Contact contact;
|
||||
private Account mAccount;
|
||||
private TextView keyErrorMessage;
|
||||
private LinearLayout keyErrorMessageCard;
|
||||
private TextView ownKeysTitle;
|
||||
|
@ -50,10 +52,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
commitTrusts();
|
||||
Intent data = new Intent();
|
||||
data.putExtra("choice", getIntent().getIntExtra("choice", ConversationActivity.ATTACHMENT_CHOICE_INVALID));
|
||||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
finishOk();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -157,11 +156,11 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
|||
foreignKeysTitle.setText(contactJid.toString());
|
||||
foreignKeysCard.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if(hasPendingFetches) {
|
||||
if(hasPendingKeyFetches()) {
|
||||
setFetching();
|
||||
lock();
|
||||
} else {
|
||||
if (!hasForeignKeys && !hasOtherTrustedKeys) {
|
||||
if (!hasForeignKeys && hasNoOtherTrustedKeys()) {
|
||||
keyErrorMessageCard.setVisibility(View.VISIBLE);
|
||||
keyErrorMessage.setText(R.string.error_no_keys_to_trust);
|
||||
ownKeys.removeAllViews(); ownKeysCard.setVisibility(View.GONE);
|
||||
|
@ -172,12 +171,13 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
|||
}
|
||||
}
|
||||
|
||||
private void getFingerprints(final Account account) {
|
||||
Set<IdentityKey> ownKeysSet = account.getAxolotlService().getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED);
|
||||
Set<IdentityKey> foreignKeysSet = account.getAxolotlService().getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, contact);
|
||||
private boolean reloadFingerprints() {
|
||||
AxolotlService service = this.mAccount.getAxolotlService();
|
||||
Set<IdentityKey> ownKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED);
|
||||
Set<IdentityKey> foreignKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, contact);
|
||||
if (hasNoTrustedKeys) {
|
||||
ownKeysSet.addAll(account.getAxolotlService().getKeysWithTrust(XmppAxolotlSession.Trust.UNTRUSTED));
|
||||
foreignKeysSet.addAll(account.getAxolotlService().getKeysWithTrust(XmppAxolotlSession.Trust.UNTRUSTED, contact));
|
||||
ownKeysSet.addAll(service.getKeysWithTrust(XmppAxolotlSession.Trust.UNTRUSTED));
|
||||
foreignKeysSet.addAll(service.getKeysWithTrust(XmppAxolotlSession.Trust.UNTRUSTED, contact));
|
||||
}
|
||||
for(final IdentityKey identityKey : ownKeysSet) {
|
||||
if(!ownKeysToTrust.containsKey(identityKey)) {
|
||||
|
@ -189,39 +189,55 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
|||
foreignKeysToTrust.put(identityKey.getFingerprint().replaceAll("\\s", ""), false);
|
||||
}
|
||||
}
|
||||
return ownKeysSet.size() + foreignKeysSet.size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackendConnected() {
|
||||
if ((accountJid != null) && (contactJid != null)) {
|
||||
final Account account = xmppConnectionService
|
||||
.findAccountByJid(accountJid);
|
||||
if (account == null) {
|
||||
this.mAccount = xmppConnectionService.findAccountByJid(accountJid);
|
||||
if (this.mAccount == null) {
|
||||
return;
|
||||
}
|
||||
this.contact = account.getRoster().getContact(contactJid);
|
||||
this.contact = this.mAccount.getRoster().getContact(contactJid);
|
||||
ownKeysToTrust.clear();
|
||||
foreignKeysToTrust.clear();
|
||||
getFingerprints(account);
|
||||
|
||||
if(account.getAxolotlService().getNumTrustedKeys(contact) > 0) {
|
||||
hasOtherTrustedKeys = true;
|
||||
}
|
||||
Conversation conversation = xmppConnectionService.findOrCreateConversation(account, contactJid, false);
|
||||
if(account.getAxolotlService().hasPendingKeyFetches(conversation)) {
|
||||
hasPendingFetches = true;
|
||||
}
|
||||
|
||||
reloadFingerprints();
|
||||
populateView();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasNoOtherTrustedKeys() {
|
||||
return mAccount == null || mAccount.getAxolotlService().getNumTrustedKeys(contact) == 0;
|
||||
}
|
||||
|
||||
private boolean hasPendingKeyFetches() {
|
||||
return mAccount != null && contact != null && mAccount.getAxolotlService().hasPendingKeyFetches(mAccount,contact);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onKeyStatusUpdated() {
|
||||
final Account account = xmppConnectionService.findAccountByJid(accountJid);
|
||||
hasPendingFetches = false;
|
||||
getFingerprints(account);
|
||||
refreshUi();
|
||||
boolean keysToTrust = reloadFingerprints();
|
||||
if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) {
|
||||
refreshUi();
|
||||
} else {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(TrustKeysActivity.this, "Nothing to do", Toast.LENGTH_SHORT).show();
|
||||
finishOk();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void finishOk() {
|
||||
Intent data = new Intent();
|
||||
data.putExtra("choice", getIntent().getIntExtra("choice", ConversationActivity.ATTACHMENT_CHOICE_INVALID));
|
||||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void commitTrusts() {
|
||||
|
@ -248,7 +264,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
|||
}
|
||||
|
||||
private void lockOrUnlockAsNeeded() {
|
||||
if (!hasOtherTrustedKeys && !foreignKeysToTrust.values().contains(true)){
|
||||
if (hasNoOtherTrustedKeys() && !foreignKeysToTrust.values().contains(true)){
|
||||
lock();
|
||||
} else {
|
||||
unlock();
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
package eu.siacs.conversations.utils;
|
||||
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x500.style.BCStyle;
|
||||
import org.bouncycastle.asn1.x500.style.IETFUtils;
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
|
||||
import org.bouncycastle.jce.PrincipalUtil;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateParsingException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.X509Extension;
|
||||
import java.text.Normalizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
@ -137,11 +142,26 @@ public final class CryptoHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static Pair<Jid,String> extractJidAndName(X509Certificate certificate) throws CertificateEncodingException, InvalidJidException {
|
||||
public static Pair<Jid,String> extractJidAndName(X509Certificate certificate) throws CertificateEncodingException, InvalidJidException, CertificateParsingException {
|
||||
Collection<List<?>> alternativeNames = certificate.getSubjectAlternativeNames();
|
||||
List<String> emails = new ArrayList<>();
|
||||
if (alternativeNames != null) {
|
||||
for(List<?> san : alternativeNames) {
|
||||
Integer type = (Integer) san.get(0);
|
||||
if (type == 1) {
|
||||
emails.add((String) san.get(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
X500Name x500name = new JcaX509CertificateHolder(certificate).getSubject();
|
||||
//String xmpp = IETFUtils.valueToString(x500name.getRDNs(new ASN1ObjectIdentifier("1.3.6.1.5.5.7.8.5"))[0].getFirst().getValue());
|
||||
String email = IETFUtils.valueToString(x500name.getRDNs(BCStyle.EmailAddress)[0].getFirst().getValue());
|
||||
if (emails.size() == 0) {
|
||||
emails.add(IETFUtils.valueToString(x500name.getRDNs(BCStyle.EmailAddress)[0].getFirst().getValue()));
|
||||
}
|
||||
String name = IETFUtils.valueToString(x500name.getRDNs(BCStyle.CN)[0].getFirst().getValue());
|
||||
return new Pair<>(Jid.fromString(email),name);
|
||||
if (emails.size() >= 1) {
|
||||
return new Pair<>(Jid.fromString(emails.get(0)), name);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -947,11 +947,10 @@ public class XmppConnection implements Runnable {
|
|||
}
|
||||
}
|
||||
disco.put(jid, info);
|
||||
if (account.getServer().equals(jid)) {
|
||||
if ((jid.equals(account.getServer()) || jid.equals(account.getJid().toBareJid()))
|
||||
&& disco.containsKey(account.getServer())
|
||||
&& disco.containsKey(account.getJid().toBareJid())) {
|
||||
enableAdvancedStreamFeatures();
|
||||
for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) {
|
||||
listener.onAdvancedStreamFeaturesAvailable(account);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not query disco info for "+jid.toString());
|
||||
|
@ -969,6 +968,9 @@ public class XmppConnection implements Runnable {
|
|||
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": Requesting block list");
|
||||
this.sendIqPacket(getIqGenerator().generateGetBlockList(), mXmppConnectionService.getIqParser());
|
||||
}
|
||||
for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) {
|
||||
listener.onAdvancedStreamFeaturesAvailable(account);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendServiceDiscoveryItems(final Jid server) {
|
||||
|
|
Loading…
Reference in New Issue