switched to mtm
This commit is contained in:
parent
9fcc195a6d
commit
4607e2c546
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -5,3 +5,6 @@
|
||||||
[submodule "libs/openpgp-api-lib"]
|
[submodule "libs/openpgp-api-lib"]
|
||||||
path = libs/openpgp-api-lib
|
path = libs/openpgp-api-lib
|
||||||
url = https://github.com/open-keychain/openpgp-api-lib.git
|
url = https://github.com/open-keychain/openpgp-api-lib.git
|
||||||
|
[submodule "libs/MemorizingTrustManager"]
|
||||||
|
path = libs/MemorizingTrustManager
|
||||||
|
url = https://github.com/ge0rg/MemorizingTrustManager
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
<data android:mimeType="image/*" />
|
<data android:mimeType="image/*" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity android:name="de.duenndns.ssl.MemorizingActivity" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
1
libs/MemorizingTrustManager
Submodule
1
libs/MemorizingTrustManager
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 7610570fd89194af108b417b47951b8e97814245
|
|
@ -14,3 +14,4 @@
|
||||||
target=android-19
|
target=android-19
|
||||||
android.library.reference.1=libs/minidns
|
android.library.reference.1=libs/minidns
|
||||||
android.library.reference.2=libs/openpgp-api-lib
|
android.library.reference.2=libs/openpgp-api-lib
|
||||||
|
android.library.reference.3=libs/MemorizingTrustManager
|
||||||
|
|
|
@ -15,6 +15,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import org.openintents.openpgp.util.OpenPgpApi;
|
import org.openintents.openpgp.util.OpenPgpApi;
|
||||||
import org.openintents.openpgp.util.OpenPgpServiceConnection;
|
import org.openintents.openpgp.util.OpenPgpServiceConnection;
|
||||||
|
|
||||||
|
import de.duenndns.ssl.MemorizingTrustManager;
|
||||||
|
|
||||||
import net.java.otr4j.OtrException;
|
import net.java.otr4j.OtrException;
|
||||||
import net.java.otr4j.session.Session;
|
import net.java.otr4j.session.Session;
|
||||||
import net.java.otr4j.session.SessionStatus;
|
import net.java.otr4j.session.SessionStatus;
|
||||||
|
@ -90,6 +92,8 @@ public class XmppConnectionService extends Service {
|
||||||
public static final long CARBON_GRACE_PERIOD = 60000L;
|
public static final long CARBON_GRACE_PERIOD = 60000L;
|
||||||
|
|
||||||
private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
|
private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
|
||||||
|
|
||||||
|
private MemorizingTrustManager mMemorizingTrustManager;
|
||||||
|
|
||||||
private MessageParser mMessageParser = new MessageParser(this);
|
private MessageParser mMessageParser = new MessageParser(this);
|
||||||
private PresenceParser mPresenceParser = new PresenceParser(this);
|
private PresenceParser mPresenceParser = new PresenceParser(this);
|
||||||
|
@ -106,7 +110,6 @@ public class XmppConnectionService extends Service {
|
||||||
private int convChangedListenerCount = 0;
|
private int convChangedListenerCount = 0;
|
||||||
private OnAccountUpdate mOnAccountUpdate = null;
|
private OnAccountUpdate mOnAccountUpdate = null;
|
||||||
private OnRosterUpdate mOnRosterUpdate = null;
|
private OnRosterUpdate mOnRosterUpdate = null;
|
||||||
private OnTLSExceptionReceived tlsException = null;
|
|
||||||
public OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() {
|
public OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -121,11 +124,6 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public void setOnTLSExceptionReceivedListener(
|
|
||||||
OnTLSExceptionReceived listener) {
|
|
||||||
tlsException = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SecureRandom mRandom;
|
private SecureRandom mRandom;
|
||||||
|
|
||||||
private ContentObserver contactObserver = new ContentObserver(null) {
|
private ContentObserver contactObserver = new ContentObserver(null) {
|
||||||
|
@ -368,6 +366,9 @@ public class XmppConnectionService extends Service {
|
||||||
ExceptionHelper.init(getApplicationContext());
|
ExceptionHelper.init(getApplicationContext());
|
||||||
PRNGFixes.apply();
|
PRNGFixes.apply();
|
||||||
this.mRandom = new SecureRandom();
|
this.mRandom = new SecureRandom();
|
||||||
|
this.mMemorizingTrustManager = new MemorizingTrustManager(getApplicationContext());
|
||||||
|
this.mMemorizingTrustManager.wrapHostnameVerifier(
|
||||||
|
new org.apache.http.conn.ssl.StrictHostnameVerifier());
|
||||||
this.databaseBackend = DatabaseBackend
|
this.databaseBackend = DatabaseBackend
|
||||||
.getInstance(getApplicationContext());
|
.getInstance(getApplicationContext());
|
||||||
this.fileBackend = new FileBackend(getApplicationContext());
|
this.fileBackend = new FileBackend(getApplicationContext());
|
||||||
|
@ -467,19 +468,6 @@ public class XmppConnectionService extends Service {
|
||||||
connection
|
connection
|
||||||
.setOnUnregisteredIqPacketReceivedListener(this.mIqParser);
|
.setOnUnregisteredIqPacketReceivedListener(this.mIqParser);
|
||||||
connection.setOnJinglePacketReceivedListener(this.jingleListener);
|
connection.setOnJinglePacketReceivedListener(this.jingleListener);
|
||||||
connection
|
|
||||||
.setOnTLSExceptionReceivedListener(new OnTLSExceptionReceived() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTLSExceptionReceived(String fingerprint,
|
|
||||||
Account account) {
|
|
||||||
Log.d(LOGTAG, "tls exception arrived in service");
|
|
||||||
if (tlsException != null) {
|
|
||||||
tlsException.onTLSExceptionReceived(fingerprint,
|
|
||||||
account);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connection.setOnBindListener(this.mOnBindListener);
|
connection.setOnBindListener(this.mOnBindListener);
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
@ -1214,10 +1202,6 @@ public class XmppConnectionService extends Service {
|
||||||
this.databaseBackend.updateConversation(conversation);
|
this.databaseBackend.updateConversation(conversation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeOnTLSExceptionReceivedListener() {
|
|
||||||
this.tlsException = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reconnectAccount(final Account account, final boolean force) {
|
public void reconnectAccount(final Account account, final boolean force) {
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
|
|
||||||
|
@ -1338,6 +1322,10 @@ public class XmppConnectionService extends Service {
|
||||||
public SecureRandom getRNG() {
|
public SecureRandom getRNG() {
|
||||||
return this.mRandom;
|
return this.mRandom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MemorizingTrustManager getMemorizingTrustManager() {
|
||||||
|
return this.mMemorizingTrustManager;
|
||||||
|
}
|
||||||
|
|
||||||
public PowerManager getPowerManager() {
|
public PowerManager getPowerManager() {
|
||||||
return this.pm;
|
return this.pm;
|
||||||
|
|
|
@ -59,57 +59,6 @@ public class ManageAccountActivity extends XmppActivity {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected OnTLSExceptionReceived tlsExceptionReceived = new OnTLSExceptionReceived() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTLSExceptionReceived(final String fingerprint,
|
|
||||||
final Account account) {
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(
|
|
||||||
activity);
|
|
||||||
builder.setTitle(getString(R.string.account_status_error));
|
|
||||||
builder.setIconAttribute(android.R.attr.alertDialogIcon);
|
|
||||||
View view = (View) getLayoutInflater().inflate(
|
|
||||||
R.layout.cert_warning, null);
|
|
||||||
TextView sha = (TextView) view.findViewById(R.id.sha);
|
|
||||||
TextView hint = (TextView) view.findViewById(R.id.hint);
|
|
||||||
StringBuilder humanReadableSha = new StringBuilder();
|
|
||||||
humanReadableSha.append(fingerprint);
|
|
||||||
for (int i = 2; i < 59; i += 3) {
|
|
||||||
if ((i == 14) || (i == 29) || (i == 44)) {
|
|
||||||
humanReadableSha.insert(i, "\n");
|
|
||||||
} else {
|
|
||||||
humanReadableSha.insert(i, ":");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
hint.setText(getString(R.string.untrusted_cert_hint,
|
|
||||||
account.getServer()));
|
|
||||||
sha.setText(humanReadableSha.toString());
|
|
||||||
builder.setView(view);
|
|
||||||
builder.setNegativeButton(
|
|
||||||
getString(R.string.certif_no_trust), null);
|
|
||||||
builder.setPositiveButton(getString(R.string.certif_trust),
|
|
||||||
new OnClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog,
|
|
||||||
int which) {
|
|
||||||
account.setSSLCertFingerprint(fingerprint);
|
|
||||||
activity.xmppConnectionService
|
|
||||||
.updateAccount(account);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.create().show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
@ -471,7 +420,6 @@ public class ManageAccountActivity extends XmppActivity {
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
if (xmppConnectionServiceBound) {
|
if (xmppConnectionServiceBound) {
|
||||||
xmppConnectionService.removeOnAccountListChangedListener();
|
xmppConnectionService.removeOnAccountListChangedListener();
|
||||||
xmppConnectionService.removeOnTLSExceptionReceivedListener();
|
|
||||||
}
|
}
|
||||||
super.onStop();
|
super.onStop();
|
||||||
}
|
}
|
||||||
|
@ -479,8 +427,6 @@ public class ManageAccountActivity extends XmppActivity {
|
||||||
@Override
|
@Override
|
||||||
void onBackendConnected() {
|
void onBackendConnected() {
|
||||||
xmppConnectionService.setOnAccountListChangedListener(accountChanged);
|
xmppConnectionService.setOnAccountListChangedListener(accountChanged);
|
||||||
xmppConnectionService
|
|
||||||
.setOnTLSExceptionReceivedListener(tlsExceptionReceived);
|
|
||||||
this.accountList.clear();
|
this.accountList.clear();
|
||||||
this.accountList.addAll(xmppConnectionService.getAccounts());
|
this.accountList.addAll(xmppConnectionService.getAccounts());
|
||||||
accountListViewAdapter.notifyDataSetChanged();
|
accountListViewAdapter.notifyDataSetChanged();
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.SSLSocket;
|
import javax.net.ssl.SSLSocket;
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
@ -28,8 +29,12 @@ import javax.net.ssl.TrustManager;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import org.bouncycastle.pqc.math.linearalgebra.GoppaCode.MaMaPe;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
import de.duenndns.ssl.MemorizingTrustManager;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.PowerManager.WakeLock;
|
import android.os.PowerManager.WakeLock;
|
||||||
|
@ -97,11 +102,12 @@ public class XmppConnection implements Runnable {
|
||||||
private OnIqPacketReceived unregisteredIqListener = null;
|
private OnIqPacketReceived unregisteredIqListener = null;
|
||||||
private OnMessagePacketReceived messageListener = null;
|
private OnMessagePacketReceived messageListener = null;
|
||||||
private OnStatusChanged statusListener = null;
|
private OnStatusChanged statusListener = null;
|
||||||
private OnTLSExceptionReceived tlsListener = null;
|
|
||||||
private OnBindListener bindListener = null;
|
private OnBindListener bindListener = null;
|
||||||
|
private MemorizingTrustManager mMemorizingTrustManager;
|
||||||
|
|
||||||
public XmppConnection(Account account, XmppConnectionService service) {
|
public XmppConnection(Account account, XmppConnectionService service) {
|
||||||
this.mRandom = service.getRNG();
|
this.mRandom = service.getRNG();
|
||||||
|
this.mMemorizingTrustManager = service.getMemorizingTrustManager();
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.wakeLock = service.getPowerManager().newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
|
this.wakeLock = service.getPowerManager().newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
|
||||||
account.getJid());
|
account.getJid());
|
||||||
|
@ -440,67 +446,19 @@ public class XmppConnection implements Runnable {
|
||||||
tagReader.readTag();
|
tagReader.readTag();
|
||||||
try {
|
try {
|
||||||
SSLContext sc = SSLContext.getInstance("TLS");
|
SSLContext sc = SSLContext.getInstance("TLS");
|
||||||
TrustManagerFactory tmf = TrustManagerFactory
|
sc.init(null, new X509TrustManager[] { this.mMemorizingTrustManager }, mRandom);
|
||||||
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
|
||||||
try {
|
|
||||||
tmf.init((KeyStore) null);
|
|
||||||
} catch (KeyStoreException e1) {
|
|
||||||
e1.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
TrustManager[] trustManagers = tmf.getTrustManagers();
|
|
||||||
final X509TrustManager origTrustmanager = (X509TrustManager) trustManagers[0];
|
|
||||||
|
|
||||||
TrustManager[] wrappedTrustManagers = new TrustManager[] { new X509TrustManager() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkClientTrusted(X509Certificate[] chain,
|
|
||||||
String authType) throws CertificateException {
|
|
||||||
origTrustmanager.checkClientTrusted(chain, authType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkServerTrusted(X509Certificate[] chain,
|
|
||||||
String authType) throws CertificateException {
|
|
||||||
try {
|
|
||||||
origTrustmanager.checkServerTrusted(chain, authType);
|
|
||||||
} catch (CertificateException e) {
|
|
||||||
if (e.getCause() instanceof CertPathValidatorException) {
|
|
||||||
String sha;
|
|
||||||
try {
|
|
||||||
MessageDigest sha1 = MessageDigest
|
|
||||||
.getInstance("SHA1");
|
|
||||||
sha1.update(chain[0].getEncoded());
|
|
||||||
sha = CryptoHelper.bytesToHex(sha1.digest());
|
|
||||||
if (!sha.equals(account.getSSLFingerprint())) {
|
|
||||||
changeStatus(Account.STATUS_TLS_ERROR);
|
|
||||||
if (tlsListener != null) {
|
|
||||||
tlsListener.onTLSExceptionReceived(sha,
|
|
||||||
account);
|
|
||||||
}
|
|
||||||
throw new CertificateException();
|
|
||||||
}
|
|
||||||
} catch (NoSuchAlgorithmException e1) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e1.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new CertificateException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public X509Certificate[] getAcceptedIssuers() {
|
|
||||||
return origTrustmanager.getAcceptedIssuers();
|
|
||||||
}
|
|
||||||
|
|
||||||
} };
|
|
||||||
sc.init(null, wrappedTrustManagers, null);
|
|
||||||
SSLSocketFactory factory = sc.getSocketFactory();
|
SSLSocketFactory factory = sc.getSocketFactory();
|
||||||
|
|
||||||
|
HostnameVerifier verifier = this.mMemorizingTrustManager.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier());
|
||||||
SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket,
|
SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket,
|
||||||
socket.getInetAddress().getHostAddress(), socket.getPort(),
|
socket.getInetAddress().getHostAddress(), socket.getPort(),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
|
if (verifier != null && !verifier.verify(account.getServer(), sslSocket.getSession())) {
|
||||||
|
Log.d(LOGTAG, account.getJid() + ": host mismatch in TLS connection");
|
||||||
|
sslSocket.close();
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
tagReader.setInputStream(sslSocket.getInputStream());
|
tagReader.setInputStream(sslSocket.getInputStream());
|
||||||
tagWriter.setOutputStream(sslSocket.getOutputStream());
|
tagWriter.setOutputStream(sslSocket.getOutputStream());
|
||||||
sendStartStream();
|
sendStartStream();
|
||||||
|
@ -508,10 +466,8 @@ public class XmppConnection implements Runnable {
|
||||||
processStream(tagReader.readTag());
|
processStream(tagReader.readTag());
|
||||||
sslSocket.close();
|
sslSocket.close();
|
||||||
} catch (NoSuchAlgorithmException e1) {
|
} catch (NoSuchAlgorithmException e1) {
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
} catch (KeyManagementException e) {
|
} catch (KeyManagementException e) {
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -844,11 +800,6 @@ public class XmppConnection implements Runnable {
|
||||||
this.statusListener = listener;
|
this.statusListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnTLSExceptionReceivedListener(
|
|
||||||
OnTLSExceptionReceived listener) {
|
|
||||||
this.tlsListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOnBindListener(OnBindListener listener) {
|
public void setOnBindListener(OnBindListener listener) {
|
||||||
this.bindListener = listener;
|
this.bindListener = listener;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue