directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dran...@apache.org
Subject [18/36] directory-kerby git commit: Moved the source codes of not-so-commons-ssl into kerby-pkix module and cleaned up accordingly
Date Sun, 13 Dec 2015 02:02:09 GMT
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/3rdparty/not-yet-commons-ssl/src/test/resources/x509/x509_wild_foo_bar_hanako.pem
----------------------------------------------------------------------
diff --git a/3rdparty/not-yet-commons-ssl/src/test/resources/x509/x509_wild_foo_bar_hanako.pem b/3rdparty/not-yet-commons-ssl/src/test/resources/x509/x509_wild_foo_bar_hanako.pem
deleted file mode 100644
index 2c751b7..0000000
--- a/3rdparty/not-yet-commons-ssl/src/test/resources/x509/x509_wild_foo_bar_hanako.pem
+++ /dev/null
@@ -1,88 +0,0 @@
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number:
-            8c:fe:11:83:01:53:a6:96
-        Signature Algorithm: sha1WithRSAEncryption
-        Issuer: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_intermediate_ca/emailAddress=juliusdavies@gmail.com
-        Validity
-            Not Before: Dec 11 16:17:31 2006 GMT
-            Not After : Nov  5 16:17:31 2028 GMT
-        Subject: C=US, ST=Maryland, L=Forest Hill, O=httpcomponents, OU=test certificates, CN=*.foo.com/emailAddress=juliusdavies@gmail.com
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-            RSA Public Key: (2048 bit)
-                Modulus (2048 bit):
-                    00:c8:63:af:96:82:3e:8c:a9:d1:1d:62:ae:85:80:
-                    7e:71:32:04:c1:98:5a:80:a2:74:7f:7a:c8:63:c5:
-                    8d:82:e8:c1:ec:f9:69:82:98:d4:83:8a:4d:8d:81:
-                    95:88:68:e0:ef:38:5f:6e:38:42:b6:53:46:5f:24:
-                    41:b6:2d:c6:71:a1:e2:04:82:0f:e6:7c:82:36:7f:
-                    80:cb:cb:52:58:6a:39:bf:96:5c:f0:14:1c:c0:77:
-                    f4:64:72:cd:ea:c0:fd:9b:6b:95:4a:9f:fa:52:a8:
-                    d2:e5:9c:a1:cc:5e:45:ce:fb:d4:a3:7c:70:f1:f7:
-                    9c:76:74:ad:5d:07:c7:86:40:67:2e:94:e3:1c:4e:
-                    6d:ee:2b:b5:25:58:d3:b8:4d:29:70:1b:da:87:67:
-                    56:a8:33:71:88:83:90:b5:7c:8a:5b:c4:9a:83:56:
-                    31:6a:e9:f1:40:6a:91:37:29:12:16:21:09:8a:77:
-                    71:39:20:27:03:12:ba:ab:fc:06:a9:c6:77:ce:f1:
-                    41:4d:c5:55:92:38:b5:bb:64:07:e2:b3:8c:3f:73:
-                    cf:c4:02:0c:90:1f:0e:36:47:47:4d:ca:35:0e:66:
-                    c4:e8:17:c3:1c:0a:c3:a9:46:31:a8:95:25:3c:69:
-                    4c:aa:b2:9b:dd:f0:85:89:3d:de:5d:e8:70:47:b9:
-                    e5:cd
-                Exponent: 65537 (0x10001)
-        X509v3 extensions:
-            X509v3 Basic Constraints: 
-                CA:FALSE
-            Netscape Comment: 
-                OpenSSL Generated Certificate
-            X509v3 Subject Key Identifier: 
-                9F:14:77:BF:3F:3A:B6:CA:38:82:42:48:16:2C:DA:D0:CB:5E:87:D8
-            X509v3 Authority Key Identifier: 
-                keyid:7B:9A:DA:8F:90:99:4E:52:D2:AC:DB:B3:03:52:CA:87:A6:0D:3E:0D
-
-            X509v3 Subject Alternative Name: 
-                DNS:*.bar.com, DNS:*.花子.co.jp
-    Signature Algorithm: sha1WithRSAEncryption
-        68:6d:60:be:0f:9f:e5:c7:a6:21:5f:ae:02:c1:9d:ba:5c:b8:
-        f1:68:4d:12:e3:5e:5a:8d:b0:6a:0c:ae:e5:cf:e4:60:ef:33:
-        84:dc:6b:13:00:c8:be:95:d5:18:9e:1c:b3:d3:00:e2:5c:1f:
-        14:c0:a5:e5:d1:20:d3:a0:1d:99:e0:63:a0:a9:08:c0:aa:83:
-        26:ac:fd:2e:58:1e:98:e9:da:64:7d:dd:6a:0d:15:33:23:5d:
-        b4:cc:f6:20:49:db:17:8c:75:bd:ab:61:fb:ee:25:76:df:c8:
-        6a:21:4e:ea:0a:f1:33:fa:57:ea:a9:61:18:e7:4e:33:85:83:
-        65:92:76:d4:9d:1e:76:e4:8b:68:b0:45:70:5c:50:49:4e:46:
-        77:63:0f:20:83:4d:9c:d7:dc:a2:f1:30:21:e4:b8:b7:01:df:
-        17:42:69:92:24:c5:81:57:85:ca:a8:5a:f4:00:86:4a:06:58:
-        3a:35:96:45:7f:fd:1d:3f:dc:dc:2a:1c:d2:ae:25:b6:ed:b6:
-        34:5d:fc:c0:e8:64:a2:44:35:eb:0e:38:17:ab:a6:da:45:3e:
-        98:c2:02:20:a6:02:6c:0d:b2:6d:65:f1:e7:57:59:dd:dc:ce:
-        b3:3a:d4:0f:9b:54:c8:42:93:66:30:c3:1d:fc:33:eb:19:c5:
-        10:7a:b0:f7
------BEGIN CERTIFICATE-----
-MIIEcDCCA1igAwIBAgIJAIz+EYMBU6aWMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
-VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
-ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
-FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
-ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTczMVoXDTI4MTEwNTE2MTczMVowgaYx
-CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0
-IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl
-cnRpZmljYXRlczESMBAGA1UEAxQJKi5mb28uY29tMSUwIwYJKoZIhvcNAQkBFhZq
-dWxpdXNkYXZpZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjUg4pN
-jYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQcwHf0
-ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t7iu1
-JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAnAxK6
-q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArDqUYx
-qJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABo4GiMIGfMAkGA1UdEwQCMAAwLAYJ
-YIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1Ud
-DgQWBBSfFHe/Pzq2yjiCQkgWLNrQy16H2DAfBgNVHSMEGDAWgBR7mtqPkJlOUtKs
-27MDUsqHpg0+DTAkBgNVHREEHTAbggkqLmJhci5jb22CDiou6Iqx5a2QLmNvLmpw
-MA0GCSqGSIb3DQEBBQUAA4IBAQBobWC+D5/lx6YhX64CwZ26XLjxaE0S415ajbBq
-DK7lz+Rg7zOE3GsTAMi+ldUYnhyz0wDiXB8UwKXl0SDToB2Z4GOgqQjAqoMmrP0u
-WB6Y6dpkfd1qDRUzI120zPYgSdsXjHW9q2H77iV238hqIU7qCvEz+lfqqWEY504z
-hYNlknbUnR525ItosEVwXFBJTkZ3Yw8gg02c19yi8TAh5Li3Ad8XQmmSJMWBV4XK
-qFr0AIZKBlg6NZZFf/0dP9zcKhzSriW27bY0XfzA6GSiRDXrDjgXq6baRT6YwgIg
-pgJsDbJtZfHnV1nd3M6zOtQPm1TIQpNmMMMd/DPrGcUQerD3
------END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/3rdparty/not-yet-commons-ssl/version.txt
----------------------------------------------------------------------
diff --git a/3rdparty/not-yet-commons-ssl/version.txt b/3rdparty/not-yet-commons-ssl/version.txt
deleted file mode 100644
index d8913dd..0000000
--- a/3rdparty/not-yet-commons-ssl/version.txt
+++ /dev/null
@@ -1 +0,0 @@
-$URL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.16/version.txt $

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/3rdparty/pom.xml
----------------------------------------------------------------------
diff --git a/3rdparty/pom.xml b/3rdparty/pom.xml
deleted file mode 100644
index 80007cb..0000000
--- a/3rdparty/pom.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License. See accompanying LICENSE file.
--->
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <groupId>org.apache.kerby</groupId>
-    <artifactId>kerby-all</artifactId>
-    <version>1.0.0-RC2-SNAPSHOT</version>
-  </parent>
-
-  <artifactId>3rdparty</artifactId>
-  <name>Third Party Projects</name>
-  <description>Third Party Projects</description>
-  <packaging>pom</packaging>
-
-  <modules>
-    <module>not-yet-commons-ssl</module>
-  </modules>
-
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>${junit.version}</version>
-    </dependency>
-  </dependencies>
-
-  <profiles>
-    <profile>
-      <id>nochecks</id>
-      <activation>
-        <activeByDefault>true</activeByDefault>
-      </activation>
-      <properties>
-        <pmd.skip>true</pmd.skip>
-      </properties>
-    </profile>
-  </profiles>
-
-
-</project>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/kerby-pkix/README.txt
----------------------------------------------------------------------
diff --git a/kerby-pkix/README.txt b/kerby-pkix/README.txt
new file mode 100644
index 0000000..2db185a
--- /dev/null
+++ b/kerby-pkix/README.txt
@@ -0,0 +1,2 @@
+Part of codes of this module is adapted from not-yet-commons-ssl library,
+with much simplified, only focusing on PKI related and removing away the SSL stuffs.

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/kerby-pkix/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-pkix/pom.xml b/kerby-pkix/pom.xml
index 3c3d5be..e53c6b8 100644
--- a/kerby-pkix/pom.xml
+++ b/kerby-pkix/pom.xml
@@ -32,6 +32,27 @@
       <artifactId>kerby-asn1</artifactId>
       <version>${project.version}</version>
     </dependency>
