Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4524090

SSLSocketImpl error behavior inconsistent with java.net.Socket

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 1.4.1
    • 1.3.1, 1.4.0
    • security-libs
    • None
    • hopper
    • generic, x86
    • generic, windows_2000
    • Verified

      During the evaluation of bug 4514971 we discovered problems in the error handling in SSLSocketImpl. These were partially fixed. This work needs to be completed and better integrated with the SSLSocketImpl state machine. We should also follow bug 4517622 which will define the behavior of Sockets in error cases more clearly.

      Another issue is that we currently call close() on the Socket in (most) error conditions and at TLS layer shutdown. This is inconsistent with java.net.Socket and should be reconsidered.

      ###@###.### 2001-11-09


      Customer Problem Description:
      We have implemented secured connection usning JSSE 1.02 with JDK 1.3.1 running on Windows 2000.
      A socket client application is connected to the socket server over the firewall using SUN's SSL implementation. The client application is also a RMI Server.

      The client connects to the server (using socket pool) and keeps connections open. If the connection is not used within 15 minutes background thread closes it.

      While client is connected it sends a request to the server using BufferedWriter.write and reads the response using BufferedReader.readLine(). There is always one response for one request.

      I have discovered that occasionally the client sends a request and then BufferedReader.readline() receives the null instead of a valid response. This never happens if the client and the server are using plain sockets instead of SSL sockets.

      I have spent some time testing different error conditions that may occur while client application writes and than reads from the socket and I have compared results between SSL and plain sockets. The plain sockets will always throw some meaningful exception like: Read timeout occurred or Connection reset by peer or Connection aborted by pier etc. In case of SSL socket there is no exception being thrown, the only indication that something went wrong is that BufferedReader.readLine() returned null instead of the valid data.
      I have also observed that even if the physical connection is terminated by unplugging the SSL Server from the network the SSL client will successfully write data and only reading from the socket is going to indicate problem by returning null. At this point there is no way to determine if the server received data or not. In case of the plain sockets when the connection is dropped the writing to the socket is going to fail so the client can intelligently reconnect with the different socket and resent the data.

      Customer has provided a sample code and would like to know if we have any
      suggestions to change it in order to handle SSL Socket errors in a better
      manner in JDK 1.4.

      I have attached the code that is responsible for writing and reading to/from the
      socket. If SSL socket fails the "Where is the data ????" message is displayed.

      TESTCASEBEGIN
      package COM.vilink.tx.net;

      import java.io.BufferedReader;
      import java.io.BufferedWriter;
      import java.io.OutputStreamWriter;
      import java.io.InputStreamReader;
      import java.io.IOException;
      import java.io.InterruptedIOException;
      import java.net.Socket;

      /**
       *
       * @author kgemborys
       * @version
       */
      public class TxSimpleSocketStreamer extends TxSocketConnectionImpl {

          public TxSimpleSocketStreamer(Socket a_socket,int a_connectionTimeOut)
      throws IOException {
              super(a_socket, a_connectionTimeOut);
          }

          public TxSimpleSocketStreamer(Socket a_socket) throws IOException {
              super(a_socket);
          }
          
          public TxMessage send(String a_msg, int a_timeout) {
              BufferedWriter bw = null;
              TxMessage retMsg = new TxMessage(a_msg);
              try {
                  if (a_timeout >= 0 && a_timeout <= _connectionTimeOut) {
                      _socket.setSoTimeout(a_timeout);
      } else {
                      _socket.setSoTimeout(_connectionTimeOut);
      }
                  bw = new BufferedWriter(new
      OutputStreamWriter(_socket.getOutputStream(), _encode));
                  if (bw == null) {
                      throw new IllegalStateException("TxSocketSimple.Send() - Invalid
      socket type");
                  }
           bw.write(a_msg);
      bw.newLine();
           bw.write(EOTX);
      bw.newLine();
           bw.flush();
      System.out.println(Thread.currentThread().getName() + " -
      Sending :" + a_msg);
              }
              catch (Throwable th) {
                  retMsg.setError(99, "", th, "");
              }
              finally {
                  bw = null;
                  return retMsg;
              }
          }
          
          public TxMessage send(String a_msg) {
              return send(a_msg, -1);
          }
          
          public TxMessage receive() {
      String line = "";
              TxMessage msg = null;
              BufferedReader br;
      System.out.println(Thread.currentThread().getName() + "
      Receiving on Socket: " + _socket.hashCode());
      try {
                  br = new BufferedReader(new
      InputStreamReader(_socket.getInputStream(), _encode));
                  if (br == null) {
                      throw new IllegalStateException("TxSocketSimple.Receive() -
      Invalid socket type");
                  }
                  StringBuffer strbuf = new StringBuffer();
      line = br.readLine();
                  if (line == null) {
                      msg = new TxMessage("");
                      msg.setError(99, "Where is the data ????", null, "");
                  }
                  else {
                      while (line != null && ! line.equals(EOTX)) {
          
      System.out.println(Thread.currentThread().getName() + " - Receiving :" + line);
                          strbuf.append(line);
                          line = br.readLine();
                      }
                      // Reset connection timeout to the default value
                      _socket.setSoTimeout(_connectionTimeOut);
                      msg = new TxMessage(strbuf.toString());
                  }
      }
              catch (Throwable th) {
                  msg = new TxMessage("");
                  msg.setError(99, "Socket connection was terminated unexcpectedly.",
      th, "");
              }
              finally {
      // System.out.println(Thread.currentThread().getName() + " -
      BEGIN OF TRANS");
      // System.out.println(Thread.currentThread().getName() + "- " +
      strbuf.toString());
      // System.out.println(Thread.currentThread().getName() + "-
      Receiving : END OF TRANS");
                  br = null;
                  return msg;
              }
          }
      }

      /TESTCASEEND


      ###@###.### 2001-11-15

      I have attached a testcase and the error messages seen in each case below.
      Please let me know if all these error messages are pertinent to this bug
      report or we need a new bug report to track these different errors.

      I have duplicated this problem inhouse between Win Server and Solaris 8 client.
      Customer has used two win systems to reproduce this problem.

      ---------

      I have attached four files that can be used to duplicate the reported
      problems. The classes are based on the sample provided by SUN as part of
      JSSE package.

      (See attached file: SSLSocketClient.java)(See attached file:
      SimpleClassServer.java)(See attached file: ClassFileServer.java)(See
      attached file: testkeys)


      Client code:
           - SSLSocketClient.java

      Server code:
           - ClassFileServer.java
           - SimpleClassServer.java

      testkeys is used for SSL authentication by both client and server.

      The attached sample can be executed over both plain and SSL sockets. This
      is controlled by additional runtime parameter (TLS). The sample socket
      client sends one line string to the socket server . The socket server reads
      the line and resends it back to the client. The client loops 10 time and
      sends the "close" connection token to the server and both client and server
      close the connection.

      Please make sure that Client and Server code are executed on different
      physical machines.
      Tests where performed on Windows 2000, JDK 1.3.1.1, JSSE 1.0.2.

      The detail description of how to dupilcate the problems:

      1. Test Case for Timeout problem

      Plain Sockets:

      Server:

      set breakpoint in SimpleClassServer line 65 (bw.write)
      run server as plain socket socket
      java ClassFileServer 7030 /workingdirectory

      Client:

      run client as plain socket
      java SSLSocketClient host 7030

      The exception is thrown:

      java.io.InterruptedIOException: Read timed out
              at java.net.SocketInputStream.socketRead(Native Method)
              at java.net.SocketInputStream.read(SocketInputStream.java:86)
              at java.net.SocketInputStream.read(SocketInputStream.java:67)
              at java.io.InputStreamReader.fill(InputStreamReader.java:173)
              at java.io.InputStreamReader.read(InputStreamReader.java:249)
              at java.io.BufferedReader.fill(BufferedReader.java:139)
              at java.io.BufferedReader.readLine(BufferedReader.java:299)
              at java.io.BufferedReader.readLine(BufferedReader.java:362)
              at SSLSocketClient.main(SSLSocketClient.java:102)


      SSL:

      Server:

      run server as SSL socket socket
      java ClassFileServer 7030 /workingdirectory TLS

      Client:

      run client as SSL socket
      java SSLSocketClient host 7030 TLS

      Client readLine returns null and continues executing.


      2. Test Case to simulate problems when firewall is dropping connections

      Plain Sockets:

      Server:

      Uncomment line 67 in SimpleClassServer (socket.close())
      Remove breakpoint

      run server as plain socket socket

      Client:

      run client as plain socket

      The exception is thrown:

      D:\Work\Transactions\SSL>java SSLSocketClient vl122 7030
      Sending Back: Connection: Keep-Alive
      java.net.SocketException: Connection reset by peer: JVM_recv in socket
      input str
      eam read
              at java.net.SocketInputStream.socketRead(Native Method)
              at java.net.SocketInputStream.read(SocketInputStream.java:86)
              at java.net.SocketInputStream.read(SocketInputStream.java:67)
              at java.io.InputStreamReader.fill(InputStreamReader.java:173)
              at java.io.InputStreamReader.read(InputStreamReader.java:249)
              at java.io.BufferedReader.fill(BufferedReader.java:139)
              at java.io.BufferedReader.readLine(BufferedReader.java:299)
              at java.io.BufferedReader.readLine(BufferedReader.java:362)
              at SSLSocketClient.main(SSLSocketClient.java:102)


      SSL:

      Server:
      run server as SSL socket socket


      Client:

      run client as SSL socket

      Client readLine returns null and continues executing.


      I put a great deal of effort in preparing this sample so please
      verify that you can duplicate the problem and let me know if you need any
      additional instructions.

      Thanks for your assistance, Kris.
      -----------------

            andreas Andreas Sterbenz
            andreas Andreas Sterbenz
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: