diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d02df83..88ba21f 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2,29 +2,27 @@ - - - + - + + + + + + + + + + + - - - - - - - - - \ No newline at end of file diff --git a/bin/SSLDroid.apk b/bin/SSLDroid.apk index 5b66f79..7432a98 100644 Binary files a/bin/SSLDroid.apk and b/bin/SSLDroid.apk differ diff --git a/bin/classes.dex b/bin/classes.dex index 78f586a..f54c7c0 100644 Binary files a/bin/classes.dex and b/bin/classes.dex differ diff --git a/bin/resources.ap_ b/bin/resources.ap_ index 871f008..40337c3 100644 Binary files a/bin/resources.ap_ and b/bin/resources.ap_ differ diff --git a/src/hu/blint/ssldroid/BootStartupReceiver.java b/src/hu/blint/ssldroid/BootStartupReceiver.java index 69387d2..421947c 100644 --- a/src/hu/blint/ssldroid/BootStartupReceiver.java +++ b/src/hu/blint/ssldroid/BootStartupReceiver.java @@ -4,11 +4,13 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -public class BootStartupReceiver extends BroadcastReceiver{ -@Override -public void onReceive(Context context, Intent intent) { - Intent serviceIntent = new Intent(); - serviceIntent.setAction("hu.blint.ssldroid.SSLDroid"); - context.startService(serviceIntent); -} +public class BootStartupReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { + Intent i = new Intent(); + i.setAction("hu.blint.ssldroid.SSLDroid"); + context.startService(i); + } + } } \ No newline at end of file diff --git a/src/hu/blint/ssldroid/SSLDroid.java b/src/hu/blint/ssldroid/SSLDroid.java index ccc9346..b83cd2c 100644 --- a/src/hu/blint/ssldroid/SSLDroid.java +++ b/src/hu/blint/ssldroid/SSLDroid.java @@ -2,12 +2,9 @@ package hu.blint.ssldroid; import hu.blint.ssldroid.TcpProxy; import android.app.*; -import android.content.BroadcastReceiver; -import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.util.Log; -import android.widget.Toast; public class SSLDroid extends Service { @@ -16,30 +13,30 @@ public class SSLDroid extends Service { @Override public void onCreate() { - // Toast.makeText(this, "SSLDroid Service Started", - // Toast.LENGTH_LONG).show(); - // Log.d(TAG, "onStart"); - } - - @Override - public void onStart(Intent intent, int startid) { - int listenPort = 9999; // port to listen on int targetPort = 443; // port to connect to String targetHost = "sogo.balabit.com"; // remote host String keyFile = "/mnt/sdcard/blint-imaps.p12"; String keyPass = "titkos"; - Toast.makeText(this, "SSLDroid Service Started", Toast.LENGTH_LONG).show(); - Log.d(TAG, "onCreate"); + //Toast.makeText(this, "SSLDroid Service Started", Toast.LENGTH_LONG).show(); + createNotification("SSLDroid is running", "SSLDroid service is running"); + Log.d(TAG, "SSLDroid Service Started"); + + //createNotification("test", "This is a test of the emergency broadcast system"); tp = new TcpProxy(); try { tp.serve(listenPort, targetHost, targetPort, keyFile, keyPass); } catch (Exception e) { - Log.d(TAG, "SSLDroid Sulyos Errorhiba" + e.getMessage()); + Log.d(TAG, "Error" + e.toString()); } } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return START_STICKY; + } @Override public IBinder onBind(Intent intent) { @@ -50,10 +47,26 @@ public class SSLDroid extends Service { public void onDestroy() { try { tp.stop(); + NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + notificationManager.cancel(0); + Log.d(TAG, "SSLDroid Service Stopped"); } catch (Exception e) { - Log.d("SSLDroid", "Error stopping service: " + e.getMessage()); + Log.d("SSLDroid", "Error stopping service: " + e.toString()); } } + + public void createNotification(String title, String text) { + NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + Notification notification = new Notification(R.drawable.icon, + "SSLDroid startup", System.currentTimeMillis()); + // Hide the notification after its selected + //notification.flags |= Notification.FLAG_AUTO_CANCEL; + + Intent intent = new Intent(this, SSLDroidGui.class); + PendingIntent activity = PendingIntent.getActivity(this, 0, intent, 0); + notification.setLatestEventInfo(this, title, text, activity); + notificationManager.notify(0, notification); + } } /* @@ -66,4 +79,4 @@ public class MyStartupIntentReceiver extends BroadcastReceiver{ context.startService(serviceIntent); } -*/ \ No newline at end of file +*/ diff --git a/src/hu/blint/ssldroid/SSLDroidGui.java b/src/hu/blint/ssldroid/SSLDroidGui.java index 9062112..e520eb2 100644 --- a/src/hu/blint/ssldroid/SSLDroidGui.java +++ b/src/hu/blint/ssldroid/SSLDroidGui.java @@ -9,8 +9,8 @@ import android.view.View.OnClickListener; import android.widget.Button; public class SSLDroidGui extends Activity implements OnClickListener { - private static final String TAG = "ServicesDemo"; - Button buttonStart, buttonStop; + private static final String TAG = "SSLDroidGui"; + Button buttonStart, buttonStop, showLog; @Override public void onCreate(Bundle savedInstanceState) { diff --git a/src/hu/blint/ssldroid/TcpProxy.java b/src/hu/blint/ssldroid/TcpProxy.java index dd1a007..5174e76 100644 --- a/src/hu/blint/ssldroid/TcpProxy.java +++ b/src/hu/blint/ssldroid/TcpProxy.java @@ -1,20 +1,13 @@ package hu.blint.ssldroid; -import java.net.*; -import java.io.*; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.UnrecoverableKeyException; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.ServerSocket; +import java.sql.Timestamp; +import java.util.Date; import android.util.Log; -import android.widget.Toast; /** * This is a modified version of the TcpTunnelGui utility borrowed from the @@ -25,13 +18,13 @@ public class TcpProxy { String tunnelHost; int tunnelPort; String keyFile, keyPass; - Relay inRelay, outRelay; Thread server = null; + ServerSocket ss = null; public TcpProxy() { } - public TcpProxy(int listenPort, String tunnelHost, int tunnelPort, + /*public TcpProxy(int listenPort, String tunnelHost, int tunnelPort, String keyFile, String keyPass) { this.listenPort = listenPort; this.tunnelHost = tunnelHost; @@ -59,168 +52,52 @@ public class TcpProxy { public String getKeyPass() { return keyPass; } - - private static SSLSocketFactory sslSocketFactory; - - public static final SSLSocketFactory getSocketFactory(String pkcsFile, - String pwd) { - 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()); - SSLContext context = SSLContext.getInstance("TLS"); - context.init(keyManagerFactory.getKeyManagers(), null, - new SecureRandom()); - sslSocketFactory = (SSLSocketFactory) context - .getSocketFactory(); - - } catch (FileNotFoundException e) { - Log.d("SSLDroid", "Error loading the client certificate file:" - + e.getMessage()); - // Toast.makeText(none, "SSLDroid Sulyos Errorhiba" + - // e.getMessage(), Toast.LENGTH_LONG).show(); - } catch (KeyManagementException e) { - Log - .d("SSLDroid", "No SSL algorithm support: " - + e.getMessage()); - } catch (NoSuchAlgorithmException e) { - Log.d("SSLDroid", "No common SSL algorithm found: " - + e.getMessage()); - } catch (KeyStoreException e) { - Log - .d("SSLDroid", "Error setting up keystore:" - + e.getMessage()); - } catch (java.security.cert.CertificateException e) { - Log.d("SSLDroid", "Error loading the client certificate:" - + e.getMessage()); - } catch (IOException e) { - Log.d("SSLDroid", "Error loading the client certificate file:" - + e.getMessage()); - } catch (UnrecoverableKeyException e) { - Log.d("SSLDroid", "Error loading the client certificate:" - + e.getMessage()); - } + */ + public void createNotification(String title, String text) { + try { + FileWriter outFile = new FileWriter("/mnt/sdcard/ssldroid.txt"); + PrintWriter out = new PrintWriter(outFile); + Date date= new Date(); + + out.println(new Timestamp(date.getTime())+" "+title+" "+text); + out.close(); + } catch (IOException e){ + return; } - return sslSocketFactory; } public void serve(int listenPort, String tunnelHost, int tunnelPort, String keyFile, String keyPass) throws IOException { - final TcpProxy ttg = new TcpProxy(listenPort, tunnelHost, tunnelPort, - keyFile, keyPass); - + //final TcpProxy ttg = new TcpProxy(listenPort, tunnelHost, tunnelPort,keyFile, keyPass); // create the server thread - server = new Thread() { - public void run() { - ServerSocket ss = null; - try { - ss = new ServerSocket(ttg.getListenPort()); - Log.d("SSLDroid", "Listening for connections on port " - + ttg.getListenPort() + " ..."); - } catch (Exception e) { - Log.d("SSLDroid", "Error setting up listening socket: " - + e.getMessage()); - // e.printStackTrace(); - System.exit(1); - } - while (true) { - try { - // accept the connection from my client - Socket sc = ss.accept(); - Socket st; - - try { - st = (SSLSocket) getSocketFactory(ttg.getKeyFile(), - ttg.getKeyPass()).createSocket( - ttg.getTunnelHost(), ttg.getTunnelPort()); - ((SSLSocket) st).startHandshake(); - } catch (Exception e) { - Log.d("SSLDroid", "SSL failure: " + e.toString()); - st = new Socket(ttg.getTunnelHost(), ttg.getTunnelPort()); - } - - Log.d("SSLDroid", "Tunnelling port " - + ttg.getListenPort() + " to port " - + ttg.getTunnelPort() + " on host " - + ttg.getTunnelHost() + " ..."); - - // relay the stuff thru - Thread fromBrowserToServer = new Relay(sc - .getInputStream(), st.getOutputStream(), - "<<< B2S <<<"); - Thread fromServerToBrowser = new Relay(st - .getInputStream(), sc.getOutputStream(), - ">>> S2B >>>"); - - fromBrowserToServer.start(); - fromServerToBrowser.start(); - - if (server.isInterrupted()) { - ss.close(); - return; - } - - } catch (Exception ee) { - Log.d("SSLDroid", "Ouch: " + ee.getMessage()); - // ee.printStackTrace(); - } - } - } - }; + try { + ss = new ServerSocket(listenPort); + Log.d("SSLDroid", "Listening for connections on port " + + listenPort + " ..."); + //ttg.doLog("Listening for connections on port " + ttg.getListenPort() + " ..."); + } catch (Exception e) { + Log.d("SSLDroid", "Error setting up listening socket: " + + e.toString()); + //createNotification(e.getMessage(), "Error setting up listening socket: "+e.toString()); + //e.printStackTrace(); + System.exit(1); + } + server = new TcpProxyServerThread(ss, listenPort, tunnelHost, tunnelPort, keyFile, keyPass); server.start(); } public void stop() { - if (server != null) - server.interrupt(); + if (server != null){ + try { + ss.close(); + server.interrupt(); + } catch (Exception e) { + Log.d("SSLDroid", "Interrupt failure: " + e.toString()); + createNotification(e.getMessage(), "Ouch: "+e.toString());; + } + } Log.d("SSLDroid", "Stopping service"); } - public static class Relay extends Thread { - private InputStream in; - private OutputStream out; - private final static int BUFSIZ = 4096; - private byte buf[] = new byte[BUFSIZ]; - public Relay(InputStream in, OutputStream out, String prefix) { - this.in = in; - this.out = out; - } - - public void run() { - int n = 0; - - try { - while ((n = in.read(buf)) > 0) { - out.write(buf, 0, n); - out.flush(); - - for (int i = 0; i < n; i++) { - if (buf[i] == 7) - buf[i] = '#'; - } - - if (Thread.interrupted()) { - // We've been interrupted: no more serving. - return; - } - } - } catch (SocketException e) { - Log.d("SSLDroid", e.getMessage()); - } catch (IOException e) { - Log.d("SSLDroid", e.getMessage()); - } finally { - try { - in.close(); - out.close(); - } catch (IOException e) { - Log.d("SSLDroid", e.getMessage()); - } - } - - Log.d("SSLDroid", "Quitting stream proxy..."); - } - } -} \ No newline at end of file +} diff --git a/src/hu/blint/ssldroid/TcpProxyServerThread.java b/src/hu/blint/ssldroid/TcpProxyServerThread.java new file mode 100644 index 0000000..43195b5 --- /dev/null +++ b/src/hu/blint/ssldroid/TcpProxyServerThread.java @@ -0,0 +1,224 @@ +package hu.blint.ssldroid; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; +import java.sql.Timestamp; +import java.util.Date; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +import android.util.Log; + +public class TcpProxyServerThread extends Thread { + + int listenPort; + String tunnelHost; + int tunnelPort; + String keyFile, keyPass; + Relay inRelay, outRelay; + ServerSocket ss = null; + + public TcpProxyServerThread(ServerSocket ss, int listenPort, String tunnelHost, int tunnelPort, String keyFile, String keyPass) { + this.listenPort = listenPort; + this.tunnelHost = tunnelHost; + this.tunnelPort = tunnelPort; + this.keyFile = keyFile; + this.keyPass = keyPass; + this.ss = ss; + } + + /*@Override + public static void yield(){ + try { + ss.close(); + } catch (IOException e) { + Log.d("SSLDroid", "Error loading the client certificate file:" + e.toString()); + } + }*/ + + + + private static SSLSocketFactory sslSocketFactory; + + public final SSLSocketFactory getSocketFactory(String pkcsFile, + String pwd) { + 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()); + SSLContext context = SSLContext.getInstance("TLS"); + context.init(keyManagerFactory.getKeyManagers(), null, + new SecureRandom()); + sslSocketFactory = (SSLSocketFactory) context.getSocketFactory(); + + } catch (FileNotFoundException e) { + Log.d("SSLDroid", "Error loading the client certificate file:" + + e.toString()); + createNotification(e.getMessage(), e.toString()); + //log += "Error loading the client certificate file:" + e.toString() + "\n"; + // Toast.makeText(none, "SSLDroid Sulyos Errorhiba" + + // e.toString(), Toast.LENGTH_LONG).show(); + } catch (KeyManagementException e) { + Log.d("SSLDroid", "No SSL algorithm support: " + e.toString()); + createNotification(e.getMessage(), e.toString()); + //log += "No SSL algorithm support: " + e.toString() + "\n"; + } catch (NoSuchAlgorithmException e) { + Log.d("SSLDroid", "No common SSL algorithm found: " + e.toString()); + createNotification(e.getMessage(), e.toString()); + //log += "No common SSL algorithm found: " + e.toString() + "\n"; + } catch (KeyStoreException e) { + Log.d("SSLDroid", "Error setting up keystore:" + e.toString()); + createNotification(e.getMessage(), e.toString()); + //log += "Error setting up keystore:" + e.toString() + "\n"; + } catch (java.security.cert.CertificateException e) { + Log.d("SSLDroid", "Error loading the client certificate:" + + e.toString()); + createNotification(e.getMessage(), e.toString()); + //log += "Error loading the client certificate:" + e.toString() + "\n"; + } catch (IOException e) { + Log.d("SSLDroid", "Error loading the client certificate file:" + + e.toString()); + createNotification(e.getMessage(), e.toString()); + //log += "Error loading the client certificate file:" + e.toString() + "\n"; + } catch (UnrecoverableKeyException e) { + Log.d("SSLDroid", "Error loading the client certificate:" + + e.toString()); + createNotification(e.getMessage(), e.toString()); + //log += "Error loading the client certificate:" + e.toString() + "\n"; + } + } + return sslSocketFactory; + } + + public void createNotification(String title, String text) { + try { + FileWriter outFile = new FileWriter("/mnt/sdcard/ssldroid.txt"); + PrintWriter out = new PrintWriter(outFile); + Date date= new Date(); + + out.println(new Timestamp(date.getTime())+" "+title+" "+text); + out.close(); + } catch (IOException e){ + return; + } + } + + public class Relay extends Thread { + private InputStream in; + private OutputStream out; + private final static int BUFSIZ = 4096; + private byte buf[] = new byte[BUFSIZ]; + + public Relay(InputStream in, OutputStream out) { + this.in = in; + this.out = out; + } + + public void run() { + int n = 0; + + try { + while ((n = in.read(buf)) > 0) { + if (Thread.interrupted()) { + // We've been interrupted: no more relaying + Log.d("SSLDroid", "Interrupted thread"); + return; + } + out.write(buf, 0, n); + out.flush(); + + for (int i = 0; i < n; i++) { + if (buf[i] == 7) + buf[i] = '#'; + } + } + } catch (SocketException e) { + Log.d("SSLDroid", e.toString()); + createNotification(e.getMessage(), e.toString()); + } catch (IOException e) { + Log.d("SSLDroid", e.toString()); + createNotification(e.getMessage(), e.toString()); + } finally { + try { + in.close(); + out.close(); + } catch (IOException e) { + Log.d("SSLDroid", e.toString()); + createNotification(e.getMessage(), e.toString()); + } + } + Log.d("SSLDroid", "Quitting stream proxy..."); + } + } + + public void run() { + while (true) { + try { + if (isInterrupted()){ + Log.d("SSLDroid", "Interrupted server thread, closing sockets..."); + ss.close(); + return; + } + // accept the connection from my client + Socket sc = null; + try { + sc = ss.accept(); + } catch (SocketException e){ + Log.d("SSLDroid", "Accept failure: " + e.toString()); + } + + Socket st = null; + + try { + st = (SSLSocket) getSocketFactory(keyFile, keyPass).createSocket(tunnelHost, tunnelPort); + ((SSLSocket) st).startHandshake(); + } catch (Exception e) { + Log.d("SSLDroid", "SSL failure: " + e.toString()); + //createNotification(e.getMessage(), "SSL failure: "+e.toString()); + Thread.sleep(10000); + continue; + //st = new Socket(ttg.getTunnelHost(), ttg.getTunnelPort()); + } + + Log.d("SSLDroid", "Tunnelling port " + + listenPort + " to port " + + tunnelPort + " on host " + + tunnelHost + " ..."); + + // relay the stuff thru + Thread fromBrowserToServer = new Relay( + sc.getInputStream(), st.getOutputStream()); + Thread fromServerToBrowser = new Relay( + st.getInputStream(), sc.getOutputStream()); + + fromBrowserToServer.start(); + fromServerToBrowser.start(); + + } catch (Exception ee) { + Log.d("SSLDroid", "Ouch: " + ee.toString()); + createNotification(ee.getMessage(), "Ouch: "+ee.toString()); + //ttg.doLog("Ouch: " + ee.toString()); + } + } + } +}; +