Path: blob/master/test/jdk/sun/security/tools/keytool/ExtOptionCamelCase.java
41152 views
/*1* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 8231950 825749726* @summary keytool -ext camel-case shorthand not working27* @modules java.base/sun.security.tools.keytool28* java.base/sun.security.tools.keytool:open29* java.base/sun.security.util30* java.base/sun.security.x50931* @compile -XDignore.symbol.file ExtOptionCamelCase.java32* @run main ExtOptionCamelCase33*/3435import sun.security.tools.keytool.Main;36import sun.security.util.DerValue;37import sun.security.x509.BasicConstraintsExtension;38import sun.security.x509.CertificateExtensions;39import sun.security.x509.Extension;40import sun.security.x509.KeyIdentifier;41import sun.security.x509.KeyUsageExtension;4243import java.io.ByteArrayOutputStream;44import java.lang.reflect.Constructor;45import java.lang.reflect.InvocationTargetException;46import java.lang.reflect.Method;47import java.security.KeyPairGenerator;48import java.security.PublicKey;49import java.util.List;5051public class ExtOptionCamelCase {52static Method createV3Extensions;53static Constructor<Main> ctor;54static PublicKey pk;55static Method oneOf;5657public static void main(String[] args) throws Exception {5859prepare();6061// Unseen ext name62testCreateFail("abc");6364// camelCase match, both cases work65testCreate("bc", BasicConstraintsExtension.class);66testCreate("BC", BasicConstraintsExtension.class);6768// Prefix match69testCreate("BasicC", BasicConstraintsExtension.class);7071// Ambiguous, digitalSignature or dataEncipherment?72testCreateFail("ku=d");7374// prefix match75testCreate("ku:c=dig", KeyUsageExtension.class,76x -> x.get(KeyUsageExtension.DIGITAL_SIGNATURE));7778// camelCase match79testCreate("ku=kE", KeyUsageExtension.class,80x -> x.get(KeyUsageExtension.KEY_ENCIPHERMENT));8182// camelCase match must be only 1st+CAPITALs83testCreateFail("ku=KeUs");8485// camelCase match, must be only 1st + all CAPITALs86testCreate("ku=kCS", KeyUsageExtension.class,87x -> x.get(KeyUsageExtension.KEY_CERTSIGN));8889// ... not all CAPITALs90testCreateFail("ku=kC");9192// ... has lowercase letters93testCreateFail("ku=keCeSi");9495// Ambiguous, keyAgreement or keyCertSign96testCreateFail("ku:c=ke");9798// camelCase natch99testCreate("ku:c=dE", KeyUsageExtension.class,100x -> x.get(KeyUsageExtension.DATA_ENCIPHERMENT));101// prefix match102testCreate("ku:c=de", KeyUsageExtension.class,103x -> x.get(KeyUsageExtension.DECIPHER_ONLY));104105// camelCase match106testCreate("ku:c=kA", KeyUsageExtension.class,107x -> x.get(KeyUsageExtension.KEY_AGREEMENT));108109// camelCase match, fallback110testCreate("ku:c=ka", KeyUsageExtension.class,111x -> x.get(KeyUsageExtension.KEY_AGREEMENT));112113// Testing oneOf() directly114testOneOf("a", -1, "b", "c"); // -1 means not found115testOneOf("a", -2, "ab", "ac"); // -2 means ambiguous116117testOneOf("a", 0, "a", "ac"); //exact match118testOneOf("a", 0, "a", "b");119testOneOf("ac", 1, "a", "ac");120121testOneOf("a", 0, "abc", "bcd");122testOneOf("ab", 0, "abc", "ABC");123testOneOf("ab", 0, "abc", "aBC");124testOneOf("ab", 0, "abc", "Abc");125testOneOf("AB", 1, "abc", "ABC");126testOneOf("aB", 0, "abcBcd", "abcDef");127testOneOf("ab", -2, "abcBcd", "abcDef");128testOneOf("aB", -2, "abcBcdEfg", "abcDef");129130testOneOf("ab", 0, "abcDef", "axyBuv");131testOneOf("aB", 1, "abcDef", "axyBuv");132testOneOf("a", -2, "abcDef", "axyBuv");133134testOneOf("aBC", -1, "a12BxyCuvDmn"); // 12 is not removed135testOneOf("a12BCD", 0, "a12BxyCuvDmn");136testOneOf("a12BC", -1, "a12BxyCuvDmn"); // must be full137138// Fallback139testOneOf("bc", 0, "BasicConstraints");140testOneOf("BC", 0, "BasicConstraints");141testOneOf("BasicConstraints", 0, "BasicConstraints");142testOneOf("basicconstraints", 0, "BasicConstraints");143testOneOf("Basic", 0, "BasicConstraints");144testOneOf("basic", 0, "BasicConstraints");145146testOneOf("BaCo", -1, "BasicConstraints");147}148149// Expose some private methods150static void prepare() throws Exception {151createV3Extensions = Main.class.getDeclaredMethod(152"createV3Extensions",153CertificateExtensions.class,154CertificateExtensions.class,155List.class,156PublicKey.class,157KeyIdentifier.class);158createV3Extensions.setAccessible(true);159ctor = Main.class.getDeclaredConstructor();160ctor.setAccessible(true);161KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");162pk = kpg.generateKeyPair().getPublic();163164oneOf = Main.class.getDeclaredMethod(165"oneOf", String.class, String[].class);166oneOf.setAccessible(true);167}168169/**170* Ensures the given type of extension is created with the option171*/172static <T extends Extension> void testCreate(String option, Class<T> clazz)173throws Exception {174testCreate(option, clazz, null);175}176177/**178* Ensures an option is invalid and will be rejected179*/180static <T extends Extension> void testCreateFail(String option)181throws Exception {182testCreate(option, null, null);183}184185/**186* Ensures the given type of extension is created and match the rule187* with the option.188*189* @param option the -ext option provided to keytool190* @param clazz the expected extension to create, null means none191* @param rule a predicate to check if the extension created is acceptable192* @param <T> the extected extension type193* @throws Exception if test result is unexpected194*/195static <T extends Extension> void testCreate(String option, Class<T> clazz,196PredicateWithException<T> rule) throws Exception {197try {198CertificateExtensions exts = (CertificateExtensions)199createV3Extensions.invoke(ctor.newInstance(),200null, null, List.of(option), pk, null);201202// ATTENTION: the extensions created above might contain raw203// extensions (not of a subtype) and we need to store and reload204// it to resolve them to subtypes.205ByteArrayOutputStream bout = new ByteArrayOutputStream();206exts.encode(bout);207exts = new CertificateExtensions(new DerValue(bout.toByteArray()).data);208209if (clazz == null) {210throw new Exception("Should fail");211} else {212for (Extension e : exts.getAllExtensions()) {213if (e.getClass() == clazz) {214if (rule == null || rule.test((T) e)) {215return;216}217}218}219throw new Exception("Unexpected result: " + exts);220}221} catch (InvocationTargetException e) {222if (clazz == null) {223return;224} else {225throw e;226}227}228}229230@FunctionalInterface231interface PredicateWithException<T> {232boolean test(T t) throws Exception;233}234235/**236* Ensures oneOf returns the expected result.237*238* @param s input239* @param expected expected value, -2 if ambiguous, -1 if no match240* @param items existing strings to match241* @throws Exception if test result is unexpected242*/243static void testOneOf(String s, int expected, String... items)244throws Exception {245try {246int res = (int)oneOf.invoke(null, s, items);247if (expected == -2) {248throw new Exception("Should fail");249} else {250if (expected != res) {251throw new Exception(252"Expected " + expected + ", actually " + res);253}254}255} catch (InvocationTargetException e) {256if (expected == -2) {257return;258} else {259throw e;260}261}262}263}264265266