Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm trying to write an android application that communicates with a java PC server via secure connection (SSL/TLS) i hav eread several tutorials and followed them and the following code works when used on PC to PC , but when i but the client code on an android (3.2) device it stalls on the SSL or TLS Handshake. the following is the client communication code:

public class ClientCommunicationManager implements Runnable{
    /**
     * Application context
    */
    private Context context;
    /**
     * Host string
    */
    private String host;
    /**
    * port number
    */
    private int port;
      /**
       * Report Recieved Listeners vector
       */
      private Vector<ReportRecievedListener> rrListeners;
      /**
       * Connection to the client
       */
      private DataInputStream din;

      /**
       * Connection to the client
       */
      private DataOutputStream dout;

      /**
       * KeyStore for storing our public/private key pair
       */
      private KeyStore clientKeyStore;

      /**
       * KeyStore for storing the server's public key
       */
      private KeyStore serverKeyStore;

      /**
       * Used to generate a SocketFactory
       */
      private SSLContext sslContext;

      /**
       * A list of visible postings
       */
      private Set postings = new HashSet();

      /**
       * Passphrase for accessing our authentication keystore
       */
      static private final String passphrase = "a1n2d3r4o5i6d";

      /**
       * A source of secure random numbers
       */
      static private SecureRandom secureRandom;

      public ClientCommunicationManager( String host, int port,Context context ) {
          this.context = context;
          this.host = host;
          this.port = port;

          rrListeners = new Vector<ReportRecievedListener>();

          secureRandom = new SecureRandom();
          secureRandom.nextInt();      




      }

      public void registerRRListener(ReportRecievedListener listener){
          rrListeners.add(listener);
      }

      private void setupServerKeystore() throws GeneralSecurityException, IOException {
        serverKeyStore = KeyStore.getInstance( "BKS" );

        serverKeyStore.load( context.getResources().openRawResource(R.raw.serverbks), 
                            "public".toCharArray() );
      }

      private void setupClientKeyStore() throws GeneralSecurityException, IOException {
        clientKeyStore = KeyStore.getInstance( "BKS" );
        clientKeyStore.load( context.getResources().openRawResource(R.raw.clientbks),
                           passphrase.toCharArray() );
      }

      private void setupSSLContext() throws GeneralSecurityException, IOException {
        TrustManagerFactory tmf =       TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init( serverKeyStore );

        KeyManagerFactory kmf =     KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init( clientKeyStore, passphrase.toCharArray() );

        sslContext = SSLContext.getInstance( "SSL" );
        sslContext.init( kmf.getKeyManagers(),
                         tmf.getTrustManagers(),
                         secureRandom );
      }

      public void connect() {
         new Thread(new Runnable() {

            public void run() {
                try {
                    setupServerKeystore();
                    setupClientKeyStore();
                    setupSSLContext();
                } catch (GeneralSecurityException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }




               SSLSocketFactory sf = sslContext.getSocketFactory();


               SSLSocket socket= null;
               InputStream in = null;
               OutputStream out = null;

            try {
                 socket = (SSLSocket)sf.createSocket( host, port );
                 socket.setUseClientMode(true); 

                 socket.startHandshake();

                 in = socket.getInputStream();
                 out = socket.getOutputStream();
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }



               din = new DataInputStream( in );
               dout = new DataOutputStream( out );

               if(socket!=null)
                  new Thread( this ).start();

            }
        }).start();

      }



      public void run() {
          boolean isConnected = true;
        try {
          while (isConnected) {
            String msg = din.readUTF();
            if(msg.equals("END"))
                isConnected = false;
            else
                fireReportRecievedEvent(new ReportRecievedEvent(msg));


          }
        } catch( IOException ie ) {
          ie.printStackTrace();
        }
      }

     private void fireReportRecievedEvent(ReportRecievedEvent event){
         for(ReportRecievedListener listener : rrListeners){
             listener.onReportRecieved(event);
         }
     }


}

following is the server code:

public class CommunicationManager implements Runnable{

  private int port = Constants.SERVER_PORT;
  private HashSet<ConnectionProcessor> connections = new     HashSet<ConnectionProcessor>();
  private KeyStore clientKeyStore;
  private KeyStore serverKeyStore;
  private SSLContext sslContext;
  static private SecureRandom secureRandom;
  private boolean running;
  private SSLServerSocket ss=null;

