javax.net.ssl Sockets and OKing self-signed certificates

R

Richard Maher

Hi,

I would dearly love a server with a "self-signed certificate" to be
accessible by my javax.net.ssl.startHandshake() but it seems to consistently
crap-out with a failure :-( Look I've only ever tested the client code
(please see below) with a https server (just to see if everything was
kosher) and it maybe something I'm doing wrong. I just couldn't find
anything in the handshake listener that controlled self-cert.

So, is my code crap? or is there a bit I need to toggle to get the behaviour
I require?

Please help if you can.

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 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)
t3Sock = (SSLSocket)sockFactory.createSocket();
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);

if (sslReqd)
{
((SSLSocket)t3Sock).setUseClientMode(true);

try {((SSLSocket)t3Sock).startHandshake();}
catch (IOException e)
{
System.out.println("Failed SSL Handshake");
throw new IOException("Can't SSL on Socket");
}
}
}

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
{
t3Sock.sendUrgentData(oob);
}

public void setTimeout(int msecs) throws UnknownHostException, IOException
{
t3Sock.setSoTimeout(msecs);
}

public void close () throws IOException
{
if (t3Sock != null && !t3Sock.isClosed())
{
try {t3Sock.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;
}

}
 
R

Rogan Dawes

Richard said:
Hi,

I would dearly love a server with a "self-signed certificate" to be
accessible by my javax.net.ssl.startHandshake() but it seems to consistently
crap-out with a failure :-( Look I've only ever tested the client code
(please see below) with a https server (just to see if everything was
kosher) and it maybe something I'm doing wrong. I just couldn't find
anything in the handshake listener that controlled self-cert.

So, is my code crap? or is there a bit I need to toggle to get the behaviour
I require?

Please help if you can.

Cheers Richard Maher

[snip code]

Take a look at http://dawes.za.net/rogan/PKCS11Test.java

While it refers to PKCS#11 in the name, it also includes a number of
techniques necessary to deal with your question too.

In particular, see the method configureHTTPSUrlConnection where I create
a new X509TrustManager.

Hope this helps.

Rogan
 
R

Richard Maher

Hi Rogan,

Rogan Dawes said:
Richard said:
Hi,

I would dearly love a server with a "self-signed certificate" to be
accessible by my javax.net.ssl.startHandshake() but it seems to consistently
crap-out with a failure :-( Look I've only ever tested the client code
(please see below) with a https server (just to see if everything was
kosher) and it maybe something I'm doing wrong. I just couldn't find
anything in the handshake listener that controlled self-cert.

So, is my code crap? or is there a bit I need to toggle to get the behaviour
I require?

Please help if you can.

Cheers Richard Maher

[snip code]

Take a look at http://dawes.za.net/rogan/PKCS11Test.java

While it refers to PKCS#11 in the name, it also includes a number of
techniques necessary to deal with your question too.

In particular, see the method configureHTTPSUrlConnection where I create
a new X509TrustManager.

Hope this helps.

Rogan

Thanks for the reply.

It looks like your new trust manager just lets everything through. Is there
a way to trap which connections are fully-certified and which are
self-certifying?

Cheers Richard Maher
 
R

Rogan Dawes

Richard said:
Hi Rogan,
[snip code]

Take a look at http://dawes.za.net/rogan/PKCS11Test.java

While it refers to PKCS#11 in the name, it also includes a number of
techniques necessary to deal with your question too.

In particular, see the method configureHTTPSUrlConnection where I create
a new X509TrustManager.

Hope this helps.

Rogan

Thanks for the reply.

It looks like your new trust manager just lets everything through. Is there
a way to trap which connections are fully-certified and which are
self-certifying?

Cheers Richard Maher

Well, you need to decide what your rules are, and implement a suitable
TrustManager. The typical way to approach this is:

a) Add the certificate of the self-signer to your JRE trust store, and
allow the default TrustManager to check against that cert. That would
allow connections from that particular self-signer to pass.

b) Create your own TrustManager that checks to see whether your rules
apply, and return cleanly, otherwise throwing an exception. (I forget
what the correct exception is, the JavaDoc is your friend :) )

Hope this helped.

Rogan
 
R

Richard Maher

Thanks.

Rogan Dawes said:
Richard said:
Hi Rogan,
[snip code]

Take a look at http://dawes.za.net/rogan/PKCS11Test.java

While it refers to PKCS#11 in the name, it also includes a number of
techniques necessary to deal with your question too.

In particular, see the method configureHTTPSUrlConnection where I create
a new X509TrustManager.

Hope this helps.

Rogan

Thanks for the reply.

It looks like your new trust manager just lets everything through. Is there
a way to trap which connections are fully-certified and which are
self-certifying?

Cheers Richard Maher

Well, you need to decide what your rules are, and implement a suitable
TrustManager. The typical way to approach this is:

a) Add the certificate of the self-signer to your JRE trust store, and
allow the default TrustManager to check against that cert. That would
allow connections from that particular self-signer to pass.

b) Create your own TrustManager that checks to see whether your rules
apply, and return cleanly, otherwise throwing an exception. (I forget
what the correct exception is, the JavaDoc is your friend :) )

Hope this helped.

Rogan
 
R

Rogan Dawes

Richard said:
Hi Rogan,


I've used the following command in an attempt to register the register the
self-signing server in my client's JRE Trust Store: -

keytool -import -alias gein.vistech.net -trustcacerts -file d:\temp\gein.cer

But am still having no joy with the code that I previously posted :-(

I can't say my code is perfect but it does work connecting to a https server
(at least for the handshake). Any ideas?

Cheers Richard Maher

PS. Here is the trace: -

Trace level set to 5: all ... completed.
liveconnect: Invoking JS method: document
liveconnect: Invoking JS method: URL

Urk! Applets!

Sorry, I have no clue about applets.

Rogan
 
R

Richard Maher

Hi Rogan,
Sorry, I have no clue about applets.

You don't know what you're missing - They're the Mutt's Nuts!

In ended up (thanks to the inestigative efforst of my brilliant friend
Graham Burley) to be as simple as specifying the correct default Truststore
location on the Keytool command line as in: -

keytool -importcert -alias gein -file d:\temp\gein.cer -keystore
...\lib\security\cacerts

Now the code in the OP works as advertised. Thanks for your help.

Cheers Richard Maher
 
R

Roedy Green

In ended up (thanks to the inestigative efforst of my brilliant friend
Graham Burley) to be as simple as specifying the correct default Truststore
location on the Keytool command line as in: -

keytool -importcert -alias gein -file d:\temp\gein.cer -keystore
..\lib\security\cacerts

By that di you mean adding -keystore ..\lib\security\cacerts ??
If you leave it off, keytool puts certs in .keystore.

See http://mindprod.com/jgloss/cacerts.html
http://mindprod.com/jgloss/keystore.html
http://mindprod.com/jgloss/keytool.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top