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 import java.nio.file.Files; 25 import java.nio.file.Path; 26 import java.nio.file.Paths; 27 import java.util.ArrayList; 28 import java.util.LinkedHashMap; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Arrays; 32 import java.io.IOException; 33 import java.lang.module.ModuleDescriptor; 34 import jdk.testlibrary.ProcessTools; 35 import jdk.testlibrary.OutputAnalyzer; 36 import org.testng.annotations.BeforeTest; 37 38 /** 39 * @test 40 * @bug 8130360 41 * @library /lib/testlibrary 42 * @library /java/security/modules 43 * @modules java.base/jdk.internal.module 44 * @build CompilerUtils JarUtils 45 * @summary Test custom security provider module with all possible modular 46 * condition. The test includes different combination of security 47 * client/provider modules interaction with or without service 48 * description. 49 * @run testng SecurityProviderModularTest 50 */ 51 public class SecurityProviderModularTest extends ModularTest { 52 53 private static final Path S_SRC = SRC.resolve("TestSecurityProvider.java"); 54 private static final String S_PKG = "provider"; 55 private static final String S_JAR_NAME = S_PKG + JAR_EXTN; 56 private static final String S_WITH_DESCR_JAR_NAME = S_PKG + DESCRIPTOR 57 + JAR_EXTN; 58 private static final String MS_JAR_NAME = MODULAR + S_PKG + JAR_EXTN; 59 private static final String MS_WITH_DESCR_JAR_NAME = MODULAR + S_PKG 60 + DESCRIPTOR + JAR_EXTN; 61 62 private static final Path C_SRC = SRC.resolve( 63 "TestSecurityProviderClient.java"); 64 private static final String C_PKG = "client"; 65 private static final String C_JAR_NAME = C_PKG + JAR_EXTN; 66 private static final String MCN_JAR_NAME = MODULAR + C_PKG + "N" + JAR_EXTN; 67 private static final String MC_JAR_NAME = MODULAR + C_PKG + JAR_EXTN; 68 69 private static final Path BUILD_DIR = Paths.get(".").resolve("build"); 70 private static final Path COMPILE_DIR = BUILD_DIR.resolve("bin"); 71 private static final Path S_BUILD_DIR = COMPILE_DIR.resolve(S_PKG); 72 private static final Path S_WITH_META_DESCR_BUILD_DIR = COMPILE_DIR.resolve( 73 S_PKG + DESCRIPTOR); 74 private static final Path C_BLD_DIR = COMPILE_DIR.resolve(C_PKG); 75 private static final Path M_BASE_PATH = BUILD_DIR.resolve("mbase"); 76 private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts"); 77 78 private static final Path S_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(S_PKG); 79 private static final Path S_JAR = S_ARTIFACTS_DIR.resolve(S_JAR_NAME); 80 private static final Path S_WITH_DESCRIPTOR_JAR = S_ARTIFACTS_DIR.resolve( 81 S_WITH_DESCR_JAR_NAME); 82 private static final Path MS_JAR = S_ARTIFACTS_DIR.resolve( 83 MS_JAR_NAME); 84 private static final Path MS_WITH_DESCR_JAR = S_ARTIFACTS_DIR.resolve( 85 MS_WITH_DESCR_JAR_NAME); 86 87 private static final Path C_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(C_PKG); 88 private static final Path C_JAR = C_ARTIFACTS_DIR.resolve(C_JAR_NAME); 89 private static final Path MC_JAR = C_ARTIFACTS_DIR.resolve(MC_JAR_NAME); 90 private static final Path MCN_JAR = C_ARTIFACTS_DIR.resolve(MCN_JAR_NAME); 91 92 private static final String MAIN = C_PKG + ".TestSecurityProviderClient"; 93 private static final String S_INTERFACE = "java.security.Provider"; 94 private static final String S_IMPL = S_PKG + ".TestSecurityProvider"; 95 private static final List<String> M_REQUIRED = Arrays.asList("java.base"); 96 private static final Path META_DESCR_PATH = Paths.get("META-INF") 97 .resolve("services").resolve(S_INTERFACE); 98 private static final Path S_META_DESCR_FPATH = S_WITH_META_DESCR_BUILD_DIR 99 .resolve(META_DESCR_PATH); 100 101 private static final boolean WITH_S_DESCR = true; 102 private static final boolean WITHOUT_S_DESCR = false; 103 private static final String PROVIDER_NOT_FOUND_MSG = "Unable to find Test" 104 + " Security Provider"; 105 private static final String CAN_NOT_ACCESS_MSG = "cannot access class"; 106 private static final String NO_FAILURE = null; 107 private static final String SERVICE_LOADER = "SERVICE_LOADER"; 108 private static final String CLASS_LOADER = "CLASS_LOADER"; 109 private static final String SECURITY_PROP = "SECURITY_PROP"; 110 private static final List<String> MECHANISMS = Arrays.asList(SERVICE_LOADER, 111 CLASS_LOADER, SECURITY_PROP); 112 private static final Path SECURE_PROP_EXTN = Paths.get("./java.secure.ext"); 113 114 /** 115 * Generates Test specific input parameters. 116 */ 117 @Override 118 public Object[][] getTestInput() { 119 120 List<List<Object>> params = new ArrayList<>(); 121 MECHANISMS.stream().forEach((mechanism) -> { 122 boolean useCLoader = CLASS_LOADER.equals(mechanism); 123 boolean useSLoader = SERVICE_LOADER.equals(mechanism); 124 String[] args = new String[]{mechanism}; 125 // PARAMETER ORDERS - 126 // Client Module Type, Service Module Type, 127 // If Service META Descriptor Required, 128 // Expected Failure message, mechanism used to find the provider 129 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, 130 WITH_S_DESCR, NO_FAILURE, args)); 131 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, 132 WITHOUT_S_DESCR, NO_FAILURE, args)); 133 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, 134 WITH_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG 135 : NO_FAILURE), args)); 136 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, 137 WITHOUT_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG 138 : PROVIDER_NOT_FOUND_MSG), args)); 139 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, 140 WITH_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG 141 : NO_FAILURE), args)); 142 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, 143 WITHOUT_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG 144 : ((useSLoader) ? PROVIDER_NOT_FOUND_MSG 145 : NO_FAILURE)), args)); 146 147 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, 148 WITH_S_DESCR, NO_FAILURE, args)); 149 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, 150 WITHOUT_S_DESCR, NO_FAILURE, args)); 151 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, 152 WITH_S_DESCR, NO_FAILURE, args)); 153 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, 154 WITHOUT_S_DESCR, 155 (useCLoader) ? NO_FAILURE : PROVIDER_NOT_FOUND_MSG, args)); 156 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, 157 WITH_S_DESCR, NO_FAILURE, args)); 158 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, 159 WITHOUT_S_DESCR, ((useSLoader) ? PROVIDER_NOT_FOUND_MSG 160 : NO_FAILURE), args)); 161 162 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, 163 WITH_S_DESCR, NO_FAILURE, args)); 164 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, 165 WITHOUT_S_DESCR, NO_FAILURE, args)); 166 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, 167 WITH_S_DESCR, NO_FAILURE, args)); 168 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, 169 WITHOUT_S_DESCR, 170 (useCLoader) ? NO_FAILURE : PROVIDER_NOT_FOUND_MSG, args)); 171 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, 172 WITH_S_DESCR, NO_FAILURE, args)); 173 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, 174 WITHOUT_S_DESCR, ((useSLoader) ? PROVIDER_NOT_FOUND_MSG 175 : NO_FAILURE), args)); 176 }); 177 return params.stream().map(p -> p.toArray()).toArray(Object[][]::new); 178 } 179 180 /** 181 * Pre-compile and generate the artifacts required to run this test before 182 * running each test cases. 183 */ 184 @BeforeTest 185 public void buildArtifacts() { 186 187 boolean done = true; 188 try { 189 190 done &= CompilerUtils.compile(S_SRC, S_BUILD_DIR); 191 done &= CompilerUtils.compile(S_SRC, S_WITH_META_DESCR_BUILD_DIR); 192 done &= createMetaInfServiceDescriptor(S_META_DESCR_FPATH, S_IMPL); 193 // Generate modular/regular jars with(out) META-INF 194 // service descriptor 195 generateJar(true, MODULE_TYPE.EXPLICIT, MS_JAR, S_BUILD_DIR, false); 196 generateJar(true, MODULE_TYPE.EXPLICIT, MS_WITH_DESCR_JAR, 197 S_WITH_META_DESCR_BUILD_DIR, false); 198 generateJar(true, MODULE_TYPE.UNNAMED, S_JAR, S_BUILD_DIR, false); 199 generateJar(true, MODULE_TYPE.UNNAMED, S_WITH_DESCRIPTOR_JAR, 200 S_WITH_META_DESCR_BUILD_DIR, false); 201 // Compile client source codes. 202 done &= CompilerUtils.compile(C_SRC, C_BLD_DIR, "-cp", 203 S_JAR.toFile().getCanonicalPath()); 204 // Generate modular client jar with explicit dependency 205 generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BLD_DIR, true); 206 // Generate modular client jar without any dependency 207 generateJar(false, MODULE_TYPE.EXPLICIT, MCN_JAR, C_BLD_DIR, false); 208 // Generate regular client jar 209 generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BLD_DIR, false); 210 System.out.format("%nArtifacts generated successfully? %s", done); 211 if (!done) { 212 throw new RuntimeException("Artifacts generation failed"); 213 } 214 } catch (IOException e) { 215 throw new RuntimeException(e); 216 } 217 } 218 219 /** 220 * Generate modular/regular jar based on module type for this test. 221 */ 222 private void generateJar(boolean isService, MODULE_TYPE moduleType, 223 Path jar, Path compilePath, boolean depends) throws IOException { 224 225 ModuleDescriptor mDescriptor = null; 226 if (isService) { 227 mDescriptor = generateModuleDescriptor(isService, moduleType, S_PKG, 228 S_PKG, S_INTERFACE, S_IMPL, null, M_REQUIRED, depends); 229 } else { 230 mDescriptor = generateModuleDescriptor(isService, moduleType, C_PKG, 231 C_PKG, S_INTERFACE, null, S_PKG, M_REQUIRED, depends); 232 } 233 generateJar(mDescriptor, jar, compilePath); 234 } 235 236 /** 237 * Holds Logic for the test. This method will get called with each test 238 * parameter. 239 */ 240 @Override 241 public OutputAnalyzer executeTestClient(MODULE_TYPE cModuleType, 242 Path cJarPath, MODULE_TYPE sModuletype, Path sJarPath, 243 String... args) throws Exception { 244 245 OutputAnalyzer output = null; 246 try { 247 // For automated/explicit module types, copy the corresponding 248 // jars to module base folder, which will be considered as 249 // module base path during execution. 250 if (!(cModuleType == MODULE_TYPE.UNNAMED 251 && sModuletype == MODULE_TYPE.UNNAMED)) { 252 copyJarsToModuleBase(cModuleType, cJarPath, M_BASE_PATH); 253 copyJarsToModuleBase(sModuletype, sJarPath, M_BASE_PATH); 254 } 255 256 System.out.format("%nExecuting java client with required" 257 + " custom security provider in class/module path."); 258 String mName = getModuleName(cModuleType, cJarPath, C_PKG); 259 Path cmBasePath = (cModuleType != MODULE_TYPE.UNNAMED 260 || sModuletype != MODULE_TYPE.UNNAMED) ? M_BASE_PATH : null; 261 String cPath = buildClassPath(cModuleType, cJarPath, sModuletype, 262 sJarPath); 263 264 Map<String, String> vmArgs = getVMArgs(sModuletype, 265 getModuleName(sModuletype, sJarPath, S_PKG), args); 266 output = ProcessTools.executeTestJava( 267 getJavaCommand(cmBasePath, cPath, mName, MAIN, vmArgs, 268 args)).outputTo(System.out).errorTo(System.out); 269 } finally { 270 // Clean module path to hold required jars for next run. 271 cleanModuleBasePath(M_BASE_PATH); 272 } 273 return output; 274 } 275 276 /** 277 * Decide the pre-generated client/service jar path for each test case 278 * based on client/service module type. 279 */ 280 @Override 281 public Path findJarPath(boolean isService, MODULE_TYPE moduleType, 282 boolean addMetaDesc, boolean dependsOnServiceModule) { 283 if (isService) { 284 if (moduleType == MODULE_TYPE.EXPLICIT) { 285 if (addMetaDesc) { 286 return MS_WITH_DESCR_JAR; 287 } else { 288 return MS_JAR; 289 } 290 } else { 291 if (addMetaDesc) { 292 return S_WITH_DESCRIPTOR_JAR; 293 } else { 294 return S_JAR; 295 } 296 } 297 } else { 298 // Choose corresponding client jar to use dependent module 299 if (moduleType == MODULE_TYPE.EXPLICIT) { 300 if (dependsOnServiceModule) { 301 return MC_JAR; 302 } else { 303 return MCN_JAR; 304 } 305 } else { 306 return C_JAR; 307 } 308 } 309 } 310 311 /** 312 * VM argument required for the test. 313 */ 314 private Map<String, String> getVMArgs(MODULE_TYPE sModuletype, 315 String addModName, String... args) throws IOException { 316 final Map<String, String> vmArgs = new LinkedHashMap<>(); 317 vmArgs.put("-Duser.language=", "en"); 318 vmArgs.put("-Duser.region=", "US"); 319 if (addModName != null && sModuletype == MODULE_TYPE.AUTO) { 320 vmArgs.put("--add-modules=", addModName); 321 } 322 // If mechanism selected to find the provider through 323 // Security.getProvider() then use providerName/ProviderClassName based 324 // on modular/regular provider jar in security configuration file. 325 if (args != null && args.length > 0 && SECURITY_PROP.equals(args[0])) { 326 if (sModuletype == MODULE_TYPE.UNNAMED) { 327 Files.write(SECURE_PROP_EXTN, ("security.provider.10=" + S_IMPL) 328 .getBytes()); 329 } else { 330 Files.write(SECURE_PROP_EXTN, "security.provider.10=TEST" 331 .getBytes()); 332 } 333 vmArgs.put("-Djava.security.properties=", SECURE_PROP_EXTN.toFile() 334 .getCanonicalPath()); 335 } 336 return vmArgs; 337 } 338 339 }