Add SNI, remove network operations from UI thread, and make certificate not required anymore

This commit is contained in:
Travis Burtrum 2015-07-25 01:36:52 -04:00
parent 5f53edb659
commit 3584bd8bf9
5 changed files with 44 additions and 47 deletions

View File

@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="hu.blint.ssldroid" android:versionCode="7"
android:versionName="1.2.4">
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="7" />
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17" />
<permission android:name="hu.blint.ssldroid.permission.startstop" android:protectionLevel="normal" android:label="Start and stop the SSLDroid service" />
<uses-permission android:name="hu.blint.ssldroid.permission.startstop" />
<uses-permission android:name="android.permission.INTERNET" />

View File

@ -138,8 +138,8 @@ public class SSLDroidGui extends ListActivity {
@SuppressWarnings("unused")
private void getProvisioning() {
Intent i = new Intent(this, SSLDroidProvisioning.class);
startActivity(i);
//Intent i = new Intent(this, SSLDroidProvisioning.class);
//startActivity(i);
}
// ListView and view (row) on which was clicked, position and

View File

@ -125,18 +125,6 @@ public class SSLDroidTunnelDetails extends Activity {
Toast.makeText(getBaseContext(), "Required remote host parameter not set up, skipping save", Toast.LENGTH_LONG).show();
return;
}
else {
//if we have interwebs access, the remote host should exist
ConnectivityManager conMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
if ( conMgr.getActiveNetworkInfo() != null || conMgr.getActiveNetworkInfo().isAvailable()) {
try {
InetAddress.getByName(remotehost.getText().toString());
} catch (UnknownHostException e) {
Toast.makeText(getBaseContext(), "Remote host not found, please recheck...", Toast.LENGTH_LONG).show();
}
}
}
//remote port validation
if (remoteport.getText().length() == 0) {
Toast.makeText(getBaseContext(), "Required remote port parameter not set up, skipping save", Toast.LENGTH_LONG).show();
@ -156,11 +144,7 @@ public class SSLDroidTunnelDetails extends Activity {
return;
}
}
if (pkcsfile.getText().length() == 0) {
Toast.makeText(getBaseContext(), "Required PKCS12 file parameter not set up, skipping save", Toast.LENGTH_LONG).show();
return;
}
else {
if (pkcsfile.getText().length() != 0) {
// try to open pkcs12 file with password
String cPkcsFile = pkcsfile.getText().toString();
String cPkcsPass = pkcspass.getText().toString();
@ -383,9 +367,6 @@ public class SSLDroidTunnelDetails extends Activity {
if (sRemoteport == 0) {
return;
}
if (sPkcsfile.length() == 0) {
return;
}
if (rowId == null || doClone) {
long id = dbHelper.createTunnel(sName, sLocalport, sRemotehost,

View File

@ -1,7 +1,6 @@
package hu.blint.ssldroid;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import android.util.Log;
@ -16,8 +15,7 @@ public class TcpProxy {
String tunnelHost;
int tunnelPort;
String keyFile, keyPass;
Thread server = null;
ServerSocket ss = null;
TcpProxyServerThread server = null;
public TcpProxy(String tunnelName, int listenPort, String targetHost, int targetPort, String keyFile, String keyPass) {
this.tunnelName = tunnelName;
@ -29,15 +27,7 @@ public class TcpProxy {
}
public void serve() throws IOException {
try {
ss = new ServerSocket(listenPort, 50, InetAddress.getLocalHost());
Log.d("SSLDroid", "Listening for connections on "+InetAddress.getLocalHost().getHostAddress()+":"+
+ this.listenPort + " ...");
} catch (Exception e) {
Log.d("SSLDroid", "Error setting up listening socket: " + e.toString());
return;
}
server = new TcpProxyServerThread(this.ss, this.tunnelName, this.listenPort, this.tunnelHost,
server = new TcpProxyServerThread(this.tunnelName, this.listenPort, this.tunnelHost,
this.tunnelPort, this.keyFile, this.keyPass);
server.start();
}
@ -46,7 +36,7 @@ public class TcpProxy {
if (server != null) {
try {
//close the server socket and interrupt the server thread
ss.close();
server.ss.close();
server.interrupt();
} catch (Exception e) {
Log.d("SSLDroid", "Interrupt failure: " + e.toString());
@ -57,7 +47,7 @@ public class TcpProxy {
//if the listening socket is still active, we're alive
public boolean isAlive() {
return ss.isBound();
return server.ss.isBound();
}
}

View File

@ -3,6 +3,7 @@ package hu.blint.ssldroid;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
@ -34,14 +35,13 @@ public class TcpProxyServerThread extends Thread {
int sessionid = 0;
private SSLSocketFactory sslSocketFactory;
public TcpProxyServerThread(ServerSocket ss,String tunnelName, int listenPort, String tunnelHost, int tunnelPort, String keyFile, String keyPass) {
public TcpProxyServerThread(String tunnelName, int listenPort, String tunnelHost, int tunnelPort, String keyFile, String keyPass) {
this.tunnelName = tunnelName;
this.listenPort = listenPort;
this.tunnelHost = tunnelHost;
this.tunnelPort = tunnelPort;
this.keyFile = keyFile;
this.keyPass = keyPass;
this.ss = ss;
}
// Create a trust manager that does not validate certificate chains
@ -65,15 +65,19 @@ public class TcpProxyServerThread extends Thread {
String pwd, int sessionid) {
if (sslSocketFactory == null) {
try {
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(pkcsFile), pwd.toCharArray());
keyManagerFactory.init(keyStore, pwd.toCharArray());
KeyManagerFactory keyManagerFactory;
if (pkcsFile != null && !pkcsFile.isEmpty()) {
keyManagerFactory = KeyManagerFactory.getInstance("X509");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(pkcsFile), pwd.toCharArray());
keyManagerFactory.init(keyStore, pwd.toCharArray());
} else {
keyManagerFactory = null;
}
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), trustAllCerts,
context.init(keyManagerFactory == null ? null : keyManagerFactory.getKeyManagers(), trustAllCerts,
new SecureRandom());
sslSocketFactory = (SSLSocketFactory) context.getSocketFactory();
sslSocketFactory = context.getSocketFactory();
} catch (FileNotFoundException e) {
Log.d("SSLDroid", tunnelName+"/"+sessionid+": Error loading the client certificate file:"
+ e.toString());
@ -95,6 +99,14 @@ public class TcpProxyServerThread extends Thread {
}
public void run() {
try {
ss = new ServerSocket(listenPort, 50, InetAddress.getLocalHost());
Log.d("SSLDroid", "Listening for connections on "+InetAddress.getLocalHost().getHostAddress()+":"+
+ this.listenPort + " ...");
} catch (Exception e) {
Log.d("SSLDroid", "Error setting up listening socket: " + e.toString());
return;
}
while (true) {
try {
Thread fromBrowserToServer = null;
@ -116,7 +128,9 @@ public class TcpProxyServerThread extends Thread {
Socket st = null;
try {
st = (SSLSocket) getSocketFactory(this.keyFile, this.keyPass, this.sessionid).createSocket(this.tunnelHost, this.tunnelPort);
final SSLSocketFactory sf = getSocketFactory(this.keyFile, this.keyPass, this.sessionid);
st = (SSLSocket) sf.createSocket(this.tunnelHost, this.tunnelPort);
setSNIHost(sf, (SSLSocket) st, this.tunnelHost);
((SSLSocket) st).startHandshake();
} catch (IOException e) {
Log.d("SSLDroid", tunnelName+"/"+sessionid+": SSL failure: " + e.toString());
@ -154,5 +168,17 @@ public class TcpProxyServerThread extends Thread {
}
}
}
private void setSNIHost(final SSLSocketFactory factory, final SSLSocket socket, final String hostname) {
if (factory instanceof android.net.SSLCertificateSocketFactory && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
((android.net.SSLCertificateSocketFactory)factory).setHostname(socket, hostname);
} else {
try {
socket.getClass().getMethod("setHostname", String.class).invoke(socket, hostname);
} catch (Throwable e) {
// ignore any error, we just can't set the hostname...
}
}
}
};