1 /* 2 * Copyright (c) 2019, 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 import java.util.List; 25 import java.util.regex.Matcher; 26 import java.util.regex.Pattern; 27 import java.util.stream.Collectors; 28 29 import jdk.jpackage.test.TKit; 30 import jdk.jpackage.test.Executor; 31 32 import jdk.incubator.jpackage.internal.MacCertificate; 33 34 public class SigningCheck { 35 36 public static void checkCertificates() { 37 List<String> result = findCertificate(SigningBase.APP_CERT, SigningBase.KEYCHAIN); 38 String key = findKey(SigningBase.APP_CERT, result); 39 validateCertificate(key); 40 validateCertificateTrust(SigningBase.APP_CERT); 41 42 result = findCertificate(SigningBase.INSTALLER_CERT, SigningBase.KEYCHAIN); 43 key = findKey(SigningBase.INSTALLER_CERT, result); 44 validateCertificate(key); 45 validateCertificateTrust(SigningBase.INSTALLER_CERT); 46 } 47 48 private static List<String> findCertificate(String name, String keyChain) { 49 List<String> result = new Executor() 50 .setExecutable("security") 51 .addArguments("find-certificate", "-c", name, "-a", keyChain) 52 .executeAndGetOutput(); 53 54 return result; 55 } 56 57 private static String findKey(String name, List<String> result) { 58 Pattern p = Pattern.compile("\"alis\"<blob>=\"([^\"]+)\""); 59 Matcher m = p.matcher(result.stream().collect(Collectors.joining())); 60 if (!m.find()) { 61 TKit.trace("Did not found a key for '" + name + "'"); 62 return null; 63 } 64 String matchedKey = m.group(1); 65 if (m.find()) { 66 TKit.trace("Found more than one key for '" + name + "'"); 67 return null; 68 } 69 TKit.trace("Using key '" + matchedKey); 70 return matchedKey; 71 } 72 73 private static void validateCertificate(String key) { 74 if (key != null) { 75 MacCertificate certificate = new MacCertificate(key); 76 if (!certificate.isValid()) { 77 TKit.throwSkippedException("Certifcate expired: " + key); 78 } else { 79 return; 80 } 81 } 82 83 TKit.throwSkippedException("Cannot find required certifciates: " + key); 84 } 85 86 private static void validateCertificateTrust(String name) { 87 List<String> result = new Executor() 88 .setExecutable("security") 89 .addArguments("dump-trust-settings") 90 .executeAndGetOutput(); 91 result.stream().forEachOrdered(TKit::trace); 92 TKit.assertTextStream(name) 93 .predicate((line, what) -> line.trim().endsWith(what)) 94 .orElseThrow(() -> TKit.throwSkippedException( 95 "Certifcate not trusted by current user: " + name)) 96 .apply(result.stream()); 97 } 98 99 }