1 /* 2 * Copyright (c) 2016, 2018, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.packager.internal.mac; 27 28 import jdk.packager.internal.IOUtils; 29 import jdk.packager.internal.Log; 30 31 import java.io.BufferedOutputStream; 32 import java.io.BufferedReader; 33 import java.io.ByteArrayInputStream; 34 import java.io.ByteArrayOutputStream; 35 import java.io.File; 36 import java.io.FileOutputStream; 37 import java.io.IOException; 38 import java.io.InputStreamReader; 39 import java.io.PrintStream; 40 import java.text.DateFormat; 41 import java.text.ParseException; 42 import java.text.SimpleDateFormat; 43 import java.util.ArrayList; 44 import java.util.Calendar; 45 import java.util.Date; 46 import java.util.List; 47 import java.util.Locale; 48 49 final public class MacCertificate { 50 private final String certificate; 51 private final boolean verbose; 52 53 public MacCertificate(String certificate) { 54 this.certificate = certificate; 55 this.verbose = false; 56 } 57 58 public MacCertificate(String certificate, boolean verbose) { 59 this.certificate = certificate; 60 this.verbose = verbose; 61 } 62 63 public boolean isValid() { 64 return verifyCertificate(this.certificate, verbose); 65 } 66 67 private static File findCertificate(String certificate, boolean verbose) { 68 File result = null; 69 70 List<String> args = new ArrayList<>(); 71 args.add("security"); 72 args.add("find-certificate"); 73 args.add("-c"); 74 args.add(certificate); 75 args.add("-a"); 76 args.add("-p"); 77 78 try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); 79 PrintStream ps = new PrintStream(baos)) { 80 ProcessBuilder security = new ProcessBuilder(args); 81 IOUtils.exec(security, verbose, false, ps); 82 83 File output = File.createTempFile("tempfile", ".tmp"); 84 PrintStream p = new PrintStream( 85 new BufferedOutputStream( 86 new FileOutputStream(output, true))); 87 BufferedReader bfReader = new BufferedReader( 88 new InputStreamReader( 89 new ByteArrayInputStream(baos.toByteArray()))); 90 String line = null; 91 92 while((line = bfReader.readLine()) != null){ 93 p.println(line); 94 } 95 96 p.close(); 97 result = output; 98 } 99 catch (IOException ignored) {} 100 101 return result; 102 } 103 104 private static Date findCertificateDate(String filename, boolean verbose) { 105 Date result = null; 106 107 List<String> args = new ArrayList<>(); 108 args.add("/usr/bin/openssl"); 109 args.add("x509"); 110 args.add("-noout"); 111 args.add("-enddate"); 112 args.add("-in"); 113 args.add(filename); 114 115 try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); 116 PrintStream ps = new PrintStream(baos)) { 117 ProcessBuilder security = new ProcessBuilder(args); 118 IOUtils.exec(security, verbose, false, ps); 119 String output = baos.toString(); 120 output = output.substring(output.indexOf("=") + 1); 121 DateFormat df = new SimpleDateFormat( 122 "MMM dd kk:mm:ss yyyy z", Locale.ENGLISH); 123 result = df.parse(output); 124 } catch (IOException | ParseException ex) { 125 Log.debug(ex); 126 } 127 128 return result; 129 } 130 131 private static boolean verifyCertificate( 132 String certificate, boolean verbose) { 133 boolean result = false; 134 135 try { 136 File file = null; 137 Date certificateDate = null; 138 139 try { 140 file = findCertificate(certificate, verbose); 141 142 if (file != null) { 143 certificateDate = findCertificateDate( 144 file.getCanonicalPath(), verbose); 145 } 146 } 147 finally { 148 if (file != null) { 149 file.delete(); 150 } 151 } 152 153 if (certificateDate != null) { 154 Calendar c = Calendar.getInstance(); 155 Date today = c.getTime(); 156 157 if (certificateDate.after(today)) { 158 result = true; 159 } 160 } 161 } 162 catch (IOException ignored) {} 163 164 return result; 165 } 166 }