Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8280890: Cannot use '-Djava.system.class.loader' with class loader in signed JAR #65

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 0 additions & 13 deletions src/java.base/share/classes/sun/security/tools/keytool/Main.java
Expand Up @@ -59,8 +59,6 @@
import java.security.spec.ECParameterSpec;
import java.text.Collator;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
Expand Down Expand Up @@ -4848,17 +4846,6 @@ private void checkWeakConstraint(String label, String sigAlg, Key key,
"Unable.to.parse.denyAfter.string.in.exception.message"));
}

SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
Date dateObj = null;
try {
dateObj = formatter.parse(denyAfterDate);
} catch (ParseException e2) {
throw new Exception(rb.getString(
"Unable.to.parse.denyAfter.string.in.exception.message"));
}
formatter = new SimpleDateFormat("yyyy-MM-dd");
denyAfterDate = formatter.format(dateObj);

weakWarnings.add(String.format(
rb.getString("whose.sigalg.usagesignedjar"), label, sigAlg,
denyAfterDate));
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -40,9 +40,12 @@
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.NamedParameterSpec;
import java.security.spec.PSSParameterSpec;
import java.time.DateTimeException;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
Expand All @@ -52,7 +55,6 @@
import java.util.Set;
import java.util.Collection;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -691,41 +693,30 @@ public void permits(ConstraintsParameters cp)
* timezone.
*/
private static class DenyAfterConstraint extends Constraint {
private Date denyAfterDate;
private ZonedDateTime zdt;
private Instant denyAfterDate;

DenyAfterConstraint(String algo, int year, int month, int day) {
Calendar c;

algorithm = algo;

if (debug != null) {
debug.println("DenyAfterConstraint read in as: year " +
debug.println("DenyAfterConstraint read in as: year " +
year + ", month = " + month + ", day = " + day);
}

c = new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("GMT"))
.setDate(year, month - 1, day).build();

if (year > c.getActualMaximum(Calendar.YEAR) ||
year < c.getActualMinimum(Calendar.YEAR)) {
throw new IllegalArgumentException(
"Invalid year given in constraint: " + year);
}
if ((month - 1) > c.getActualMaximum(Calendar.MONTH) ||
(month - 1) < c.getActualMinimum(Calendar.MONTH)) {
throw new IllegalArgumentException(
"Invalid month given in constraint: " + month);
}
if (day > c.getActualMaximum(Calendar.DAY_OF_MONTH) ||
day < c.getActualMinimum(Calendar.DAY_OF_MONTH)) {
try {
zdt = ZonedDateTime
.of(year, month, day, 0, 0, 0, 0, ZoneId.of("GMT"));
denyAfterDate = zdt.toInstant();
} catch (DateTimeException dte) {
throw new IllegalArgumentException(
"Invalid Day of Month given in constraint: " + day);
"Invalid denyAfter date", dte);
}

denyAfterDate = c.getTime();
if (debug != null) {
debug.println("DenyAfterConstraint date set to: " +
denyAfterDate);
zdt.toLocalDate());
}
}

Expand All @@ -740,23 +731,22 @@ private static class DenyAfterConstraint extends Constraint {
@Override
public void permits(ConstraintsParameters cp)
throws CertPathValidatorException {
Date currentDate;
String errmsg;
Instant currentDate;

if (cp.getDate() != null) {
currentDate = cp.getDate();
currentDate = cp.getDate().toInstant();
} else {
currentDate = new Date();
currentDate = Instant.now();
}

if (!denyAfterDate.after(currentDate)) {
if (!denyAfterDate.isAfter(currentDate)) {
if (next(cp)) {
return;
}
throw new CertPathValidatorException(
"denyAfter constraint check failed: " + algorithm +
" used with Constraint date: " +
denyAfterDate + "; params date: " +
zdt.toLocalDate() + "; params date: " +
currentDate + cp.extendedExceptionMsg(),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
Expand All @@ -775,7 +765,7 @@ public boolean permits(Key key) {
debug.println("DenyAfterConstraints.permits(): " + algorithm);
}

return denyAfterDate.after(new Date());
return denyAfterDate.isAfter(Instant.now());
}
}

Expand Down
43 changes: 43 additions & 0 deletions test/jdk/java/security/SignedJar/CustomClassLoader.java
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

import java.io.IOException;
import java.io.InputStream;

public class CustomClassLoader extends ClassLoader {

public CustomClassLoader(ClassLoader parent) {
super(parent);
}

@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
try (InputStream is = getClass().getClassLoader()
.getResourceAsStream(name + ".class")) {
byte[] buf = is.readAllBytes();
return defineClass(name, buf, 0, buf.length);
} catch (IOException e) {
throw new ClassNotFoundException(e.getMessage());
}
}
}
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/**
* @test
* @bug 8280890
* @library /test/lib
* @build SignedJarWithCustomClassLoader CustomClassLoader
* @run main/othervm SignedJarWithCustomClassLoader
* @summary Make sure java.system.class.loader property can be used when custom
* class loader is inside signed jar
*/

import java.nio.file.Path;
import java.nio.file.Paths;

import jdk.test.lib.SecurityTools;
import jdk.test.lib.compiler.InMemoryJavaCompiler;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.util.JarUtils;

public class SignedJarWithCustomClassLoader {

public static void main(String[] args) throws Exception {

// compile the Main program
String main = "public class Main {\n" +
" public static void main(String[] args) {}\n" +
"}\n";
String testClasses = System.getProperty("test.classes", "");
ClassFileInstaller.writeClassToDisk("Main",
InMemoryJavaCompiler.compile("Main", main),
testClasses);

// create the jar file
Path classes = Paths.get(testClasses);
JarUtils.createJarFile(Paths.get("test.jar"), classes,
classes.resolve("CustomClassLoader.class"),
classes.resolve("Main.class"));

// create signer's keypair
SecurityTools.keytool("-genkeypair -keyalg RSA -keystore ks " +
"-storepass changeit -dname CN=test -alias test")
.shouldHaveExitValue(0);

// sign jar
SecurityTools.jarsigner("-keystore ks -storepass changeit " +
"-signedjar signed.jar test.jar test")
.shouldHaveExitValue(0);

// run app with system class loader set to custom classloader
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-cp", "signed.jar",
"-Djava.system.class.loader=CustomClassLoader", "Main");
ProcessTools.executeProcess(pb)
.shouldHaveExitValue(0);

// sign jar again, but this time with SHA-1 which is disabled
SecurityTools.jarsigner("-keystore ks -storepass changeit " +
"-digestalg SHA-1 -sigalg SHA1withRSA " +
"-signedjar signed.jar test.jar test")
.shouldHaveExitValue(0);

// run app again, should still succeed even though SHA-1 is disabled
pb = ProcessTools.createJavaProcessBuilder(
"-cp", "signed.jar",
"-Djava.system.class.loader=CustomClassLoader", "Main");
ProcessTools.executeProcess(pb)
.shouldHaveExitValue(0);
}
}