6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
authorweijun
Mon, 24 May 2010 09:37:16 +0800
changeset 5616 6f3f39ddc2c2
parent 5615 3d77087a5a6c
child 5617 1b0d8c3d6223
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate Reviewed-by: mullan
jdk/src/share/classes/sun/security/provider/X509Factory.java
jdk/test/java/security/cert/CertificateFactory/openssl/BadFooter.java
--- a/jdk/src/share/classes/sun/security/provider/X509Factory.java	Mon May 24 09:37:02 2010 +0800
+++ b/jdk/src/share/classes/sun/security/provider/X509Factory.java	Mon May 24 09:37:16 2010 +0800
@@ -518,6 +518,7 @@
 
             // Step 2: Read the rest of header, determine the line end
             int end;
+            StringBuffer header = new StringBuffer("-----");
             while (true) {
                 int next = is.read();
                 if (next == -1) {
@@ -540,6 +541,7 @@
                     }
                     break;
                 }
+                header.append((char)next);
             }
 
             // Step 3: Read the data
@@ -559,6 +561,7 @@
             }
 
             // Step 4: Consume the footer
+            StringBuffer footer = new StringBuffer("-");
             while (true) {
                 int next = is.read();
                 // Add next == '\n' for maximum safety, in case endline
@@ -566,13 +569,34 @@
                 if (next == -1 || next == end || next == '\n') {
                     break;
                 }
+                if (next != '\r') footer.append((char)next);
             }
 
+            checkHeaderFooter(header.toString(), footer.toString());
+
             BASE64Decoder decoder = new BASE64Decoder();
             return decoder.decodeBuffer(new String(data, 0, pos));
         }
     }
 
+    private static void checkHeaderFooter(String header,
+            String footer) throws IOException {
+        if (header.length() < 16 || !header.startsWith("-----BEGIN ") ||
+                !header.endsWith("-----")) {
+            throw new IOException("Illegal header: " + header);
+        }
+        if (footer.length() < 14 || !footer.startsWith("-----END ") ||
+                !footer.endsWith("-----")) {
+            throw new IOException("Illegal footer: " + footer);
+        }
+        String headerType = header.substring(11, header.length()-5);
+        String footerType = footer.substring(9, footer.length()-5);
+        if (!headerType.equals(footerType)) {
+            throw new IOException("Header and footer do not match: " +
+                    header + " " + footer);
+        }
+    }
+
     /**
      * Read one BER data block. This method is aware of indefinite-length BER
      * encoding and will read all of the sub-sections in a recursive way
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/cert/CertificateFactory/openssl/BadFooter.java	Mon May 24 09:37:16 2010 +0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @test
+ * @bug 6948781
+ * @summary CertificateFactory.generateCertificate doesn't throw
+ * CertificateException for malformed certificate
+ */
+
+import java.io.ByteArrayInputStream;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertificateException;
+
+public class BadFooter {
+    public static void main(String[] args) throws Exception {
+        // The two sections below are identical, a self-signed cert generated
+        // for a fake principal:
+        // CN=Me, OU=Office, O=A-B-C, L=Backside, ST=Moon, C=EA
+        String cert =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIDGDCCAtWgAwIBAgIERgH/AjALBgcqhkjOOAQDBQAwXTELMAkGA1UEBhMCRUExDTALBgNVBAgT\n" +
+        "BE1vb24xETAPBgNVBAcTCEJhY2tzaWRlMQ4wDAYDVQQKEwVBLUItQzEPMA0GA1UECxMGT2ZmaWNl\n" +
+        "MQswCQYDVQQDEwJNZTAeFw0wNzAzMjIwMzU4NThaFw0wNzA2MjAwMzU4NThaMF0xCzAJBgNVBAYT\n" +
+        "AkVBMQ0wCwYDVQQIEwRNb29uMREwDwYDVQQHEwhCYWNrc2lkZTEOMAwGA1UEChMFQS1CLUMxDzAN\n" +
+        "BgNVBAsTBk9mZmljZTELMAkGA1UEAxMCTWUwggG4MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11\n" +
+        "EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZg\n" +
+        "t2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/y\n" +
+        "IgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o6\n" +
+        "6oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7Om\n" +
+        "dZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhQACgYEA\n" +
+        "xc7ovvDeJ5yIkiEoz6U4jcFf5ZDSC+rUEsqGuARXHUF0PlIth7h2e9KV12cwdjVH++mGvwU/m/Ju\n" +
+        "OpaaWOEFRHgCMe5fZ2xE0pWPcmKkPicc85SKHguYTMCc9D0XbTbkoBIEAeQ4nr2GmXuEQ5tYaO/O\n" +
+        "PYXjk9EfGhikHlnKgC6jITAfMB0GA1UdDgQWBBTtv4rKVwXtXJpyZWlswQL4MAKkazALBgcqhkjO\n" +
+        "OAQDBQADMAAwLQIVAIU4pnnUcMjh2CUvh/B0PSZZTHHvAhQVMhAdwNHOGPSL6sCL19q6UjoN9w==\n" +
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIDGDCCAtWgAwIBAgIERgH/AjALBgcqhkjOOAQDBQAwXTELMAkGA1UEBhMCRUExDTALBgNVBAgT\n" +
+        "BE1vb24xETAPBgNVBAcTCEJhY2tzaWRlMQ4wDAYDVQQKEwVBLUItQzEPMA0GA1UECxMGT2ZmaWNl\n" +
+        "MQswCQYDVQQDEwJNZTAeFw0wNzAzMjIwMzU4NThaFw0wNzA2MjAwMzU4NThaMF0xCzAJBgNVBAYT\n" +
+        "AkVBMQ0wCwYDVQQIEwRNb29uMREwDwYDVQQHEwhCYWNrc2lkZTEOMAwGA1UEChMFQS1CLUMxDzAN\n" +
+        "BgNVBAsTBk9mZmljZTELMAkGA1UEAxMCTWUwggG4MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11\n" +
+        "EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZg\n" +
+        "t2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/y\n" +
+        "IgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o6\n" +
+        "6oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7Om\n" +
+        "dZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhQACgYEA\n" +
+        "xc7ovvDeJ5yIkiEoz6U4jcFf5ZDSC+rUEsqGuARXHUF0PlIth7h2e9KV12cwdjVH++mGvwU/m/Ju\n" +
+        "OpaaWOEFRHgCMe5fZ2xE0pWPcmKkPicc85SKHguYTMCc9D0XbTbkoBIEAeQ4nr2GmXuEQ5tYaO/O\n" +
+        "PYXjk9EfGhikHlnKgC6jITAfMB0GA1UdDgQWBBTtv4rKVwXtXJpyZWlswQL4MAKkazALBgcqhkjO\n" +
+        "OAQDBQADMAAwLQIVAIU4pnnUcMjh2CUvh/B0PSZZTHHvAhQVMhAdwNHOGPSL6sCL19q6UjoN9w==\n" +
+        "-----END CERTIFICATE-----\n";
+        try {
+            CertificateFactory.getInstance("X509").generateCertificates(
+                    new ByteArrayInputStream(cert.getBytes()));
+            throw new Exception("Fail. certificate generation should fail");
+        } catch (CertificateException ce) {
+            ce.printStackTrace();
+            // This is the correct result
+        }
+    }
+}