From d48bd6e50ee09d1649a7680d7943510d274b5c91 Mon Sep 17 00:00:00 2001 From: megacz Date: Fri, 30 Jan 2004 06:45:17 +0000 Subject: [PATCH] 2002/03/27 20:13:44 darcs-hash:20040130064517-2ba56-d9ad719817bef2d2efe96d030caaaab27248e8ae.gz --- src/org/xwt/TinySSL.java | 70 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/src/org/xwt/TinySSL.java b/src/org/xwt/TinySSL.java index 3d38660..516fee6 100644 --- a/src/org/xwt/TinySSL.java +++ b/src/org/xwt/TinySSL.java @@ -73,9 +73,14 @@ import java.text.*; dev-crypto mailing list while I was writing this. Revision History: + 1.0 07-Dec-01 Initial Release + 1.01 15-Mar-02 Added PKCS1 class to avoid dependancy on java.security.SecureRandom + 1.02 27-Mar-02 Fixed a bug which would hang the connection when more than one + Handshake message appeared in the same TLS Record + */ public class TinySSL extends Socket { @@ -85,7 +90,7 @@ public class TinySSL extends Socket { public static void main(String[] args) { Log.on = true; try { - Socket s = new TinySSL("www.paypal.com", 443); + Socket s = new TinySSL("www.verisign.com", 443); PrintWriter pw = new PrintWriter(s.getOutputStream()); BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); pw.println("GET / HTTP/1.0"); @@ -190,7 +195,7 @@ public class TinySSL extends Socket { public int read(byte[] b, int off, int len) throws IOException { if (pendlen == 0) { - pend = readRecord(false); + pend = readRecord(); if (pend == null) return -1; pendstart = 0; pendlen = pend.length; @@ -203,13 +208,17 @@ public class TinySSL extends Socket { } /** reads and decrypts exactly one record; blocks if unavailable */ - public byte[] readRecord(boolean returnHandshakes) throws IOException { + public byte[] readRecord() throws IOException { // we only catch EOFException here, because anywhere else // would be "unusual", and we *want* and EOFException in // those cases byte type; - try { type = raw.readByte(); } catch (EOFException e) { return null; } + try { type = raw.readByte(); + } catch (EOFException e) { + if (Log.on) Log.log(this, "got EOFException reading packet type"); + return null; + } byte ver_major = raw.readByte(); byte ver_minor = raw.readByte(); @@ -220,7 +229,11 @@ public class TinySSL extends Socket { raw.readFully(ret); // simply ignore ChangeCipherSpec messages -- we change as soon as we send ours - if (type == 20) { seq_num = 0; return readRecord(returnHandshakes); } + if (type == 20) { + if (Log.on) Log.log(this, "got ChangeCipherSpec; ignoring"); + seq_num = 0; + return readRecord(); + } byte[] decrypted_payload; @@ -241,35 +254,53 @@ public class TinySSL extends Socket { } if (type == 21) { - if (decrypted_payload[1] != 0) + if (decrypted_payload[1] > 1) { throw new SSLException("got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]); - return null; + } else if (decrypted_payload[1] == 0) { + if (Log.on) Log.log(this, "server requested connection closure; returning null"); + return null; + } else { + if (Log.on) Log.log(this, "got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]); + return readRecord(); + } } else if (type == 22) { - if (!returnHandshakes) { - if (Log.on) Log.log(this, "after completion of handshake, server sent another handshake message!"); - return readRecord(false); - } + if (Log.on) Log.log(this, "read a handshake"); } else if (type != 23) { if (Log.on) Log.log(this, "unexpected record type: " + type + "; skipping"); - return readRecord(returnHandshakes); + return readRecord(); } if (Log.on) Log.log(this, " returning " + decrypted_payload.length + " byte record payload"); return decrypted_payload; } - + + private byte[] readHandshake() throws IOException { + // acquire a handshake message + byte type = (byte)read(); + int len = ((read() & 0xff) << 16) | ((read() & 0xff) << 8) | (read() & 0xff); + byte[] rec = new byte[len + 4]; + rec[0] = type; + rec[1] = (byte)(((len & 0x00ff0000) >> 16) & 0xff); + rec[2] = (byte)(((len & 0x0000ff00) >> 8) & 0xff); + rec[3] = (byte)((len & 0x000000ff) & 0xff); + if (len > 0) read(rec, 4, len); + return rec; + } + /** This reads the ServerHello, Certificate, and ServerHelloDone handshake messages */ public void readServerHandshakes() throws IOException { for(;;) { - byte[] rec = readRecord(true); + + byte[] rec = readHandshake(); handshakes = concat(new byte[][] { handshakes, rec }); DataInputStream stream = new DataInputStream(new ByteArrayInputStream(rec, 4, rec.length - 4)); switch(rec[0]) { case 2: // ServerHello + if (Log.on) Log.log(this, "got ServerHello"); byte ver_major = rec[4]; byte ver_minor = rec[5]; System.arraycopy(rec, 6, server_random, 0, server_random.length); @@ -294,6 +325,7 @@ public class TinySSL extends Socket { break; case 11: // Server's certificate(s) + if (Log.on) Log.log(this, "got Server Certificate(s)"); int numcertbytes = ((rec[4] & 0xff) << 16) | ((rec[5] & 0xff) << 8) | (rec[6] & 0xff); int numcerts = 0; X509CertificateStructure last_cert = null; @@ -369,10 +401,15 @@ public class TinySSL extends Socket { break; case 12: + if (Log.on) Log.log(this, "got ServerKeyExchange"); serverKeyExchange = rec; break; - case 13: cert_requested = true; break; + case 13: + if (Log.on) Log.log(this, "got Request for Client Certificates"); + cert_requested = true; + break; + case 14: if (Log.on) Log.log(this, " ServerHelloDone"); return; default: throw new SSLException("unknown handshake of type " + rec[0]); } @@ -380,7 +417,8 @@ public class TinySSL extends Socket { } public void readServerFinished() throws IOException { - byte[] rec = readRecord(true); + + byte[] rec = readHandshake(); if (rec[0] != 20) throw new SSLException("expecting server Finished message, but got message of type " + rec[0]); byte[] expectedFinished = concat(new byte[][] { -- 1.7.10.4