Message-Id: <9807311837.AA17341@blustone.operations.bluestone.com>
Date: Fri, 31 Jul 1998 14:54:27 -0400
To: java-security@java.Sun.COM
From: Bob Naugle <bnaugle@bluestone.COM>
Subject: Bug with SSLServerSocket (part 2)
I posted the message message to this group about two ago. Since then have
seen that another implementation of SSL (from Phaos) does not have this
problem.
I have a few questions :
Did anyone try my test case to see this problem?
Am I mailing this problem to the correct email list?
Can I get on this mailing list?
What is the proper channel for me to get support for this problem?
Is it possible to get the source code for the package sun.security.ssl so I
can fix the bug myself?
thanks in advance,
Bob Naugle
---- Previous message below ----
Bug report.
If you create a server socket using the SSLServerSocket factory and try to
write to the socket
before reading from it you get this exception :
** Exception in application:
java.lang.NullPointerException
at sun.security.ssl.InputRecord.hashInternal(Compiled Code)
at sun.security.ssl.InputRecord.read(Compiled Code)
at sun.security.ssl.SSLSocketImpl.clearPipeline(Compiled Code)
at sun.security.ssl.SSLSocketImpl.write(Compiled Code)
at sun.security.ssl.AppOutputStream.write(Compiled Code)
at SSLTestServer2.<init>(Compiled Code)
at SSLTestServer2.main(SSLTestServer2.java:15)
at sun.security.Login.main(Compiled Code)
This exeption does not occur if you simply read from the socket before
writing to it. The problem is
that in my application the server needs to write to the socket before it
reads. This error occurs in
both the JDK 1.1.4 and JDK 1.1.6 on Windows NT. I used the SSL packages
that were included with
java webserver 1.1.
I have attached code that shows this bug.
There are two files here, a client and a server. I am assuming the
keystore is in c:\keystore and
this should be changed to where yours is. Both the client and server need
one input argument. You need
to run the server first then the client and they must both be started with
the same input argument.
the input argument is just a single character being either c or n. If you
specify a c the program will
cause the bug I have shown above. If you specify a n it will not crash
because the server is reading
from the socket before writing.
So to run this you must have two dos prompts on a windows nt 4.0 box (I did
not try 95).
In one prompt run :
java -Duser.keystore=c:\keystore sun.security.Login sun.security.AuthGUI
SSLTestServer2 c
In the other run :
java -Duser.keystore=c:\keystore sun.security.Login sun.security.AuthGUI
SSLTestClient2 c
To see the workaround do this :
In one prompt run :
java -Duser.keystore=c:\keystore sun.security.Login sun.security.AuthGUI
SSLTestServer2 n
In the other run :
java -Duser.keystore=c:\keystore sun.security.Login sun.security.AuthGUI
SSLTestClient2 n
Please let me know if this is a bug or my problem.
Thanks,
Bob Naugle
The source code is below :
SSLTestServer2.java
-------------------
import java.awt.*;
import java.net.*;
import java.io.*;
import java.security.*;
import javax.security.cert.*;
import javax.net.*;
import javax.net.ssl.*;
public class SSLTestServer2 {
private SSLSocket socket;
boolean m_crash = false;
public static void main (String args []) {
SSLTestServer2 server = new SSLTestServer2 (args);
}
SSLTestServer2 (String args []) {
if (args.length != 1) {
System.out.println ("[Client] Usage: java SSLTestServer"
+ " c | n (c will make it crash, n will not)");
System.exit (-1);
}
if (args[0].equals("c"))
{
System.out.println("Crash flag set");
m_crash = true;
}
// intialize local variables
SSLServerSocket serversocket = (SSLServerSocket) null;
try {
serversocket = (SSLServerSocket)
(SSLServerSocketFactory.getDefault ())
.createServerSocket (20000, 1, InetAddress.getLocalHost
());
}
catch (IOException e) {
System.out.println (
"\n[Server] Server error in socket creation (IOException).");
e.printStackTrace ();
System.exit (-1);
}
// run the listen/accept loop forever
while (true) {
try {
// listen for a socket connection
System.out.println ("[Server] Listening for connection...");
socket = (SSLSocket)serversocket.accept ();
System.out.println ("[Server] ...connection received.");
OutputStream os = socket.getOutputStream ();
InputStream is = socket.getInputStream ();
byte buf[] = new byte [100];
if (!m_crash)
{
int br = is.read(buf,0,1);
System.out.println ("[Server] ...read byte.");
}
os.write(buf,0,1);
System.out.println ("[Server] ...wrote byte.");
os.flush();
// close the connection, but not the server socket
socket.close ();
}
catch (IOException e) {
System.out.println (
"\n[Server] Server error in accept, send (IOException).");
e.printStackTrace ();
}
}
}
}
-------------------
SSLTestClient2.java
------------------
import java.awt.*;
import java.net.*;
import java.io.*;
import javax.net.*;
import javax.net.ssl.*;
public class SSLTestClient2 {
public static void main (String args []) {
SSLTestClient2 client = new SSLTestClient2 (args);
}
static boolean m_crash = false;
SSLTestClient2 (String args []) {
// verify that we received the correct number of arguments
if (args.length != 1) {
System.out.println ("[Client] Usage: java SSLTestClient"
+ " c | n (c will make it crash, n will not)");
System.exit (-1);
}
if (args[0].equals("c"))
{
System.out.println("Crash flag set");
m_crash = true;
}
//initial variables
Socket socket;
int port = 20000;
String server = new String("localhost");
socket = null;
try {
System.out.println ("[Client] Opening socket.");
socket = openSocket (server, port);
System.out.println ("[Client] ...done opening socket.");
int blockSize, length;
System.out.println ("[Client] Receiving data...");
try {
// open an object stream and read values from server
InputStream is = socket.getInputStream ();
OutputStream os = socket.getOutputStream();
byte buf[] = new byte [100];
if (!m_crash)
{
buf[0]=0;
buf[1]=1;
os.write(buf,0,1);
System.out.println("wrote byte");
os.flush();
}
blockSize = is.read(buf,0,1);
System.out.println("read byte");
socket.close();
System.out.println ("[Client] Connection closed by client.");
}
catch (Exception e) {
System.out.println ("[Client] receive_file EXCEPTION");
e.printStackTrace ();
}
}
catch (IOException e) {
System.out.println("[Client] EXCEPTION: Connection failed");
e.printStackTrace ();
}
}
/**
* Opens the connections to the server on the specified port number.
*
* @param server The name of the server to connect to.
* @param port The port number to connect to.
*/
private Socket openSocket (String server, int port)
throws IOException
{
Socket socket = null;
// Alternative for JDK 1.1 and no javax.net Factory classes
//socket = new Socket (server, port);
if (server.equals ("localhost")) {
// Note: Had problem connecting with "localhost" as server name
socket = (SSLSocketFactory. getDefault ()).
createSocket (InetAddress.getLocalHost (), port);
} else {
try {
socket = (SSLSocketFactory.getDefault ()).
createSocket (server, port);
} catch (UnknownHostException uhe) {
System.out.println("[Client] EXCEPTION: Unknown host: "+
server);
uhe.printStackTrace ();
} catch (ConnectException ce) {
System.out.println("[Client] EXCEPTION: Connect : "+
server);
ce.printStackTrace ();
}
}
return socket;
}
/**
* Sends data across the socket.
*
* @param data Data to be sent across the socket.
* @param socket The connection to transmit data on.
*/
private static void sendData(String data, Socket socket)
throws IOException {
OutputStream os = socket.getOutputStream ();
DataOutputStream dos = new DataOutputStream (os);
String sendString = new String (data + "\n");
dos.writeBytes (sendString);
dos.flush ();
}
}
Bob Naugle bnaugle@bluestone.com
Senior Software Engineer
Bluestone Software http://www.bluestone.com/