switched to mtm

This commit is contained in:
iNPUTmice 2014-07-22 17:27:44 +02:00
parent 9fcc195a6d
commit 4607e2c546
7 changed files with 33 additions and 142 deletions

3
.gitmodules vendored
View file

@ -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

View file

@ -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>

@ -0,0 +1 @@
Subproject commit 7610570fd89194af108b417b47951b8e97814245

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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;
} }