X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2FTinySSL.java;h=abb5561b2c15c5b2657e617c579931f8920835db;hb=6a96430e10e27fc1de5754cb5add705f929dd109;hp=44b998c6dc41bbeb0c0873b461a9fe9b30dd6956;hpb=ce478ac0d941574e9165a09a00c95a5930fa7838;p=org.ibex.core.git diff --git a/src/org/xwt/TinySSL.java b/src/org/xwt/TinySSL.java index 44b998c..abb5561 100644 --- a/src/org/xwt/TinySSL.java +++ b/src/org/xwt/TinySSL.java @@ -1,4 +1,4 @@ -// Copyright (C) 2001 Adam Megacz all rights reserved. +// Copyright (C) 2002 Adam Megacz all rights reserved. // // You may modify, copy, and redistribute this code under the terms of // the GNU Library Public License version 2.1, with the exception of @@ -31,6 +31,9 @@ import org.bouncycastle.asn1.x509.RSAPublicKeyStructure; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.TBSCertificateStructure; import org.bouncycastle.asn1.x509.X509Name; +import org.bouncycastle.asn1.x509.X509Extensions; +import org.bouncycastle.asn1.x509.X509Extension; +import org.bouncycastle.asn1.x509.BasicConstraints; import org.xwt.util.Log; import java.net.*; import java.io.*; @@ -81,6 +84,9 @@ import java.text.*; 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 + 1.03 10-Aug-02 Fixed a vulnerability outlined at + http://online.securityfocus.com/archive/1/286290 + */ public class TinySSL extends Socket { @@ -90,7 +96,7 @@ public class TinySSL extends Socket { public static void main(String[] args) { Log.on = true; try { - Socket s = new TinySSL("www.verisign.com", 443); + Socket s = new TinySSL("www.paypal.com", 443); PrintWriter pw = new PrintWriter(s.getOutputStream()); BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); pw.println("GET / HTTP/1.0"); @@ -100,7 +106,7 @@ public class TinySSL extends Socket { while(true) { String s2 = br.readLine(); if (s2 == null) return; - System.out.println(s2); + Log.log(TinySSL.class, s2); } } catch (Exception e) { @@ -112,6 +118,7 @@ public class TinySSL extends Socket { public static class SSLException extends IOException { public SSLException(String s) { super(s); } } static SubjectPublicKeyInfo[] trusted_CA_public_keys; + static String[] trusted_CA_public_key_identifiers; public static byte[] pad1 = new byte[48]; public static byte[] pad2 = new byte[48]; public static byte[] pad1_sha = new byte[40]; @@ -142,6 +149,9 @@ public class TinySSL extends Socket { String hostname; + /** if true, we don't mind if the server's cert isn't signed by a CA. USE WITH CAUTION! */ + boolean ignoreUntrustedCert = false; + /** the concatenation of all the bytes of all handshake messages sent or recieved */ public byte[] handshakes = new byte[] { }; @@ -151,10 +161,12 @@ public class TinySSL extends Socket { public InputStream getInputStream() throws IOException { return is != null ? is : super.getInputStream(); } public OutputStream getOutputStream() throws IOException { return os != null ? os : super.getOutputStream(); } - public TinySSL(String host, int port) throws IOException { this(host, port, true); } - public TinySSL(String host, int port, boolean negotiateImmediately) throws IOException { + public TinySSL(String host, int port) throws IOException { this(host, port, true, false); } + public TinySSL(String host, int port, boolean negotiateImmediately) throws IOException { this(host, port, negotiateImmediately, false); } + public TinySSL(String host, int port, boolean negotiateImmediately, boolean ignoreUntrustedCert) throws IOException { super(host, port); hostname = host; + this.ignoreUntrustedCert = ignoreUntrustedCert; if (negotiateImmediately) negotiate(); } @@ -363,7 +375,7 @@ public class TinySSL extends Socket { } if (!good) throw new SSLException("server certificate does not seem to have a CN: " + CN); - if (!CN.equals(hostname)) + if (!ignoreUntrustedCert && !CN.equals(hostname)) throw new SSLException("connecting to host " + hostname + " but server certificate was issued for " + CN); SimpleDateFormat dateF = new SimpleDateFormat("MM-dd-yy-HH-mm-ss-z"); @@ -380,13 +392,28 @@ public class TinySSL extends Socket { Date endDate = dateF.parse(s, new ParsePosition(0)); Date now = new Date(); - if (now.after(endDate)) throw new SSLException("server certificate expired on " + endDate); - if (now.before(startDate)) throw new SSLException("server certificate will not be valid until " + startDate); + if (!ignoreUntrustedCert && now.after(endDate)) + throw new SSLException("server certificate expired on " + endDate); + if (!ignoreUntrustedCert && now.before(startDate)) + throw new SSLException("server certificate will not be valid until " + startDate); Log.log(this, "server cert (name, validity dates) checks out okay"); - } else if (!isSignedBy(last_cert, this_cert.getSubjectPublicKeyInfo())) - throw new SSLException("certificate chain discontinuity"); + } else { + + // don't check the top cert since some very old root certs lack a BasicConstraints field. + if (certlen + 3 + i < numcertbytes) { + // defend against Mike Benham's attack + X509Extension basicConstraints = this_cert.getTBSCertificate().getExtensions().getExtension(X509Extensions.BasicConstraints); + if (basicConstraints == null) throw new SSLException("certificate did not contain a basic constraints block"); + DERInputStream dis = new DERInputStream(new ByteArrayInputStream(basicConstraints.getValue().getOctets())); + BasicConstraints bc = new BasicConstraints((DERConstructedSequence)dis.readObject()); + if (!bc.isCA()) throw new SSLException("non-CA certificate used for signing"); + } + + if (!isSignedBy(last_cert, this_cert.getSubjectPublicKeyInfo())) + throw new SSLException("the server sent a broken chain of certificates"); + } last_cert = this_cert; i += certlen + 3; @@ -394,14 +421,30 @@ public class TinySSL extends Socket { } if (Log.on) Log.log(this, " Certificate (" + numcerts + " certificates)"); + if (ignoreUntrustedCert) break; + boolean good = false; + + // pass 1 -- only check CA's whose subject is a partial match + String subject = this_cert.getSubject().toString(); for(int i=0; i