0

I am new to Java and SSLSocket. I want to use a specified .cer file to establish a SSLSocket in client part. I search it in google, but doesn't find good solution to it. And here is my code:

    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    InputStream caInput = new BufferedInputStream(new FileInputStream("myCer.cer"));
    Certificate ca;
    try {
        ca = cf.generateCertificate(caInput);
        System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
    } finally {
        caInput.close();
    }

    // Create a KeyStore containing our trusted CAs
    String keyStoreType = KeyStore.getDefaultType();
    KeyStore keyStore = KeyStore.getInstance(keyStoreType);
    keyStore.load(null, null);
    keyStore.setCertificateEntry("ca", ca);

    // Create a TrustManager that trusts the CAs in our KeyStore
    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
    tmf.init(keyStore);

    // Create an SSLContext that uses our TrustManager
    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, tmf.getTrustManagers(), null);

    SSLSocket sock = (SSLSocket)context.getSocketFactory().createSocket("...",21000); //"...": here I ignore the host name. The address and port is right.
    sock.setUseClientMode(true);
    if(sock.isConnected()) {
        System.out.println("Connected...");
    }
    else
    {
        System.out.println("Connect Fails...");
    }

    Login.pbLogin login = Login.pbLogin.newBuilder().setUserID("dbs")
                                    .setPassword("abcd1234")
                                    .setNewPassword("")
                                    .setClientVersion("1.0.0.0")
                                    .setRestarted(true)
                                    .build();


    OutputStream outputStream =sock.getOutputStream();
    byte[] b1=login.getClass().getSimpleName().getBytes("UTF-8");
    byte[] b2=login.toByteArray();

    byte[] bytes = ByteBuffer.allocate(4).putInt(b1.length + b2.length).array();
    outputStream.write(bytes);
    outputStream.write(b1);  //login.getClass().getSimpleName().getBytes("UTF-8")
    outputStream.write(b2);  //login.toByteArray()
    outputStream.flush();

    byte[] content = new byte[100];
    int bytesRead = -1;
    InputStream inputStream = sock.getInputStream();
    String str;

    while(( bytesRead = inputStream.read( content) ) != -1){
        System.out.println("OK ,receive.....");
       // str = new String(Arrays.copyOfRange(content,0,bytesRead), StandardCharsets.UTF_8);
        //System.out.println(str);
    }

I use TCPViewer to see, the SSLSocket is in Established state, but when executing outstream.write , the SSLsocket will be Close_wait state and cause exception:

Exception in thread "main" java.net.SocketException: Software caused connection abort: socket write error.

So I couldn't write the info to server, and exit program. I guess the SSLSocket is not established successfully, but Tcpviewer show it is established early, and it's in Connected state(print "connected."). But when try to write the outputstream, it will in Close_wait state. Could you help me to sort it out?

Mysterion
  • 9,050
  • 3
  • 30
  • 52
iXiaocao
  • 11
  • 2
  • `.createSocket(host,port)` opens the *TCP* connection but does not do the SSL/TLS handshake; try calling `sock.startHandshake()` and see if you get an exception from that and if so add those details. Also, if you can look at the server's logs or have someone do so, see what if anything it says when your connection attempt fails. To avoid leaving the socket in close_wait until exit, call `sock.close()` when you are done with the socket, including if an error/exception prevents you from continuing (usually try-finally or try-with-resources is a good way to do this). – dave_thompson_085 Jul 22 '15 at 12:41
  • @dave_thomson_085 I disagree. `context.getSocketFactory()` returns an SSLSocketFactory and calling `createSocket()` on it will get you an SSLSocket. – Robert Jul 22 '15 at 14:00
  • I tried to use sock.startHandshake() and sock.getSession() method, but it didn't help. I guess there should be a way to judge the SSL/TSL is really "connected" through certification, thus it can pass message normally later. – iXiaocao Jul 23 '15 at 09:53

1 Answers1

0

Then I found the reason today. The code has no issue, the reason is that server part can't parse the protocol buffer (pblogin) correctly, which causes exception, so it close the socket. As a result , the state will be in close_wait.Since I find the reason , wish I can solve it by myself.

iXiaocao
  • 11
  • 2