1 /* 2 * Copyright (c) 2013, 2016, 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 org.openjdk.buildtools.makejavasecurity; 27 28 import java.io.*; 29 import java.nio.file.Files; 30 import java.nio.file.Paths; 31 import java.util.*; 32 33 /** 34 * Builds the java.security file, including 35 * 36 * 1. Adds additional packages to the package.access and 37 * package.definition security properties. 38 * 2. Filter out platform-unrelated parts. 39 * 3. Set the JCE jurisdiction policy directory. 40 * 41 * In order to easily maintain platform-related entries, every item 42 * (including the last line) in package.access and package.definition 43 * MUST end with ',\'. A blank line MUST exist after the last line. 44 */ 45 public class MakeJavaSecurity { 46 47 private static final String PKG_ACC = "package.access"; 48 private static final String PKG_DEF = "package.definition"; 49 private static final int PKG_ACC_INDENT = 15; 50 private static final int PKG_DEF_INDENT = 19; 51 52 public static void main(String[] args) throws Exception { 53 54 if (args.length < 5) { 55 System.err.println("Usage: java MakeJavaSecurity " + 56 "[input java.security file name] " + 57 "[output java.security file name] " + 58 "[openjdk target os] " + 59 "[openjdk target cpu architecture]" + 60 "[JCE jurisdiction policy directory]" + 61 "[more restricted packages file name?]"); 62 63 System.exit(1); 64 } 65 66 // more restricted packages 67 List<String> extraLines; 68 if (args.length == 6) { 69 extraLines = Files.readAllLines(Paths.get(args[5])); 70 } else { 71 extraLines = Collections.emptyList(); 72 } 73 74 List<String> lines = new ArrayList<>(); 75 76 // read raw java.security and add more restricted packages 77 try (FileReader fr = new FileReader(args[0]); 78 BufferedReader br = new BufferedReader(fr)) { 79 // looking for pkg access properties 80 String line = br.readLine(); 81 while (line != null) { 82 if (line.startsWith(PKG_ACC)) { 83 addPackages(br, lines, line, PKG_ACC_INDENT, extraLines); 84 } else if (line.startsWith(PKG_DEF)) { 85 addPackages(br, lines, line, PKG_DEF_INDENT, extraLines); 86 } else { 87 lines.add(line); 88 } 89 line = br.readLine(); 90 } 91 } 92 93 // Filter out platform-unrelated ones. We only support 94 // #ifdef, #ifndef, #else, and #endif. Nesting not supported (yet). 95 int mode = 0; // 0: out of block, 1: in match, 2: in non-match 96 Iterator<String> iter = lines.iterator(); 97 while (iter.hasNext()) { 98 String line = iter.next(); 99 if (line.startsWith("#endif")) { 100 mode = 0; 101 iter.remove(); 102 } else if (line.startsWith("#ifdef ")) { 103 if (line.indexOf('-') > 0) { 104 mode = line.endsWith(args[2]+"-"+args[3]) ? 1 : 2; 105 } else { 106 mode = line.endsWith(args[2]) ? 1 : 2; 107 } 108 iter.remove(); 109 } else if (line.startsWith("#ifndef ")) { 110 if (line.indexOf('-') > 0) { 111 mode = line.endsWith(args[2]+"-"+args[3]) ? 2 : 1; 112 } else { 113 mode = line.endsWith(args[2]) ? 2 : 1; 114 } 115 iter.remove(); 116 } else if (line.startsWith("#else")) { 117 if (mode == 0) { 118 throw new IllegalStateException("#else not in #if block"); 119 } 120 mode = 3 - mode; 121 iter.remove(); 122 } else { 123 if (mode == 2) iter.remove(); 124 } 125 } 126 127 // Update .tbd to .1, .2, etc. 128 Map<String,Integer> count = new HashMap<>(); 129 for (int i=0; i<lines.size(); i++) { 130 String line = lines.get(i); 131 int index = line.indexOf(".tbd"); 132 if (index >= 0) { 133 String prefix = line.substring(0, index); 134 int n = count.getOrDefault(prefix, 1); 135 count.put(prefix, n+1); 136 lines.set(i, prefix + "." + n + line.substring(index+4)); 137 } 138 } 139 140 // Set the JCE policy value 141 for (int i = 0; i < lines.size(); i++) { 142 String line = lines.get(i); 143 int index = line.indexOf("crypto.policydir-tbd"); 144 if (index >= 0) { 145 String prefix = line.substring(0, index); 146 lines.set(i, prefix + args[4]); 147 } 148 } 149 150 // Clean up the last line of PKG_ACC and PKG_DEF blocks. 151 // Not really necessary since a blank line follows. 152 boolean inBlock = false; 153 for (int i=0; i<lines.size(); i++) { 154 String line = lines.get(i); 155 if (line.startsWith(PKG_ACC) || line.startsWith(PKG_DEF)) { 156 inBlock = true; 157 } 158 if (inBlock) { 159 if (line.isEmpty()) { 160 String lastLine = lines.get(i-1); 161 lines.set(i-1, lastLine.substring(0, lastLine.length()-2)); 162 inBlock = false; 163 } 164 } 165 } 166 167 Files.write(Paths.get(args[1]), lines); 168 } 169 170 private static void addPackages(BufferedReader br, List<String> lines, 171 String line, int numSpaces, 172 List<String> args) throws IOException { 173 // parse property until EOL, not including line breaks 174 boolean first = true; 175 while (line != null && !line.isEmpty()) { 176 if (!line.startsWith("#")) { 177 if (!line.endsWith(",\\") || 178 (!first && line.contains("="))) { 179 throw new IOException("Invalid line: " + line); 180 } 181 } 182 lines.add(line); 183 line = br.readLine(); 184 first = false; 185 } 186 // add new packages, one per line 187 for (String arg: args) { 188 if (arg.startsWith("#")) { 189 lines.add(arg); 190 } else { 191 lines.add(String.format("%"+numSpaces+"s", "") + arg + ",\\"); 192 } 193 } 194 if (line != null) { 195 lines.add(line); 196 } 197 } 198 }