  private static CommunicationManager instance=null;



private CommunicationManager(){

}

public static CommunicationManager getInstance(){
    if(instance == null){
        instance = new CommunicationManager();
    }

    return instance;
}


public int getSecureRandom(){
    SecureRandom securerandom = new SecureRandom();
    return securerandom.nextInt();

}



public boolean isRunning() {
    return running;
}



public void setRunning(boolean running) {
    this.running = running;
}

public void startServer(){
    if(!isRunning()){
        setRunning(true);
        new Thread(this).start();
    }

}

public void stopServer(){
    setRunning(false);
    for(ConnectionProcessor cp : connections){
        cp.close();
    }

    try {
        if(ss!=null)
            ss.close();
    } catch (IOException e) {

        e.printStackTrace();
    }

}



private void setupClientKeyStore() throws GeneralSecurityException, IOException {
    clientKeyStore = KeyStore.getInstance( "JKS" );
    clientKeyStore.load( new FileInputStream( "resources/client.public" ),
                       "public".toCharArray() );
  }

  private void setupServerKeystore() throws GeneralSecurityException, IOException {
    serverKeyStore = KeyStore.getInstance( "JKS" );
    serverKeyStore.load( new FileInputStream( "resources/server.private" ),
                        Constants.SERVER_KEYSTORE_PWD.toCharArray() );
  }

  private void setupSSLContext() throws GeneralSecurityException, IOException {
    TrustManagerFactory tmf = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() );
    tmf.init( clientKeyStore );

    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm() );
    kmf.init( serverKeyStore, Constants.SERVER_KEYSTORE_PWD.toCharArray() );

    sslContext = SSLContext.getInstance( "TLS" );
    sslContext.init( kmf.getKeyManagers(),
                     tmf.getTrustManagers(),
                     secureRandom );
  }



  @Override
  public void run() {


      try {
          setupClientKeyStore();
          setupServerKeystore();  
          setupSSLContext();
    } catch (GeneralSecurityException | IOException e) {
        e.printStackTrace();
    }

      SSLServerSocketFactory sf = sslContext.getServerSocketFactory();

      try {
        ss = (SSLServerSocket)sf.createServerSocket( port );
    } catch (IOException e) {

        e.printStackTrace();
    }

      // Require client authorization
      ss.setNeedClientAuth( true );


      System.out.println( "Listening on port "+port+"..." );
      while (isRunning()) {
        Socket socket=null;
        try {
            socket = ss.accept();
        } catch (IOException e) {

            if(e.getClass() == SocketException.class){
                System.out.print("accept() threw SocketException because of close\n");
            }
        }
        if(socket!=null && socket.isConnected()){
            System.out.println( "Got connection from "+socket );

            ConnectionProcessor cp = new ConnectionProcessor( this, socket );
            connections.add( cp );
        }

      }






     closeServer();
  }

  private void closeServer() {
    for(ConnectionProcessor cp : connections){
        cp.close();
    }

    try {
        ss.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

/**
   * Remove a connection that has been closed from our set
   * of open connections
   */
  public void removeConnection( ConnectionProcessor cp ) {
    connections.remove( cp );
  }

  /**
   * Return an iteration over open connections
   */
  public Iterator getConnections() {
    return connections.iterator();
  }
  /**
   * Broadcast a report over all connections
   */
  public void broadcastReport(String report){
      for(ConnectionProcessor cp : connections){
          cp.send(report);
      }
  }
  /**
   * Broadcast a report over all connections using a new thread
   */

public void broadcastOnThread(final String report) {
    Thread t = new Thread(new Runnable() {

        @Override
        public void run() {
            if(isRunning())
                broadcastReport(report);    

        }
    }) ;

    t.start();
}

 /**
   * recieve a new report to be broadcasted
   */
public void acceptReport(String report_string) {
    broadcastOnThread(report_string);

}





}

Any help or insight would be very much appreciated. thank you.

share|improve this question
 
Your exception handling is very poor. In almost every case you print the message and just continue as though it hadn't happened, when you should be aborting the method concerned. In the accept() loop you only print it conditionally, which is even worse. Fix that first. Then run both with -DJavax.net.debug=ssl,handshake and add the resulting output to your post. –  EJP Nov 18 '12 at 22:42
 
@EJP You're correct about my exception handeling but i dont think it is relevant at the moment. I just want to set the connection up. regarding SSL debug mode, I dont think its applicable on android platform, or is it? ... as i explained the above code works well when both codes (client and server) are run from the same pc. when i port the client to android the connection is never made and when debugging i see that the handshake just gets stuck as if its deadlocked. but thank you for the suggestion –  user1666216 Nov 19 '12 at 18:34
 
Don't forget to verify the host name from the server certificate when you establish the connection. –  Bruno Nov 23 '12 at 11:40
add comment

1 Answer

up vote 0 down vote accepted

The problem was no data was being exchanged (yet) so the handshake never finished.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.