Hi Arne,
Thanks for the reply.
In the rest of this I'm not arguing against what you've said, I'm just
honestly trying to digest it
> Since SSLSocket inherits from Socket then you can make your
> t3sock of type Socket (you can assign from a subtype to a
> super type).
But because SSLSocket "extends" Socket, surely I have to instantiate a
SSLSocket object somewhere don't I?
Really no need for this: -
sockFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
t3Sock = (SSLSocket)sockFactory.createSocket();
What about all the Value-Added SSL bits that the SSLSocket class must
bolt-on to a Socket?
> If you need to use a SSL specific funtion you can use:
> ((SSLSocket)t3Sock).someSSLSOcketSpecificMethod()
You're casting t3Sock (a Socket object) as a SSLSocket object there right? I
haven't missed some abstract-class or Interface wizardry? So I've got a
vanilla Socket and cast it as a SSLSocket to call, say startHandshake(), and
it's not gonna complain about a bodgy brick-veneer job, absent any
certificate or crypto-algorithm info?
I'd find it easier to picture it the other way around where we have a
SSLSocket and our casting it as a Socket effectively masks out all the SSL
bits, but who cares? I'll just code it like you've said and see how I get
on.
> But that is not "nice".
It's certainly more appealing than the attached code (look for "sslReqd")
I guess the least I can do is put the common stuff such as this. . .
inSock.setKeepAlive(true);
inSock.setReuseAddress(true);
inSock.setTcpNoDelay(true);
inSock.connect(new InetSocketAddress(host,port), CONTIMOUT);
in = new BufferedInputStream (inSock.getInputStream() ,maxBufSiz);
out = new BufferedOutputStream (inSock.getOutputStream(),maxBufSiz);
. . . in a private method with a Socket parameter "inSock" and cast the
SSLSocket to that (or vica versa).
Cheers Richard Maher
import java.io.BufferedOutputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.net.SocketTimeoutException;
import java.lang.System;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class Tier3Socket
{
public static final
String T3ID="T3$";
public static final
int USERSIZ=40;
public static final
int T3IDBUFSIZ=48;
public static final
int CREDBUFSIZ=80;
public static final
int CONTIMOUT=3000;
public byte [] t3IdBuf;
public byte [] readBuf;
public byte [] writeBuf;
private String host;
private int port;
private int maxBufSiz;
private int bytesIn;
private String hostCharSet;
private Socket t3Sock;
private SSLSocket t3SSLSock;
private SSLSocketFactory sockFactory;
private BufferedInputStream in;
private BufferedOutputStream out;
private byte [] outUser;
private byte [] outPwd;
private byte [] credBuf;
private String inMsg;
private String stringOut;
private boolean sslReqd;
Tier3Socket (String host, int port, int maxBufSiz, String hostCharSet,
boolean sslReqd)
{
this.host = host;
this.port = port;
this.maxBufSiz = maxBufSiz;
this.hostCharSet = hostCharSet;
this.bytesIn = 0;
this.sslReqd = sslReqd;
t3IdBuf = new byte[T3IDBUFSIZ];
readBuf = new byte[maxBufSiz];
if (sslReqd)
sockFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
}
public void open() throws UnknownHostException, IOException
{
if (sslReqd)
{
t3SSLSock = (SSLSocket)sockFactory.createSocket();
t3SSLSock.setKeepAlive(true);
t3SSLSock.setReuseAddress(true);
t3SSLSock.setTcpNoDelay(true);
t3SSLSock.connect(new InetSocketAddress(host,port), CONTIMOUT);
in = new BufferedInputStream (t3SSLSock.getInputStream() ,maxBufSiz);
out = new BufferedOutputStream (t3SSLSock.getOutputStream(),maxBufSiz);
t3SSLSock.setUseClientMode(true);
try {t3SSLSock.startHandshake();}
catch (IOException e)
{
System.out.println("Failed SSL Handshake");
throw new IOException("Can't SSL on Socket");
}
}
else
{
t3Sock = new Socket();
t3Sock.setKeepAlive(true);
t3Sock.setReuseAddress(true);
t3Sock.setTcpNoDelay(true);
t3Sock.connect(new InetSocketAddress(host,port), CONTIMOUT);
in = new BufferedInputStream (t3Sock.getInputStream() ,maxBufSiz);
out = new BufferedOutputStream (t3Sock.getOutputStream(),maxBufSiz);
}
}
public void handShake(String username, String password) throws IOException
{
credBuf = new byte[CREDBUFSIZ];
outUser = username.getBytes(hostCharSet);
System.arraycopy(outUser, 0, credBuf, 0, outUser.length);
outPwd = password.getBytes(hostCharSet);
System.arraycopy(outPwd, 0, credBuf, USERSIZ, outPwd.length);
out.write(credBuf, 0, CREDBUFSIZ);
out.flush();
if (in.read(t3IdBuf) < t3IdBuf.length)
{
System.out.println("Read < " + Integer.toString(t3IdBuf.length) + "
bytes");
throw new IOException();
}
inMsg = new String(t3IdBuf, 0, 3, hostCharSet);
if (!inMsg.equals(T3ID))
{
throw new IOException();
}
}
public void sendUrgentData (int oob) throws IOException
{
if (sslReqd)
t3SSLSock.sendUrgentData(oob);
else
t3Sock.sendUrgentData(oob);
}
public void setTimeout(int msecs) throws UnknownHostException, IOException
{
if (sslReqd)
t3SSLSock.setSoTimeout(msecs);
else
t3Sock.setSoTimeout(msecs);
}
public void close () throws IOException
{
if (t3Sock != null && !t3Sock.isClosed())
{
try {t3Sock.close();}
catch (Exception e)
{e.printStackTrace();}
}
if (t3SSLSock != null && !t3SSLSock.isClosed())
{
try {t3SSLSock.close();}
catch (Exception e)
{e.printStackTrace();}
}
}
public void buffMessage (String message) throws IOException
{
byte [] msg = message.getBytes(hostCharSet);
out.write(msg);
}
public void sendMessage (String message) throws IOException
{
byte [] msg = message.getBytes(hostCharSet);
out.write(msg);
flush();
}
public void flush () throws IOException
{
out.flush();
}
public int readMessage () throws IOException
{
return readMessage(readBuf.length);
}
public int readMessage (int bytes) throws IOException
{
try
{
bytesIn = in.read(readBuf, 0, bytes);
}
catch (SocketTimeoutException e)
{
return 0;
}
return bytesIn;
}
public String getString () throws ArrayIndexOutOfBoundsException
{
return getString(0, bytesIn);
}
public String getString (int offset, int length) throws
ArrayIndexOutOfBoundsException
{
if ((offset + length) > bytesIn)
{
throw new ArrayIndexOutOfBoundsException();
}
try
{
stringOut = new String(readBuf, offset, length, hostCharSet);
}
catch (Exception e)
{
return null;
}
return stringOut;
}
}
> > I have created a class that uses the java.net.Socket class to talk to my
> > server and everything is great. I then converted the code to use the
[quoted text clipped - 47 lines]
>
> Arne
Arne Vajhøj - 01 Jul 2007 20:54 GMT
>> Since SSLSocket inherits from Socket then you can make your
>> t3sock of type Socket (you can assign from a subtype to a
[quoted text clipped - 6 lines]
> sockFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
> t3Sock = (SSLSocket)sockFactory.createSocket();
That works fine if t3Sock is declared to have type Socket.
And since all methods are virtual in Java, then if t2Sock is
a SSLSocket, then that class's methods will be used.
> What about all the Value-Added SSL bits that the SSLSocket class must
> bolt-on to a Socket?
[quoted text clipped - 7 lines]
> it's not gonna complain about a bodgy brick-veneer job, absent any
> certificate or crypto-algorithm info?
t3Sock is declared as a Socket, but it it actually is a SSLSocket, then
it can be cast to a SSLSocket and therefore use the SSLSocket
specific methods.
> I'd find it easier to picture it the other way around where we have a
> SSLSocket and our casting it as a Socket effectively masks out all the SSL
> bits, but who cares?
You can not assign a Socket to a SSLSocket, so it has to be this way
around.
>> But that is not "nice".
>
> It's certainly more appealing than the attached code (look for "sslReqd")
True.
Arne
Richard Maher - 02 Jul 2007 02:11 GMT
Thanks Arne. I really appreciate your help!
Cheers Richard Maher
> >> Since SSLSocket inherits from Socket then you can make your
> >> t3sock of type Socket (you can assign from a subtype to a
[quoted text clipped - 42 lines]
>
> Arne
Arne Vajhøj - 01 Jul 2007 23:11 GMT
>> Since SSLSocket inherits from Socket then you can make your
>> t3sock of type Socket (you can assign from a subtype to a
[quoted text clipped - 23 lines]
> bits, but who cares? I'll just code it like you've said and see how I get
> on.
Below are a little standalone console app client-server example.
I know you are in applet environment, but the idea is general.
Look for the hack section.
Arne
============================================================
import java.io.*;
import java.net.*;
import javax.net.ssl.*;
public class MultiServer {
private final static int PORT = 12345;
public static void main(String[] args) throws Exception {
ServerSocket ss;
if(args.length > 0 && args[0].equals("SSL")) {
System.out.println("SSL");
ss =
SSLServerSocketFactory.getDefault().createServerSocket(PORT);
} else {
System.out.println("Non-SSL");
ss = new ServerSocket(PORT);
}
System.out.println("Accepting connection");
Socket s = ss.accept();
System.out.println("Reading");
InputStream is = s.getInputStream();
byte[] b = new byte[10000];
int blen = 0;
int n;
while((n = is.read(b, blen, b.length - blen)) > 0) {
blen += n;
}
System.out.print("Received " + blen + " bytes from client:");
for(int i = 0; i < blen; i++) System.out.print(" " + b[i]);
System.out.println();
System.out.println("Closing");
is.close();
s.close();
ss.close();
}
}
import java.io.*;
import java.net.*;
import java.security.*;
import java.security.cert.*;
import javax.net.ssl.*;
public class MultiClient {
private final static String HOST = "localhost";
private final static int PORT = 12345;
public static void main(String[] args) throws Exception {
Socket s;
if(args.length > 0 && args[0].equals("SSL")) {
System.out.println("Connecting via SSL");
SSLContext sslctx = SSLContext.getInstance("SSL");
sslctx.init(null, new X509TrustManager[] { new
MyTrustManager() }, null);
SSLSocketFactory sf = sslctx.getSocketFactory();
s = sf.createSocket(new Socket(HOST, PORT), HOST, PORT, true);
} else {
System.out.println("Connecting plain");
s = new Socket(HOST, PORT);
}
// hack
if(s instanceof SSLSocket) {
SSLSession ses = ((SSLSocket)s).getSession();
System.out.println("Server: " + ses.getPeerPrincipal());
}
System.out.println("Sending 1 2 3 to server");
OutputStream os = s.getOutputStream();
byte[] b = { 1, 2, 3 };
os.write(b);
System.out.println("Closing");
os.close();
s.close();
}
}
class MyTrustManager implements X509TrustManager
{
public void checkClientTrusted(X509Certificate[] chain, String
authType) {
}
public void checkServerTrusted(X509Certificate[] chain, String
authType) {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
C:\>java MultiServer
Non-SSL
Accepting connection
Reading
Received 3 bytes from client: 1 2 3
Closing
C:\>java -Djavax.net.ssl.keyStore=server.jks
-Djavax.net.ssl.keyStorePassword=superhemmeligt MultiServer SSL
SSL
Accepting connection
Reading
Received 3 bytes from client: 1 2 3
Closing
C:\>java MultiClient
Connecting plain
Sending 1 2 3 to server
Closing
C:\>java MultiClient SSL
Connecting via SSL
Server: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
Sending 1 2 3 to server
Closing
Arne