1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8074064 27 * @summary OCSPResponse.SingleResponse objects do not parse singleExtensions 28 * @modules java.base/sun.security.x509 29 * java.base/sun.security.provider.certpath 30 * @run main/othervm OCSPSingleExtensions 31 */ 32 33 import java.io.*; 34 import java.util.*; 35 import java.security.cert.*; 36 37 import sun.security.x509.SerialNumber; 38 import sun.security.provider.certpath.*; 39 40 /* 41 * Tester note: 42 * For this test, all input files should be co-located with the test source 43 * code. All test input data should be in PEM format, and may be commented 44 * with the '#' character at the beginning of any comment line. Most tests were 45 * generated using the "openssl ocsp" utility in server mode and used the same 46 * utility as a client to drive the responses. In rare cases 47 * (ocsp-good-witharchcut.resp, etc.) the test input was manually modified 48 * because openssl's ocsp could not generate data in that format (e.g. a 49 * "good" response with singleExtensions in the SingleResponse structure.) 50 * These tests were created to force the code to walk codepaths reached only 51 * with invalid OCSP data or legal formats that are not easily generated using 52 * the tools at hand. These hand-modified test cases will not verify. 53 */ 54 55 public class OCSPSingleExtensions { 56 public static CertificateFactory CF; 57 public static final File testDir = 58 new File(System.getProperty("test.src", ".")); 59 public static final Base64.Decoder B64D = Base64.getMimeDecoder(); 60 main(String [] args)61 public static void main(String [] args) throws Exception { 62 // Get a CertificateFactory for various tests 63 CF = CertificateFactory.getInstance("X509"); 64 ByteArrayInputStream bais = 65 new ByteArrayInputStream(readFile("int.crt").getBytes()); 66 X509Certificate intCA = (X509Certificate)CF.generateCertificate(bais); 67 System.out.println("Successfully instantiated CA cert \"" + 68 intCA.getSubjectX500Principal() + "\""); 69 70 CertId cid0x1500 = new CertId(intCA, new SerialNumber(0x1500)); 71 boolean noFailures = true; 72 73 OCSPResponse.SingleResponse sr = 74 getSRByFilename("ocsp-good-nonext.resp", cid0x1500); 75 noFailures &= checkSingleExts(sr, 0); 76 77 if (sr.getRevocationTime() != null) { 78 throw new RuntimeException("Oops. revocationTime is non-null " + 79 sr.getRevocationTime()); 80 } else if (sr.getRevocationReason() != null) { 81 throw new RuntimeException("Oops. revocationReason is non-null " + 82 sr.getRevocationReason()); 83 } 84 85 sr = getSRByFilename("ocsp-good-withnext.resp", cid0x1500); 86 noFailures &= checkSingleExts(sr, 0); 87 88 sr = getSRByFilename("ocsp-good-witharchcut.resp", cid0x1500); 89 noFailures &= checkSingleExts(sr, 1); 90 91 sr = getSRByFilename("ocsp-rev-nocerts.resp", cid0x1500); 92 noFailures &= checkSingleExts(sr, 1); 93 94 sr = getSRByFilename("ocsp-rev-nonext-noinv.resp", cid0x1500); 95 noFailures &= checkSingleExts(sr, 0); 96 97 sr = getSRByFilename("ocsp-rev-withnext-noinv.resp", cid0x1500); 98 noFailures &= checkSingleExts(sr, 0); 99 100 sr = getSRByFilename("ocsp-rev-nonext-withinv.resp", cid0x1500); 101 noFailures &= checkSingleExts(sr, 1); 102 103 sr = getSRByFilename("ocsp-rev-withnext-withinv.resp", cid0x1500); 104 noFailures &= checkSingleExts(sr, 1); 105 106 try { 107 sr = getSRByFilename("ocsp-rev-twonext.resp", cid0x1500); 108 System.out.println("FAIL: Allowed two nextUpdate fields"); 109 noFailures = false; 110 } catch (IOException ioe) { 111 System.out.println("Caught expected exception: " + ioe); 112 } 113 114 try { 115 sr = getSRByFilename("ocsp-rev-bad-sr-tag.resp", cid0x1500); 116 System.out.println("FAIL: Allowed invalid singleResponse item"); 117 noFailures = false; 118 } catch (IOException ioe) { 119 System.out.println("Caught expected exception: " + ioe); 120 } 121 122 try { 123 sr = getSRByFilename("ocsp-rev-sr-cont-reverse.resp", cid0x1500); 124 System.out.println("FAIL: Allowed reversed " + 125 "nextUpdate/singleExtensions"); 126 noFailures = false; 127 } catch (IOException ioe) { 128 System.out.println("Caught expected exception: " + ioe); 129 } 130 131 if (!noFailures) { 132 throw new RuntimeException("One or more tests failed"); 133 } 134 } 135 getSRByFilename(String fileName, CertId cid)136 private static OCSPResponse.SingleResponse getSRByFilename(String fileName, 137 CertId cid) throws IOException { 138 byte[] respDER = B64D.decode(readFile(fileName)); 139 OCSPResponse or = new OCSPResponse(respDER); 140 OCSPResponse.SingleResponse sr = or.getSingleResponse(cid); 141 return sr; 142 } 143 readFile(String fileName)144 private static String readFile(String fileName) throws IOException { 145 String filePath = testDir + "/" + fileName; 146 StringBuilder sb = new StringBuilder(); 147 148 try (FileReader fr = new FileReader(filePath); 149 BufferedReader br = new BufferedReader(fr)) { 150 String line; 151 while ((line = br.readLine()) != null) { 152 if (!line.trim().startsWith("#")) { 153 sb.append(line).append("\n"); 154 } 155 } 156 } 157 158 System.out.println("Successfully read " + fileName); 159 return sb.toString(); 160 } 161 checkSingleExts(OCSPResponse.SingleResponse sr, int singleExtCount)162 private static boolean checkSingleExts(OCSPResponse.SingleResponse sr, 163 int singleExtCount) { 164 Map<String, Extension> singleExts; 165 try { 166 singleExts = sr.getSingleExtensions(); 167 } catch (NullPointerException npe) { 168 System.out.println( 169 "Warning: Sent null singleResponse into checkSingleExts"); 170 return false; 171 } 172 173 for (String key : singleExts.keySet()) { 174 System.out.println("singleExtension: " + singleExts.get(key)); 175 } 176 177 if (singleExts.size() != singleExtCount) { 178 System.out.println("Single Extension count mismatch, " + 179 "expected " + singleExtCount + ", got " + 180 singleExts.size()); 181 return false; 182 } else { 183 return true; 184 } 185 } 186 } 187