+
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-util</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcprov-ext-jdk15on</artifactId>
+      <version>1.52</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <version>1.9.5</version>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/kerby-pkix/src/main/java/org/apache/commons/ssl/Asn1PkcsStructure.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/Asn1PkcsStructure.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/Asn1PkcsStructure.java
new file mode 100644
index 0000000..5e5122f
--- /dev/null
+++ b/kerby-pkix/src/main/java/org/apache/commons/ssl/Asn1PkcsStructure.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.apache.kerby.asn1.type.Asn1Integer;
+import org.apache.kerby.util.Hex;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
+ * @since 16-Nov-2005
+ */
+
+/**
+ * Adapted from not-yet-commons-ssl ASN1Structure
+ */
+class Asn1PkcsStructure {
+    List<Asn1Integer> derIntegers = new LinkedList<Asn1Integer>();
+    Set oids = new TreeSet();
+    String oid1;
+    String oid2;
+    String oid3;
+    byte[] salt;
+    byte[] iv;
+    int iterationCount;
+    int keySize;
+    byte[] bigPayload;
+    byte[] smallPayload;
+
+    public String toString() {
+        StringBuffer buf = new StringBuffer(256);
+        buf.append("------ ASN.1 PKCS Structure ------");
+        buf.append("\noid1:    ");
+        buf.append(oid1);
+        if (oid2 != null) {
+            buf.append("\noid2:    ");
+            buf.append(oid2);
+        }
+        buf.append("\nsalt:   ");
+        if (salt != null) {
+            buf.append(Hex.encode(salt));
+        } else {
+            buf.append("[null]");
+        }
+        buf.append("\nic:      ");
+        buf.append(Integer.toString(iterationCount));
+        if (keySize != 0) {
+            buf.append("\nkeySize: ");
+            buf.append(Integer.toString(keySize * 8));
+        }
+        if (oid2 != null) {
+            buf.append("\noid3:    ");
+            buf.append(oid3);
+        }
+        if (oid2 != null) {
+            buf.append("\niv:      ");
+            if (iv != null) {
+                buf.append(Hex.encode(iv));
+            } else {
+                buf.append("[null]");
+            }
+        }
+        if (bigPayload != null) {
+            buf.append("\nbigPayload-length:   ");
+            buf.append(bigPayload.length);
+        }
+        if (smallPayload != null) {
+            buf.append("\nsmallPayload-length: ");
+            buf.append(smallPayload.length);
+        }
+        if (!oids.isEmpty()) {
+            Iterator it = oids.iterator();
+            buf.append("\nAll oids:");
+            while (it.hasNext()) {
+                buf.append("\n");
+                buf.append((String) it.next());
+            }
+        }
+        return buf.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/kerby-pkix/src/main/java/org/apache/commons/ssl/Asn1PkcsUtil.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/Asn1PkcsUtil.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/Asn1PkcsUtil.java
new file mode 100644
index 0000000..d4b0464
--- /dev/null
+++ b/kerby-pkix/src/main/java/org/apache/commons/ssl/Asn1PkcsUtil.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.apache.kerby.asn1.Asn1;
+import org.apache.kerby.asn1.type.Asn1Collection;
+import org.apache.kerby.asn1.type.Asn1Encodeable;
+import org.apache.kerby.asn1.type.Asn1Integer;
+import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
+import org.apache.kerby.asn1.type.Asn1OctetString;
+import org.apache.kerby.asn1.type.Asn1Type;
+import org.apache.kerby.util.Hex;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.List;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
+ * @since 16-Nov-2005
+ */
+
+/**
+ * Adapted from ASN1Util in not-yet-commons-ssl
+ */
+public class Asn1PkcsUtil {
+
+    public static final BigInteger BIGGEST =
+            new BigInteger(Integer.toString(Integer.MAX_VALUE));
+
+    public static Asn1PkcsStructure analyze(byte[] asn1)
+            throws IOException {
+
+        Asn1.dump(asn1, true);
+        Asn1Type aObj = Asn1.decode(asn1);
+        Asn1.dump(aObj);
+
+        Asn1PkcsStructure pkcs8 = new Asn1PkcsStructure();
+        if (aObj instanceof Asn1Collection) {
+            Asn1PkcsUtil.analyze(((Asn1Collection) aObj), pkcs8, 0);
+        } else {
+            Asn1PkcsUtil.analyze(aObj, pkcs8, 0);
+        }
+
+        return pkcs8;
+    }
+
+    public static void analyze(Asn1Collection asn1Coll,
+                               Asn1PkcsStructure pkcs8, int depth) {
+        if (depth >= 2) {
+            pkcs8.derIntegers = null;
+        }
+
+        List<Asn1Type> items = asn1Coll.getValue();
+        for (Asn1Type item : items) {
+            Asn1Encodeable aObj = (Asn1Encodeable) item;
+            if (!aObj.isCollection()) {
+                analyze(item, pkcs8, depth);
+            } else {
+                analyze((Asn1Collection) aObj, pkcs8, depth + 1);
+            }
+        }
+    }
+
+    public static void analyze(Asn1Type obj,
+                               Asn1PkcsStructure pkcs8, int depth) {
+
+        String tag = null;
+        if (depth >= 2) {
+            pkcs8.derIntegers = null;
+        }
+
+        String str = obj.toString();
+        String name = obj.getClass().getName();
+        name = name.substring(name.lastIndexOf('.') + 1);
+        if (tag != null) {
+            name = " [tag=" + tag + "] " + name;
+        }
+        for (int i = 0; i < depth; i++) {
+            name = "  " + name;
+        }
+
+        if (obj instanceof Asn1Integer) {
+            Asn1Integer dInt = (Asn1Integer) obj;
+            if (pkcs8.derIntegers != null) {
+                pkcs8.derIntegers.add(dInt);
+            }
+            BigInteger big = dInt.getValue();
+            int intValue = big.intValue();
+            if (BIGGEST.compareTo(big) >= 0 && intValue > 0) {
+                if (pkcs8.iterationCount == 0) {
+                    pkcs8.iterationCount = intValue;
+                } else if (pkcs8.keySize == 0) {
+                    pkcs8.keySize = intValue;
+                }
+            }
+        } else if (obj instanceof Asn1ObjectIdentifier) {
+            Asn1ObjectIdentifier id = (Asn1ObjectIdentifier) obj;
+            str = id.getValue();
+            pkcs8.oids.add(str);
+            if (pkcs8.oid1 == null) {
+                pkcs8.oid1 = str;
+            } else if (pkcs8.oid2 == null) {
+                pkcs8.oid2 = str;
+            } else if (pkcs8.oid3 == null) {
+                pkcs8.oid3 = str;
+            }
+        } else {
+            pkcs8.derIntegers = null;
+            if (obj instanceof Asn1OctetString) {
+                Asn1OctetString oct = (Asn1OctetString) obj;
+                byte[] octets = oct.getValue();
+                int len = Math.min(10, octets.length);
+                boolean probablyBinary = false;
+                for (int i = 0; i < len; i++) {
+                    byte b = octets[i];
+                    boolean isBinary = b > 128 || b < 0;
+                    if (isBinary) {
+                        probablyBinary = true;
+                        break;
+                    }
+                }
+                if (probablyBinary && octets.length > 64) {
+                    if (pkcs8.bigPayload == null) {
+                        pkcs8.bigPayload = octets;
+                    }
+                } else {
+                    str = Hex.encode(octets);
+                    if (octets.length <= 64) {
+                        if (octets.length % 8 == 0) {
+                            if (pkcs8.salt == null) {
+                                pkcs8.salt = octets;
+                            } else if (pkcs8.iv == null) {
+                                pkcs8.iv = octets;
+                            }
+                        } else {
+                            if (pkcs8.smallPayload == null) {
+                                pkcs8.smallPayload = octets;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        FileInputStream in = new FileInputStream(args[0]);
+        byte[] bytes = Util.streamToBytes(in);
+        List list = PEMUtil.decode(bytes);
+        if (!list.isEmpty()) {
+            bytes = ((PEMItem) list.get(0)).getDerBytes();
+        }
+
+        Asn1PkcsStructure asn1 = analyze(bytes);
+        while (asn1.bigPayload != null) {
+            System.out.println("------------------------------------------");
+            System.out.println(asn1);
+            System.out.println("------------------------------------------");
+            asn1 = analyze(asn1.bigPayload);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/kerby-pkix/src/main/java/org/apache/commons/ssl/CRLSocket.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/CRLSocket.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/CRLSocket.java
new file mode 100644
index 0000000..473a7e2
--- /dev/null
+++ b/kerby-pkix/src/main/java/org/apache/commons/ssl/CRLSocket.java
@@ -0,0 +1,98 @@
+package org.apache.commons.ssl;
+
+import javax.net.SocketFactory;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.security.GeneralSecurityException;
+
+public final class CRLSocket extends SSLClient {
+    private static final CRLSocket SECURE_INSTANCE;
+    private static final CRLSocket PLAIN_INSTANCE;
+
+    static {
+        CRLSocket sf1 = null, sf2 = null;
+        try {
+            sf1 = new CRLSocket();
+            sf2 = new CRLSocket();
+            sf2.setIsSecure(false);
+        } catch (Exception e) {
+            System.out.println("could not create CRLSocket: " + e);
+            e.printStackTrace();
+        } finally {
+            SECURE_INSTANCE = sf1;
+            PLAIN_INSTANCE = sf2;
+        }
+    }
+
+    private CRLSocket() throws GeneralSecurityException, IOException {
+        super();
+
+        // For now we setup the usual trust infrastructure, but consumers
+        // are encouraged to call getInstance().addTrustMaterial() or
+        // getInstance().setTrustMaterial() to customize the trust.
+        if (TrustMaterial.JSSE_CACERTS != null) {
+            setTrustMaterial(TrustMaterial.JSSE_CACERTS);
+        } else {
+            setTrustMaterial(TrustMaterial.CACERTS);
+        }
+        setConnectTimeout(5000);
+        setSoTimeout(5000);
+        setCheckCRL(false);
+    }
+
+    public static SocketFactory getDefault() {
+        return getSecureInstance();
+    }
+
+    public static CRLSocket getSecureInstance() {
+        return SECURE_INSTANCE;
+    }
+
+    public static CRLSocket getPlainInstance() {
+        return PLAIN_INSTANCE;
+    }
+
+    public static void main(String[] args) throws Exception {
+        String host = args[0];
+        String port = args[1];
+        String hello
+                = "HEAD / HTTP/1.1\r\n"
+                + "Host:" + host + ":" + port + "\r\n\r\n";
+        byte[] helloBytes = hello.getBytes("UTF-8");
+
+        System.out.println("About to getInstance() ");
+        CRLSocket sf = getPlainInstance();
+        long now = System.currentTimeMillis();
+        System.out.println("About to create socket: [" + host + ":" + port + "]");
+        Socket s = sf.createSocket(host, Integer.parseInt(port));
+        long delay = System.currentTimeMillis() - now;
+        System.out.println("Created socket! took " + delay + "ms ");
+        OutputStream out = s.getOutputStream();
+        out.write(helloBytes);
+        out.flush();
+
+        System.out.println("\n" + new String(helloBytes, "UTF-8"));
+
+        InputStream in = s.getInputStream();
+        int c = in.read();
+        StringBuffer buf = new StringBuffer();
+        System.out.println("Reading: ");
+        System.out.println("================================================================================");
+        while (c >= 0) {
+            byte b = (byte) c;
+            buf.append((char) b);
+            System.out.print((char) b);
+            if (-1 == buf.toString().indexOf("\r\n\r\n")) {
+                c = in.read();
+            } else {
+                break;
+            }
+        }
+        in.close();
+        out.close();
+        s.close();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/kerby-pkix/src/main/java/org/apache/commons/ssl/CRLUtil.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/CRLUtil.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/CRLUtil.java
new file mode 100644
index 0000000..bec387e
--- /dev/null
+++ b/kerby-pkix/src/main/java/org/apache/commons/ssl/CRLUtil.java
@@ -0,0 +1,75 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.16/src/java/org/apache/commons/ssl/CRLUtil.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+/*
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.asn1.x509.CRLDistPoint;
+import org.bouncycastle.asn1.x509.DistributionPoint;
+import org.bouncycastle.asn1.x509.DistributionPointName;
+import org.bouncycastle.x509.extension.X509ExtensionUtil;
+*/
+
+import java.io.IOException;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
+ * @since 20-Dec-2005
+ */
+public class CRLUtil {
+
+    public static String getURLToCRL(byte[] extension)
+        throws IOException {
+
+        throw new UnsupportedOperationException("not yet implemented");
+
+        /*
+                    byte[] bytes = extension2_5_29_31;
+                    ASN1Encodable asn1 = X509ExtensionUtil.fromExtensionValue(bytes);
+                    DERObject obj = asn1.getDERObject();
+                    CRLDistPoint distPoint = CRLDistPoint.getInstance(obj);
+                    DistributionPoint[] points = distPoint.getDistributionPoints();
+                    DistributionPointName dpn = points[0].getDistributionPoint();
+                    obj = dpn.getName().toASN1Object();
+                    ASN1Sequence seq = ASN1Sequence.getInstance(obj);
+                    DERTaggedObject tag = (DERTaggedObject) seq.getObjectAt(0);
+                    bytes = ASN1OctetString.getInstance(tag, false).getOctets();
+                    return new String(bytes);
+                    */
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/kerby-pkix/src/main/java/org/apache/commons/ssl/Certificates.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/Certificates.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/Certificates.java
new file mode 100644
index 0000000..0af39ea
--- /dev/null
+++ b/kerby-pkix/src/main/java/org/apache/commons/ssl/Certificates.java
@@ -0,0 +1,617 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.16/src/java/org/apache/commons/ssl/Certificates.java $
+ * $Revision: 180 $
+ * $Date: 2014-09-23 11:33:47 -0700 (Tue, 23 Sep 2014) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.apache.kerby.util.Base64;
+
+import javax.naming.InvalidNameException;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+import javax.net.ssl.HttpsURLConnection;
+import javax.security.auth.x500.X500Principal;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CRL;
+import java.security.cert.CRLException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.security.cert.X509Extension;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
+ * @since 19-Aug-2005
+ */
+public class Certificates {
+
+    public static final CertificateFactory CF;
+    public static final String LINE_ENDING = System.getProperty("line.separator");
+
+    private static final HashMap CRL_CACHE = new HashMap();
+
+    public static final String CRL_EXTENSION = "2.5.29.31";
+    public static final String OCSP_EXTENSION = "1.3.6.1.5.5.7.1.1";
+    private static final DateFormat DF = new SimpleDateFormat("yyyy/MMM/dd");
+
+    public interface SerializableComparator extends Comparator, Serializable {
+    }
+
+    public static final SerializableComparator COMPARE_BY_EXPIRY =
+        new SerializableComparator() {
+            public int compare(Object o1, Object o2) {
+                X509Certificate c1 = (X509Certificate) o1;
+                X509Certificate c2 = (X509Certificate) o2;
+                // this deals with case where both are null
+                if (c1 == c2) {
+                    return 0;
+                }
+                // non-null is always bigger than null
+                if (c1 == null) {
+                    return -1;
+                }
+                if (c2 == null) {
+                    return 1;
+                }
+                if (c1.equals(c2)) {
+                    return 0;
+                }
+                Date d1 = c1.getNotAfter();
+                Date d2 = c2.getNotAfter();
+                int c = d1.compareTo(d2);
+                if (c == 0) {
+                    String s1 = JavaImpl.getSubjectX500(c1);
+                    String s2 = JavaImpl.getSubjectX500(c2);
+                    c = s1.compareTo(s2);
+                    if (c == 0) {
+                        s1 = JavaImpl.getIssuerX500(c1);
+                        s2 = JavaImpl.getIssuerX500(c2);
+                        c = s1.compareTo(s2);
+                        if (c == 0) {
+                            BigInteger big1 = c1.getSerialNumber();
+                            BigInteger big2 = c2.getSerialNumber();
+                            c = big1.compareTo(big2);
+                            if (c == 0) {
+                                try {
+                                    byte[] b1 = c1.getEncoded();
+                                    byte[] b2 = c2.getEncoded();
+                                    int len1 = b1.length;
+                                    int len2 = b2.length;
+                                    int i = 0;
+                                    for (; i < len1 && i < len2; i++) {
+                                        c = ((int) b1[i]) - ((int) b2[i]);
+                                        if (c != 0) {
+                                            break;
+                                        }
+                                    }
+                                    if (c == 0) {
+                                        c = b1.length - b2.length;
+                                    }
+                                } catch (CertificateEncodingException cee) {
+                                    // I give up.  They can be equal if they
+                                    // really want to be this badly.
+                                    c = 0;
+                                }
+                            }
+                        }
+                    }
+                }
+                return c;
+            }
+        };
+
+    static {
+        CertificateFactory cf = null;
+        try {
+            cf = CertificateFactory.getInstance("X.509");
+        } catch (CertificateException ce) {
+            ce.printStackTrace(System.out);
+        } finally {
+            CF = cf;
+        }
+    }
+
+    public static String toPEMString(X509Certificate cert)
+        throws CertificateEncodingException {
+        return toString(cert.getEncoded());
+    }
+
+    public static String toString(byte[] x509Encoded) {
+        byte[] encoded = Base64.encodeBase64(x509Encoded);
+        StringBuffer buf = new StringBuffer(encoded.length + 100);
+        buf.append("-----BEGIN CERTIFICATE-----\n");
+        for (int i = 0; i < encoded.length; i += 64) {
+            if (encoded.length - i >= 64) {
+                buf.append(new String(encoded, i, 64));
+            } else {
+                buf.append(new String(encoded, i, encoded.length - i));
+            }
+            buf.append(LINE_ENDING);
+        }
+        buf.append("-----END CERTIFICATE-----");
+        buf.append(LINE_ENDING);
+        return buf.toString();
+    }
+
+    public static String toString(X509Certificate cert) {
+        return toString(cert, false);
+    }
+
+    public static String toString(X509Certificate cert, boolean htmlStyle) {
+        String cn = getCN(cert);
+        String startStart = DF.format(cert.getNotBefore());
+        String endDate = DF.format(cert.getNotAfter());
+        String subject = JavaImpl.getSubjectX500(cert);
+        String issuer = JavaImpl.getIssuerX500(cert);
+        Iterator crls = getCRLs(cert).iterator();
+        if (subject.equals(issuer)) {
+            issuer = "self-signed";
+        }
+        StringBuffer buf = new StringBuffer(128);
+        if (htmlStyle) {
+            buf.append("<strong class=\"cn\">");
+        }
+        buf.append(cn);
+        if (htmlStyle) {
+            buf.append("</strong>");
+        }
+        buf.append(LINE_ENDING);
+        buf.append("Valid: ");
+        buf.append(startStart);
+        buf.append(" - ");
+        buf.append(endDate);
+        buf.append(LINE_ENDING);
+        buf.append("s: ");
+        buf.append(subject);
+        buf.append(LINE_ENDING);
+        buf.append("i: ");
+        buf.append(issuer);
+        while (crls.hasNext()) {
+            buf.append(LINE_ENDING);
+            buf.append("CRL: ");
+            buf.append((String) crls.next());
+        }
+        buf.append(LINE_ENDING);
+        return buf.toString();
+    }
+
+    public static List getCRLs(X509Extension cert) {
+        // What follows is a poor man's CRL extractor, for those lacking
+        // a BouncyCastle "bcprov.jar" in their classpath.
+
+        // It's a very basic state-machine:  look for a standard URL scheme
+        // (such as http), and then start looking for a terminator.  After
+        // running hexdump a few times on these things, it looks to me like
+        // the UTF-8 value "65533" seems to happen near where these things
+        // terminate.  (Of course this stuff is ASN.1 and not UTF-8, but
+        // I happen to like some of the functions available to the String
+        // object).    - juliusdavies@cucbc.com, May 10th, 2006
+        byte[] bytes = cert.getExtensionValue(CRL_EXTENSION);
+        LinkedList httpCRLS = new LinkedList();
+        LinkedList ftpCRLS = new LinkedList();
+        LinkedList otherCRLS = new LinkedList();
+        if (bytes == null) {
+            // just return empty list
+            return httpCRLS;
+        } else {
+            String s;
+            try {
+                s = new String(bytes, "UTF-8");
+            } catch (UnsupportedEncodingException uee) {
+                // We're screwed if this thing has more than one CRL, because
+                // the "indeOf( (char) 65533 )" below isn't going to work.
+                s = new String(bytes);
+            }
+            int pos = 0;
+            while (pos >= 0) {
+                int x = -1, y;
+                int[] indexes = new int[4];
+                indexes[0] = s.indexOf("http", pos);
+                indexes[1] = s.indexOf("ldap", pos);
+                indexes[2] = s.indexOf("file", pos);
+                indexes[3] = s.indexOf("ftp", pos);
+                Arrays.sort(indexes);
+                for (int i = 0; i < indexes.length; i++) {
+                    if (indexes[i] >= 0) {
+                        x = indexes[i];
+                        break;
+                    }
+                }
+                if (x >= 0) {
+                    y = s.indexOf((char) 65533, x);
+                    String crl = y > x ? s.substring(x, y - 1) : s.substring(x);
+                    if (y > x && crl.endsWith("0")) {
+                        crl = crl.substring(0, crl.length() - 1);
+                    }
+                    String crlTest = crl.trim().toLowerCase();
+                    if (crlTest.startsWith("http")) {
+                        httpCRLS.add(crl);
+                    } else if (crlTest.startsWith("ftp")) {
+                        ftpCRLS.add(crl);
+                    } else {
+                        otherCRLS.add(crl);
+                    }
+                    pos = y;
+                } else {
+                    pos = -1;
+                }
+            }
+        }
+
+        httpCRLS.addAll(ftpCRLS);
+        httpCRLS.addAll(otherCRLS);
+        return httpCRLS;
+    }
+
+    public static void checkCRL(X509Certificate cert)
+        throws CertificateException {
+        // String name = cert.getSubjectX500Principal().toString();
+        byte[] bytes = cert.getExtensionValue("2.5.29.31");
+        if (bytes == null) {
+            // log.warn( "Cert doesn't contain X509v3 CRL Distribution Points (2.5.29.31): " + name );
+            System.err.println("Cert doesn't contain X509v3 CRL Distribution Points (2.5.29.31)");
+        } else {
+            List crlList = getCRLs(cert);
+            Iterator it = crlList.iterator();
+            while (it.hasNext()) {
+                String url = (String) it.next();
+                CRLHolder holder = (CRLHolder) CRL_CACHE.get(url);
+                if (holder == null) {
+                    holder = new CRLHolder(url);
+                    CRL_CACHE.put(url, holder);
+                }
+                // success == false means we couldn't actually load the CRL
+                // (probably due to an IOException), so let's try the next one in
+                // our list.
+                boolean success = holder.checkCRL(cert);
+                if (success) {
+                    break;
+                }
+            }
+        }
+
+    }
+
+    public static BigInteger getFingerprint(X509Certificate x509)
+        throws CertificateEncodingException {
+        return getFingerprint(x509.getEncoded());
+    }
+
+    public static BigInteger getFingerprint(byte[] x509)
+        throws CertificateEncodingException {
+        MessageDigest sha1;
+        try {
+            sha1 = MessageDigest.getInstance("SHA1");
+        } catch (NoSuchAlgorithmException nsae) {
+            throw JavaImpl.newRuntimeException(nsae);
+        }
+
+        sha1.reset();
+        byte[] result = sha1.digest(x509);
+        return new BigInteger(result);
+    }
+
+    private static class CRLHolder {
+        private final String urlString;
+
+        private File tempCRLFile;
+        private long creationTime;
+        private Set passedTest = new HashSet();
+        private Set failedTest = new HashSet();
+
+        CRLHolder(String urlString) {
+            if (urlString == null) {
+                throw new NullPointerException("urlString can't be null");
+            }
+            this.urlString = urlString;
+        }
+
+        public synchronized boolean checkCRL(X509Certificate cert)
+            throws CertificateException {
+            CRL crl = null;
+            long now = System.currentTimeMillis();
+            if (now - creationTime > 24 * 60 * 60 * 1000) {
+                // Expire cache every 24 hours
+                if (tempCRLFile != null && tempCRLFile.exists()) {
+                    tempCRLFile.delete();
+                }
+                tempCRLFile = null;
+                passedTest.clear();
+
+                /*
+                      Note:  if any certificate ever fails the check, we will
+                      remember that fact.
+
+                      This breaks with temporary "holds" that CRL's can issue.
+                      Apparently a certificate can have a temporary "hold" on its
+                      validity, but I'm not interested in supporting that.  If a "held"
+                      certificate is suddenly "unheld", you're just going to need
+                      to restart your JVM.
+                    */
+                // failedTest.clear();  <-- DO NOT UNCOMMENT!
+            }
+
+            BigInteger fingerprint = getFingerprint(cert);
+            if (failedTest.contains(fingerprint)) {
+                throw new CertificateException("Revoked by CRL (cached response)");
+            }
+            if (passedTest.contains(fingerprint)) {
+                return true;
+            }
+
+            if (tempCRLFile == null) {
+                try {
+                    // log.info( "Trying to load CRL [" + urlString + "]" );
+
+                    // java.net.URL blocks forever by default, so CRL-checking
+                    // is freezing some systems.  Below we go to great pains
+                    // to enforce timeouts for CRL-checking (5 seconds).
+                    URL url = new URL(urlString);
+                    URLConnection urlConn = url.openConnection();
+                    if (urlConn instanceof HttpsURLConnection) {
+
+                        // HTTPS sites will use special CRLSocket.getInstance() SocketFactory
+                        // that is configured to timeout after 5 seconds:
+                        HttpsURLConnection httpsConn = (HttpsURLConnection) urlConn;
+                        httpsConn.setSSLSocketFactory(CRLSocket.getSecureInstance());
+
+                    } else if (urlConn instanceof HttpURLConnection) {
+
+                        // HTTP timeouts can only be set on Java 1.5 and up.  :-(
+                        // The code required to set it for Java 1.4 and Java 1.3 is just too painful.
+                        HttpURLConnection httpConn = (HttpURLConnection) urlConn;
+                        try {
+                            // Java 1.5 and up support these, so using reflection.  UGH!!!
+                            Class c = httpConn.getClass();
+                            Method setConnTimeOut = c.getDeclaredMethod("setConnectTimeout", new Class[]{Integer.TYPE});
+                            Method setReadTimeout = c.getDeclaredMethod("setReadTimeout", new Class[]{Integer.TYPE});
+                            setConnTimeOut.invoke(httpConn, Integer.valueOf(5000));
+                            setReadTimeout.invoke(httpConn, Integer.valueOf(5000));
+                        } catch (NoSuchMethodException nsme) {
+                            // oh well, java 1.4 users can suffer.
+                            System.err.println(nsme);
+                        } catch (Exception e) {
+                            throw new RuntimeException("can't set timeout", e);
+                        }
+                    }
+
+                    File tempFile = File.createTempFile("crl", ".tmp");
+                    tempFile.deleteOnExit();
+
+                    OutputStream out = new FileOutputStream(tempFile);
+                    out = new BufferedOutputStream(out);
+                    InputStream in = new BufferedInputStream(urlConn.getInputStream());
+                    try {
+                        Util.pipeStream(in, out);
+                    } catch (IOException ioe) {
+                        // better luck next time
+                        tempFile.delete();
+                        throw ioe;
+                    }
+                    this.tempCRLFile = tempFile;
+                    this.creationTime = System.currentTimeMillis();
+                } catch (IOException ioe) {
+                    // log.warn( "Cannot check CRL: " + e );
+                    System.err.println(ioe);
+                }
+            }
+
+            if (tempCRLFile != null && tempCRLFile.exists()) {
+                try {
+                    InputStream in = new FileInputStream(tempCRLFile);
+                    in = new BufferedInputStream(in);
+                    synchronized (CF) {
+                        crl = CF.generateCRL(in);
+                    }
+                    in.close();
+                    if (crl.isRevoked(cert)) {
+                        // log.warn( "Revoked by CRL [" + urlString + "]: " + name );
+                        passedTest.remove(fingerprint);
+                        failedTest.add(fingerprint);
+                        throw new CertificateException("Revoked by CRL");
+                    } else {
+                        passedTest.add(fingerprint);
+                    }
+                } catch (IOException ioe) {
+                    // couldn't load CRL that's supposed to be stored in Temp file.
+                    // log.warn(  );
+                    System.err.println(ioe);
+                } catch (CRLException crle) {
+                    // something is wrong with the CRL
+                    // log.warn(  );
+                    System.err.println(crle);
+                }
+            }
+            return crl != null;
+        }
+    }
+
+    public static String getCN(X509Certificate cert) {
+        String[] cns = getCNs(cert);
+        boolean foundSomeCNs = cns != null && cns.length >= 1;
+        return foundSomeCNs ? cns[0] : null;
+    }
+
+    public static String[] getCNs(X509Certificate cert) {
+        try {
+            final String subjectPrincipal = cert.getSubjectX500Principal().getName(X500Principal.RFC2253);
+            final LinkedList<String> cnList = new LinkedList<String>();
+            final LdapName subjectDN = new LdapName(subjectPrincipal);
+            for (final Rdn rds : subjectDN.getRdns()) {
+                final Attributes attributes = rds.toAttributes();
+                final Attribute cn = attributes.get("cn");
+                if (cn != null) {
+                    try {
+                        final Object value = cn.get();
+                        if (value != null) {
+                            cnList.add(value.toString());
+                        }
+                    } catch (NoSuchElementException ignore) {
+                        System.err.println(ignore);
+                    } catch (NamingException ignore) {
+                        System.err.println(ignore);
+                    }
+                }
+            }
+            if (!cnList.isEmpty()) {
+                return cnList.toArray(new String[cnList.size()]);
+            }
+        } catch (InvalidNameException ignore) {
+            System.err.println(ignore);
+        }
+        return null;
+    }
+
+    /**
+     * Extracts the array of SubjectAlt DNS names from an X509Certificate.
+     * Returns null if there aren't any.
+     * <p/>
+     * Note:  Java doesn't appear able to extract international characters
+     * from the SubjectAlts.  It can only extract international characters
+     * from the CN field.
+     * <p/>
+     * (Or maybe the version of OpenSSL I'm using to test isn't storing the
+     * international characters correctly in the SubjectAlts?).
+     *
+     * @param cert X509Certificate
+     * @return Array of SubjectALT DNS names stored in the certificate.
+     */
+    public static String[] getDNSSubjectAlts(X509Certificate cert) {
+        LinkedList subjectAltList = new LinkedList();
+        Collection c = null;
+        try {
+            c = cert.getSubjectAlternativeNames();
+        } catch (CertificateParsingException cpe) {
+            // Should probably log.debug() this?
+            cpe.printStackTrace();
+        }
+        if (c != null) {
+            Iterator it = c.iterator();
+            while (it.hasNext()) {
+                List list = (List) it.next();
+                int type = ((Integer) list.get(0)).intValue();
+                // If type is 2, then we've got a dNSName
+                if (type == 2) {
+                    String s = (String) list.get(1);
+                    subjectAltList.add(s);
+                }
+            }
+        }
+        if (!subjectAltList.isEmpty()) {
+            String[] subjectAlts = new String[subjectAltList.size()];
+            subjectAltList.toArray(subjectAlts);
+            return subjectAlts;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Trims off any null entries on the array.  Returns a shrunk array.
+     *
+     * @param chain X509Certificate[] chain to trim
+     * @return Shrunk array with all trailing null entries removed.
+     */
+    public static Certificate[] trimChain(Certificate[] chain) {
+        for (int i = 0; i < chain.length; i++) {
+            if (chain[i] == null) {
+                X509Certificate[] newChain = new X509Certificate[i];
+                System.arraycopy(chain, 0, newChain, 0, i);
+                return newChain;
+            }
+        }
+        return chain;
+    }
+
+    /**
+     * Returns a chain of type X509Certificate[].
+     *
+     * @param chain Certificate[] chain to cast to X509Certificate[]
+     * @return chain of type X509Certificate[].
+     */
+    public static X509Certificate[] x509ifyChain(Certificate[] chain) {
+        if (chain instanceof X509Certificate[]) {
+            return (X509Certificate[]) chain;
+        } else {
+            X509Certificate[] x509Chain = new X509Certificate[chain.length];
+            System.arraycopy(chain, 0, x509Chain, 0, chain.length);
+            return x509Chain;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        for (int i = 0; i < args.length; i++) {
+            FileInputStream in = new FileInputStream(args[i]);
+            TrustMaterial tm = new TrustMaterial(in);
+            Iterator it = tm.getCertificates().iterator();
+            while (it.hasNext()) {
+                X509Certificate x509 = (X509Certificate) it.next();
+                System.out.println(toString(x509));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/kerby-pkix/src/main/java/org/apache/commons/ssl/ComboInputStream.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/ComboInputStream.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/ComboInputStream.java
new file mode 100644
index 0000000..83a3077
--- /dev/null
+++ b/kerby-pkix/src/main/java/org/apache/commons/ssl/ComboInputStream.java
@@ -0,0 +1,95 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.16/src/java/org/apache/commons/ssl/ComboInputStream.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
+ * @since 22-Feb-2007
+ */
+public class ComboInputStream extends InputStream {
+    private boolean headDone;
+    private InputStream head;
+    private InputStream tail;
+
+    public ComboInputStream(InputStream head, InputStream tail) {
+        this.head = head != null ? head : tail;
+        this.tail = tail != null ? tail : head;
+    }
+
+    public int read() throws IOException {
+        int c;
+        if (headDone) {
+            c = tail.read();
+        } else {
+            c = head.read();
+            if (c == -1) {
+                headDone = true;
+                c = tail.read();
+            }
+        }
+        return c;
+    }
+
+    public int available() throws IOException {
+        return tail.available() + head.available();
+    }
+
+    public void close() throws IOException {
+        try {
+            head.close();
+        } finally {
+            if (head != tail) {
+                tail.close();
+            }
+        }
+    }
+
+    public int read(byte[] b, int off, int len) throws IOException {
+        int c;
+        if (headDone) {
+            c = tail.read(b, off, len);
+        } else {
+            c = head.read(b, off, len);
+            if (c == -1) {
+                headDone = true;
+                c = tail.read(b, off, len);
+            }
+        }
+        return c;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/kerby-pkix/src/main/java/org/apache/commons/ssl/DerivedKey.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/DerivedKey.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/DerivedKey.java
new file mode 100644
index 0000000..7005187
--- /dev/null
+++ b/kerby-pkix/src/main/java/org/apache/commons/ssl/DerivedKey.java
@@ -0,0 +1,49 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.16/src/java/org/apache/commons/ssl/DerivedKey.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
+ * @since 7-Nov-2006
+ */
+public class DerivedKey {
+    public final byte[] key;
+    public final byte[] iv;
+
+    DerivedKey(byte[] key, byte[] iv) {
+        this.key = key;
+        this.iv = iv;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/kerby-pkix/src/main/java/org/apache/commons/ssl/HostPort.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/HostPort.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/HostPort.java
new file mode 100644
index 0000000..b39772d
--- /dev/null
+++ b/kerby-pkix/src/main/java/org/apache/commons/ssl/HostPort.java
@@ -0,0 +1,57 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.16/src/java/org/apache/commons/ssl/HostPort.java $
+ * $Revision: 166 $
+ * $Date: 2014-04-28 11:40:25 -0700 (Mon, 28 Apr 2014) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
+ * @since 14-July-2006
+ */
+public class HostPort {
+    public final String host;
+    public final int port;
+    public final InetAddress addr;
+
+    public HostPort(String host, int port) throws UnknownHostException {
+        this.host = host;
+        this.port = port;
+        this.addr = Util.toInetAddress(host);
+    }
+
+    public String toString() {
+        return host + ":" + port;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/a2c604ee/kerby-pkix/src/main/java/org/apache/commons/ssl/HostnameVerifier.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/HostnameVerifier.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/HostnameVerifier.java
new file mode 100644
index 0000000..ada875f
--- /dev/null
+++ b/kerby-pkix/src/main/java/org/apache/commons/ssl/HostnameVerifier.java
@@ -0,0 +1,491 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.16/src/java/org/apache/commons/ssl/HostnameVerifier.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.TreeSet;
+
+/**
+ * Interface for checking if a hostname matches the names stored inside the
+ * server's X.509 certificate.  Correctly implements
+ * javax.net.ssl.HostnameVerifier, but that interface is not recommended.
+ * Instead we added several check() methods that take SSLSocket,
+ * or X509Certificate, or ultimately (they all end up calling this one),
+ * String.  (It's easier to supply JUnit with Strings instead of mock
+ * SSLSession objects!)
+ * </p><p>Our check() methods throw exceptions if the name is
+ * invalid, whereas javax.net.ssl.HostnameVerifier just returns true/false.
+ * <p/>
+ * We provide the HostnameVerifier.DEFAULT, HostnameVerifier.STRICT, and
+ * HostnameVerifier.ALLOW_ALL implementations.  We also provide the more
+ * specialized HostnameVerifier.DEFAULT_AND_LOCALHOST, as well as
+ * HostnameVerifier.STRICT_IE6.  But feel free to define your own
+ * implementations!
+ * <p/>
+ * Inspired by Sebastian Hauer's original StrictSSLProtocolSocketFactory in the
+ * HttpClient "contrib" repository.
+ *
+ * @author Julius Davies
+ * @author <a href="mailto:hauer@psicode.com">Sebastian Hauer</a>
+ * @since 8-Dec-2006
+ */
+public interface HostnameVerifier extends javax.net.ssl.HostnameVerifier {
+
+    boolean verify(String host, SSLSession session);
+
+    void check(String host, SSLSocket ssl) throws IOException;
+
+    void check(String host, X509Certificate cert) throws SSLException;
+
+    void check(String host, String[] cns, String[] subjectAlts)
+        throws SSLException;
+
+    void check(String[] hosts, SSLSocket ssl) throws IOException;
+
+    void check(String[] hosts, X509Certificate cert) throws SSLException;
+
+
+    /**
+     * Checks to see if the supplied hostname matches any of the supplied CNs
+     * or "DNS" Subject-Alts.  Most implementations only look at the first CN,
+     * and ignore any additional CNs.  Most implementations do look at all of
+     * the "DNS" Subject-Alts. The CNs or Subject-Alts may contain wildcards
+     * according to RFC 2818.
+     *
+     * @param cns         CN fields, in order, as extracted from the X.509
+     *                    certificate.
+     * @param subjectAlts Subject-Alt fields of type 2 ("DNS"), as extracted
+     *                    from the X.509 certificate.
+     * @param hosts       The array of hostnames to verify.
+     * @throws javax.net.ssl.SSLException If verification failed.
+     */
+    void check(String[] hosts, String[] cns, String[] subjectAlts)
+        throws SSLException;
+
+
+    /**
+     * The DEFAULT HostnameVerifier works the same way as Curl and Firefox.
+     * <p/>
+     * The hostname must match either the first CN, or any of the subject-alts.
+     * A wildcard can occur in the CN, and in any of the subject-alts.
+     * <p/>
+     * The only difference between DEFAULT and STRICT is that a wildcard (such
+     * as "*.foo.com") with DEFAULT matches all subdomains, including
+     * "a.b.foo.com".
+     */
+    HostnameVerifier DEFAULT =
+        new AbstractVerifier() {
+            public final void check(final String[] hosts, final String[] cns,
+                                    final String[] subjectAlts)
+                throws SSLException {
+                check(hosts, cns, subjectAlts, false, false);
+            }
+
+            public final String toString() {
+                return "DEFAULT";
+            }
+        };
+
+
+    /**
+     * The DEFAULT_AND_LOCALHOST HostnameVerifier works like the DEFAULT
+     * one with one additional relaxation:  a host of "localhost",
+     * "localhost.localdomain", "127.0.0.1", "::1" will always pass, no matter
+     * what is in the server's certificate.
+     */
+    HostnameVerifier DEFAULT_AND_LOCALHOST =
+        new AbstractVerifier() {
+            public final void check(final String[] hosts, final String[] cns,
+                                    final String[] subjectAlts)
+                throws SSLException {
+                if (isLocalhost(hosts[0])) {
+                    return;
+                }
+                check(hosts, cns, subjectAlts, false, false);
+            }
+
+            public final String toString() {
+                return "DEFAULT_AND_LOCALHOST";
+            }
+        };
+
+    /**
+     * The STRICT HostnameVerifier works the same way as java.net.URL in Sun
+     * Java 1.4, Sun Java 5, Sun Java 6.  It's also pretty close to IE6.
+     * This implementation appears to be compliant with RFC 2818 for dealing
+     * with wildcards.
+     * <p/>
+     * The hostname must match either the first CN, or any of the subject-alts.
+     * A wildcard can occur in the CN, and in any of the subject-alts.  The
+     * one divergence from IE6 is how we only check the first CN.  IE6 allows
+     * a match against any of the CNs present.  We decided to follow in
+     * Sun Java 1.4's footsteps and only check the first CN.
+     * <p/>
+     * A wildcard such as "*.foo.com" matches only subdomains in the same
+     * level, for example "a.foo.com".  It does not match deeper subdomains
+     * such as "a.b.foo.com".
+     */
+    HostnameVerifier STRICT =
+        new AbstractVerifier() {
+            public final void check(final String[] host, final String[] cns,
+                                    final String[] subjectAlts)
+                throws SSLException {
+                check(host, cns, subjectAlts, false, true);
+            }
+
+            public final String toString() {
+                return "STRICT";
+            }
+        };
+
+    /**
+     * The STRICT_IE6 HostnameVerifier works just like the STRICT one with one
+     * minor variation:  the hostname can match against any of the CN's in the
+     * server's certificate, not just the first one.  This behaviour is
+     * identical to IE6's behaviour.
+     */
+    HostnameVerifier STRICT_IE6 =
+        new AbstractVerifier() {
+            public final void check(final String[] host, final String[] cns,
+                                    final String[] subjectAlts)
+                throws SSLException {
+                check(host, cns, subjectAlts, true, true);
+            }
+
+            public final String toString() {
+                return "STRICT_IE6";
+            }
+        };
+
+    /**
+     * The ALLOW_ALL HostnameVerifier essentially turns hostname verification
+     * off.  This implementation is a no-op, and never throws the SSLException.
+     */
+    HostnameVerifier ALLOW_ALL =
+        new AbstractVerifier() {
+            public final void check(final String[] host, final String[] cns,
+                                    final String[] subjectAlts) {
+                // Allow everything - so never blowup.
+            }
+
+            public final String toString() {
+                return "ALLOW_ALL";
+            }
+        };
+
+    abstract class AbstractVerifier implements HostnameVerifier {
+
+        /**
+         * This contains a list of 2nd-level domains that aren't allowed to
+         * have wildcards when combined with country-codes.
+         * For example: [*.co.uk].
+         * <p/>
+         * The [*.co.uk] problem is an interesting one.  Should we just hope
+         * that CA's would never foolishly allow such a certificate to happen?
+         * Looks like we're the only implementation guarding against this.
+         * Firefox, Curl, Sun Java 1.4, 5, 6 don't bother with this check.
+         */
+        private static final String[] BAD_COUNTRY_2LDS =
+            {"ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
+                "lg", "ne", "net", "or", "org"};
+
+        private static final String[] LOCALHOSTS = {"::1", "127.0.0.1",
+            "localhost",
+            "localhost.localdomain"};
+
+
+        static {
+            // Just in case developer forgot to manually sort the array.  :-)
+            Arrays.sort(BAD_COUNTRY_2LDS);
+            Arrays.sort(LOCALHOSTS);
+        }
+
+        protected AbstractVerifier() {
+        }
+
+        /**
+         * The javax.net.ssl.HostnameVerifier contract.
+         *
+         * @param host    'hostname' we used to create our socket
+         * @param session SSLSession with the remote server
+         * @return true if the host matched the one in the certificate.
+         */
+        public boolean verify(String host, SSLSession session) {
+            try {
+                Certificate[] certs = session.getPeerCertificates();
+                X509Certificate x509 = (X509Certificate) certs[0];
+                check(new String[]{host}, x509);
+                return true;
+            } catch (SSLException e) {
+                return false;
+            }
+        }
+
+        public void check(String host, SSLSocket ssl) throws IOException {
+            check(new String[]{host}, ssl);
+        }
+
+        public void check(String host, X509Certificate cert)
+            throws SSLException {
+            check(new String[]{host}, cert);
+        }
+
+        public void check(String host, String[] cns, String[] subjectAlts)
+            throws SSLException {
+            check(new String[]{host}, cns, subjectAlts);
+        }
+
+        public void check(String[] host, SSLSocket ssl)
+            throws IOException {
+            if (host == null) {
+                throw new NullPointerException("host to verify is null");
+            }
+
+            SSLSession session = ssl.getSession();
+            if (session == null) {
+                // In our experience this only happens under IBM 1.4.x when
+                // spurious (unrelated) certificates show up in the server'
+                // chain.  Hopefully this will unearth the real problem:
+                InputStream in = ssl.getInputStream();
+                in.available();
+                /*
+                  If you're looking at the 2 lines of code above because
+                  you're running into a problem, you probably have two
+                  options:
+
+                    #1.  Clean up the certificate chain that your server
+                         is presenting (e.g. edit "/etc/apache2/server.crt"
+                         or wherever it is your server's certificate chain
+                         is defined).
+
+                                               OR
+
+                    #2.   Upgrade to an IBM 1.5.x or greater JVM, or switch
+                          to a non-IBM JVM.
+                */
+
+                // If ssl.getInputStream().available() didn't cause an
+                // exception, maybe at least now the session is available?
+                session = ssl.getSession();
+                if (session == null) {
+                    // If it's still null, probably a startHandshake() will
+                    // unearth the real problem.
+                    ssl.startHandshake();
+
+                    // Okay, if we still haven't managed to cause an exception,
+                    // might as well go for the NPE.  Or maybe we're okay now?
+                    session = ssl.getSession();
+                }
+            }
+            Certificate[] certs;
+            try {
+                certs = session.getPeerCertificates();
+            } catch (SSLPeerUnverifiedException spue) {
+                InputStream in = ssl.getInputStream();
+                in.available();
+                // Didn't trigger anything interesting?  Okay, just throw
+                // original.
+                throw spue;
+            }
+            X509Certificate x509 = (X509Certificate) certs[0];
+            check(host, x509);
+        }
+
+        public void check(String[] host, X509Certificate cert)
+            throws SSLException {
+            String[] cns = Certificates.getCNs(cert);
+            String[] subjectAlts = Certificates.getDNSSubjectAlts(cert);
+            check(host, cns, subjectAlts);
+        }
+
+        public void check(final String[] hosts, final String[] cns,
+                          final String[] subjectAlts, final boolean ie6,
+                          final boolean strictWithSubDomains)
+            throws SSLException {
+            // Build up lists of allowed hosts For logging/debugging purposes.
+            StringBuffer buf = new StringBuffer(32);
+            buf.append('<');
+            for (int i = 0; i < hosts.length; i++) {
+                String h = hosts[i];
+                h = h != null ? h.trim().toLowerCase() : "";
+                hosts[i] = h;
+                if (i > 0) {
+                    buf.append('/');
+                }
+                buf.append(h);
+            }
+            buf.append('>');
+            String hostnames = buf.toString();
+            // Build the list of names we're going to check.  Our DEFAULT and
+            // STRICT implementations of the HostnameVerifier only use the
+            // first CN provided.  All other CNs are ignored.
+            // (Firefox, wget, curl, Sun Java 1.4, 5, 6 all work this way).
+            TreeSet names = new TreeSet();
+            if (cns != null && cns.length > 0 && cns[0] != null) {
+                names.add(cns[0]);
+                if (ie6) {
+                    for (int i = 1; i < cns.length; i++) {
+                        names.add(cns[i]);
+                    }
+                }
+            }
+            if (subjectAlts != null) {
+                for (int i = 0; i < subjectAlts.length; i++) {
+                    if (subjectAlts[i] != null) {
+                        names.add(subjectAlts[i]);
+                    }
+                }
+            }
+            if (names.isEmpty()) {
+                String msg = "Certificate for " + hosts[0] + " doesn't contain CN or DNS subjectAlt";
+                throw new SSLException(msg);
+            }
+
+            // StringBuffer for building the error message.
+            buf = new StringBuffer();
+
+            boolean match = false;
+            out:
+            for (Iterator it = names.iterator(); it.hasNext();) {
+                // Don't trim the CN, though!
+                String cn = (String) it.next();
+                cn = cn.toLowerCase();
+                // Store CN in StringBuffer in case we need to report an error.
+                buf.append(" <");
+                buf.append(cn);
+                buf.append('>');
+                if (it.hasNext()) {
+                    buf.append(" OR");
+                }
+
+                // The CN better have at least two dots if it wants wildcard
+                // action.  It also can't be [*.co.uk] or [*.co.jp] or
+                // [*.org.uk], etc...
+                boolean doWildcard = cn.startsWith("*.")
+                                     && cn.lastIndexOf('.') >= 0
+                                     && !isIP4Address(cn)
+                                     && acceptableCountryWildcard(cn);
+
+                for (int i = 0; i < hosts.length; i++) {
+                    final String hostName = hosts[i].trim().toLowerCase();
+                    if (doWildcard) {
+                        match = hostName.endsWith(cn.substring(1));
+                        if (match && strictWithSubDomains) {
+                            // If we're in strict mode, then [*.foo.com] is not
+                            // allowed to match [a.b.foo.com]
+                            match = countDots(hostName) == countDots(cn);
+                        }
+                    } else {
+                        match = hostName.equals(cn);
+                    }
+                    if (match) {
+                        break out;
+                    }
+                }
+            }
+            if (!match) {
+                throw new SSLException("hostname in certificate didn't match: " + hostnames + " !=" + buf);
+            }
+        }
+
+        public static boolean isIP4Address(final String cn) {
+            boolean isIP4 = true;
+            String tld = cn;
+            int x = cn.lastIndexOf('.');
+            // We only bother analyzing the characters after the final dot
+            // in the name.
+            if (x >= 0 && x + 1 < cn.length()) {
+                tld = cn.substring(x + 1);
+            }
+            for (int i = 0; i < tld.length(); i++) {
+                if (!Character.isDigit(tld.charAt(0))) {
+                    isIP4 = false;
+                    break;
+                }
+            }
+            return isIP4;
+        }
+
+        public static boolean acceptableCountryWildcard(final String cn) {
+            int cnLen = cn.length();
+            if (cnLen >= 7 && cnLen <= 9) {
+                // Look for the '.' in the 3rd-last position:
+                if (cn.charAt(cnLen - 3) == '.') {
+                    // Trim off the [*.] and the [.XX].
+                    String s = cn.substring(2, cnLen - 3);
+                    // And test against the sorted array of bad 2lds:
+                    int x = Arrays.binarySearch(BAD_COUNTRY_2LDS, s);
+                    return x < 0;
+                }
+            }
+            return true;
+        }
+
+        public static boolean isLocalhost(String host) {
+            host = host != null ? host.trim().toLowerCase() : "";
+            if (host.startsWith("::1")) {
+                int x = host.lastIndexOf('%');
+                if (x >= 0) {
+                    host = host.substring(0, x);
+                }
+            }
+            int x = Arrays.binarySearch(LOCALHOSTS, host);
+            return x >= 0;
+        }
+
+        /**
+         * Counts the number of dots "." in a string.
+         *
+         * @param s string to count dots from
+         * @return number of dots
+         */
+        public static int countDots(final String s) {
+            int count = 0;
+            for (int i = 0; i < s.length(); i++) {
+                if (s.charAt(i) == '.') {
+                    count++;
+                }
+            }
+            return count;
+        }
+    }
+
+}


Mime
View raw message