提交 67d7f66d 编写于 作者: A aefimov

Merge

...@@ -857,6 +857,13 @@ c9254e01820639526f803dbe05080fce0d33db98 jdk8u162-b08 ...@@ -857,6 +857,13 @@ c9254e01820639526f803dbe05080fce0d33db98 jdk8u162-b08
95df717479b19f5ea244afc67434827f2f851287 jdk8u162-b11 95df717479b19f5ea244afc67434827f2f851287 jdk8u162-b11
ddae5cb11d6c04130b8002b852bc7f80e0c8bcd2 jdk8u162-b12 ddae5cb11d6c04130b8002b852bc7f80e0c8bcd2 jdk8u162-b12
8e40acfcc41a631f5922824712d4336742652eac jdk8u162-b31 8e40acfcc41a631f5922824712d4336742652eac jdk8u162-b31
c00bdbbd9a77150f565298af9c305d7e6863eb59 jdk8u162-b32
70a653814e61a5552312345308b85330fa8f27bc jdk8u162-b33
f1f949ac13549c6fb3766279848539b124ad835e jdk8u162-b34
b3de2b1e82fb2427cd40bb230aa26d9b7d8fb09c jdk8u162-b35
e03fff22900242d92a97839a9c095bb106bdc68f jdk8u162-b36
19696e8204b0e77e0f10af106c384b7ba6dd5bda jdk8u162-b37
305c40e81a6fd59699036d4c35d8994f8501f116 jdk8u162-b38
b6195815c4bbbf275f1aefd337d805eb66f2b5b8 jdk8u171-b00 b6195815c4bbbf275f1aefd337d805eb66f2b5b8 jdk8u171-b00
f1792a59f1fa20e47fe5d4561754012440564bec jdk8u171-b01 f1792a59f1fa20e47fe5d4561754012440564bec jdk8u171-b01
cac020298633fc736f5e21afddf00145665ef0a7 jdk8u171-b02 cac020298633fc736f5e21afddf00145665ef0a7 jdk8u171-b02
...@@ -875,6 +882,8 @@ ac700f67341a20ddae093c319da1c65e41edcacd jdk8u171-b04 ...@@ -875,6 +882,8 @@ ac700f67341a20ddae093c319da1c65e41edcacd jdk8u171-b04
db8272cb8c99eea536a66c4c368c4bf2bf013a81 jdk8u172-b02 db8272cb8c99eea536a66c4c368c4bf2bf013a81 jdk8u172-b02
bd24ee3a9a0494121fd1d96c308b9738f585001b jdk8u172-b03 bd24ee3a9a0494121fd1d96c308b9738f585001b jdk8u172-b03
cf952b84daa1e74403a4d1df541c0ecca830717d jdk8u172-b04 cf952b84daa1e74403a4d1df541c0ecca830717d jdk8u172-b04
e7e27f446209924f66a4bf86738f3e5f2fbbef5f jdk8u181-b00
a8746b41e23a1deda3d0f41ed2eca3d3a4cc74de jdk8u191-b00
076daed81c0a851f6d13fac538834ac465cdc122 jdk8u172-b05 076daed81c0a851f6d13fac538834ac465cdc122 jdk8u172-b05
94491d0dc59590535339a2ffae510166bb16f34c jdk8u172-b06 94491d0dc59590535339a2ffae510166bb16f34c jdk8u172-b06
7e9eeb74e84beb6d8a6f562441eb7dd0ab0befa9 jdk8u172-b07 7e9eeb74e84beb6d8a6f562441eb7dd0ab0befa9 jdk8u172-b07
...@@ -885,6 +894,16 @@ f52ece1d8708024735f06e7e3bdc771efbc073d0 jdk8u172-b09 ...@@ -885,6 +894,16 @@ f52ece1d8708024735f06e7e3bdc771efbc073d0 jdk8u172-b09
d902fae6241006af3c4cfc4ce82ebcb3efb9d725 jdk8u181-b01 d902fae6241006af3c4cfc4ce82ebcb3efb9d725 jdk8u181-b01
baac18e216fb47b4cfa04169b3c3de58d667de7c jdk8u181-b02 baac18e216fb47b4cfa04169b3c3de58d667de7c jdk8u181-b02
d237c59d14e1c1fb1f750e9cdabcea6e711f4d34 jdk8u181-b03 d237c59d14e1c1fb1f750e9cdabcea6e711f4d34 jdk8u181-b03
f3185b46a35b82727f39d52ac7fad7c4c78ddcdd jdk8u172-b31
0939503b7477ba081484c54f26f177f9a66d92e4 jdk8u172-b32
f4b138a6c95cf17f6138598fe04a90dfe1086bf4 jdk8u172-b33
93b4d31ee70576a45a87607e2f5474d90ba31653 jdk8u172-b34
6b4e239c74929b86b46113e92fe36d355157e235 jdk8u172-b35
010852525831e0e88f622167d615438b82002e1f jdk8u172-b36
9ac2466ffdbb1b9d9005b50aa633a5986617a002 jdk8u172-b37
d902fae6241006af3c4cfc4ce82ebcb3efb9d725 jdk8u181-b01
baac18e216fb47b4cfa04169b3c3de58d667de7c jdk8u181-b02
d237c59d14e1c1fb1f750e9cdabcea6e711f4d34 jdk8u181-b03
6eeca4fb7748e8bdca4afbd6785b04376b1d44cc jdk8u181-b04 6eeca4fb7748e8bdca4afbd6785b04376b1d44cc jdk8u181-b04
f34c24087b0e6f52391f491d6c3a608616d1db2c jdk8u181-b05 f34c24087b0e6f52391f491d6c3a608616d1db2c jdk8u181-b05
076f5fd6258846fce7010a598de2c7583628bb1e jdk8u181-b06 076f5fd6258846fce7010a598de2c7583628bb1e jdk8u181-b06
...@@ -895,6 +914,10 @@ f26f68978e0e7ed0e6e61f9d64fa2d06f1c1a24c jdk8u181-b08 ...@@ -895,6 +914,10 @@ f26f68978e0e7ed0e6e61f9d64fa2d06f1c1a24c jdk8u181-b08
112f3576f12e24d5e35d8d31782698e7d9a8fa52 jdk8u181-b11 112f3576f12e24d5e35d8d31782698e7d9a8fa52 jdk8u181-b11
22e01e7c5c39bfa3f5e2d18be76c7bf0dc71033a jdk8u181-b12 22e01e7c5c39bfa3f5e2d18be76c7bf0dc71033a jdk8u181-b12
0cb452d66676bc1b3824bea4a0c16ac76e58b070 jdk8u181-b13 0cb452d66676bc1b3824bea4a0c16ac76e58b070 jdk8u181-b13
b01c6e5aa43c784fc66465b56227ddd9aa29eee6 jdk8u191-b01
2db6890a956723ac347b573217d91bbbedbb0528 jdk8u191-b02
89e2889d02d2f5dabdeda7f60cf80a8df3100eb4 jdk8u191-b03
94e4769c6d69241f9eb7164a85fc91fc83faab5c jdk8u191-b04
51b6cc7fbd98a87c6cdb5c70b7dbe25bb10e0dd7 jdk8u182-b00 51b6cc7fbd98a87c6cdb5c70b7dbe25bb10e0dd7 jdk8u182-b00
bead1ed7344f2911f5bed83639cf5160596561ef jdk8u192-b00 bead1ed7344f2911f5bed83639cf5160596561ef jdk8u192-b00
444b4528c8ecdd39b5923820fa2ed6d583808b5e jdk8u192-b01 444b4528c8ecdd39b5923820fa2ed6d583808b5e jdk8u192-b01
......
...@@ -548,7 +548,7 @@ public final class DLSSoundbank implements Soundbank { ...@@ -548,7 +548,7 @@ public final class DLSSoundbank implements Soundbank {
long count = riff.readUnsignedInt(); long count = riff.readUnsignedInt();
if (size - 8 != 0) if (size - 8 != 0)
riff.skipBytes(size - 8); riff.skip(size - 8);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
DLSModulator modulator = new DLSModulator(); DLSModulator modulator = new DLSModulator();
...@@ -568,7 +568,7 @@ public final class DLSSoundbank implements Soundbank { ...@@ -568,7 +568,7 @@ public final class DLSSoundbank implements Soundbank {
long count = riff.readUnsignedInt(); long count = riff.readUnsignedInt();
if (size - 8 != 0) if (size - 8 != 0)
riff.skipBytes(size - 8); riff.skip(size - 8);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
DLSModulator modulator = new DLSModulator(); DLSModulator modulator = new DLSModulator();
...@@ -661,7 +661,7 @@ public final class DLSSoundbank implements Soundbank { ...@@ -661,7 +661,7 @@ public final class DLSSoundbank implements Soundbank {
long loops = riff.readInt(); long loops = riff.readInt();
if (size > 20) if (size > 20)
riff.skipBytes(size - 20); riff.skip(size - 20);
for (int i = 0; i < loops; i++) { for (int i = 0; i < loops; i++) {
DLSSampleLoop loop = new DLSSampleLoop(); DLSSampleLoop loop = new DLSSampleLoop();
...@@ -671,7 +671,7 @@ public final class DLSSoundbank implements Soundbank { ...@@ -671,7 +671,7 @@ public final class DLSSoundbank implements Soundbank {
loop.length = riff.readUnsignedInt(); loop.length = riff.readUnsignedInt();
sampleOptions.loops.add(loop); sampleOptions.loops.add(loop);
if (size2 > 16) if (size2 > 16)
riff.skipBytes(size2 - 16); riff.skip(size2 - 16);
} }
} }
......
...@@ -172,49 +172,41 @@ public final class RIFFReader extends InputStream { ...@@ -172,49 +172,41 @@ public final class RIFFReader extends InputStream {
} }
} }
public final long skipBytes(long n) throws IOException { @Override
if (n < 0) public long skip(final long n) throws IOException {
if (n <= 0 || avail == 0) {
return 0; return 0;
long skipped = 0;
while (skipped != n) {
long s = skip(n - skipped);
if (s < 0)
break;
if (s == 0)
Thread.yield();
skipped += s;
} }
return skipped; // will not skip more than
} long remaining = Math.min(n, avail);
while (remaining > 0) {
public long skip(long n) throws IOException { // Some input streams like FileInputStream can return more bytes,
if (avail == 0) // when EOF is reached.
return -1; long ret = Math.min(stream.skip(remaining), remaining);
if (n > avail) { if (ret == 0) {
long len = stream.skip(avail); // EOF or not? we need to check.
if (len != -1) Thread.yield();
filepointer += len; if (stream.read() == -1) {
avail = 0; avail = 0;
return len; break;
} else { }
long ret = stream.skip(n); ret = 1;
if (ret == -1) {
avail = 0;
return -1;
} }
remaining -= ret;
avail -= ret; avail -= ret;
filepointer += ret; filepointer += ret;
return ret;
} }
return n - remaining;
} }
@Override
public int available() { public int available() {
return (int)avail; return (int)avail;
} }
public void finish() throws IOException { public void finish() throws IOException {
if (avail != 0) { if (avail != 0) {
skipBytes(avail); skip(avail);
} }
} }
...@@ -337,6 +329,7 @@ public final class RIFFReader extends InputStream { ...@@ -337,6 +329,7 @@ public final class RIFFReader extends InputStream {
return ch1 + (ch2 << 8) | (ch3 << 16) | (ch4 << 24); return ch1 + (ch2 << 8) | (ch3 << 16) | (ch4 << 24);
} }
@Override
public void close() throws IOException { public void close() throws IOException {
finish(); finish();
if (this == root) if (this == root)
......
...@@ -61,6 +61,25 @@ final class VersionHelper12 extends VersionHelper { ...@@ -61,6 +61,25 @@ final class VersionHelper12 extends VersionHelper {
return loadClass(className, getContextClassLoader()); return loadClass(className, getContextClassLoader());
} }
/**
* Determines whether classes may be loaded from an arbitrary URL code base.
*/
private static final String TRUST_URL_CODEBASE_PROPERTY =
"com.sun.jndi.ldap.object.trustURLCodebase";
private static final String trustURLCodebase =
AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
try {
return System.getProperty(TRUST_URL_CODEBASE_PROPERTY,
"false");
} catch (SecurityException e) {
return "false";
}
}
}
);
/** /**
* Package private. * Package private.
* *
...@@ -79,12 +98,15 @@ final class VersionHelper12 extends VersionHelper { ...@@ -79,12 +98,15 @@ final class VersionHelper12 extends VersionHelper {
*/ */
public Class<?> loadClass(String className, String codebase) public Class<?> loadClass(String className, String codebase)
throws ClassNotFoundException, MalformedURLException { throws ClassNotFoundException, MalformedURLException {
if ("true".equalsIgnoreCase(trustURLCodebase)) {
ClassLoader parent = getContextClassLoader();
ClassLoader cl =
URLClassLoader.newInstance(getUrlArray(codebase), parent);
ClassLoader parent = getContextClassLoader(); return loadClass(className, cl);
ClassLoader cl = } else {
URLClassLoader.newInstance(getUrlArray(codebase), parent); return null;
}
return loadClass(className, cl);
} }
String getJndiProperty(final int i) { String getJndiProperty(final int i) {
......
/* /*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -37,6 +37,7 @@ import java.security.AccessController; ...@@ -37,6 +37,7 @@ import java.security.AccessController;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
import java.io.ObjectStreamField; import java.io.ObjectStreamField;
import java.io.IOException; import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectInputStream.GetField; import java.io.ObjectInputStream.GetField;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
...@@ -1602,8 +1603,11 @@ class InetAddress implements java.io.Serializable { ...@@ -1602,8 +1603,11 @@ class InetAddress implements java.io.Serializable {
} }
GetField gf = s.readFields(); GetField gf = s.readFields();
String host = (String)gf.get("hostName", null); String host = (String)gf.get("hostName", null);
int address= gf.get("address", 0); int address = gf.get("address", 0);
int family= gf.get("family", 0); int family = gf.get("family", 0);
if (family != IPv4 && family != IPv6) {
throw new InvalidObjectException("invalid address family type: " + family);
}
InetAddressHolder h = new InetAddressHolder(host, address, family); InetAddressHolder h = new InetAddressHolder(host, address, family);
UNSAFE.putObject(this, FIELDS_OFFSET, h); UNSAFE.putObject(this, FIELDS_OFFSET, h);
} }
......
/* /*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -319,8 +319,20 @@ public final class NetworkInterface { ...@@ -319,8 +319,20 @@ public final class NetworkInterface {
if (addr == null) { if (addr == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) { if (addr instanceof Inet4Address) {
throw new IllegalArgumentException ("invalid address type"); Inet4Address inet4Address = (Inet4Address) addr;
if (inet4Address.holder.family != InetAddress.IPv4) {
throw new IllegalArgumentException("invalid family type: "
+ inet4Address.holder.family);
}
} else if (addr instanceof Inet6Address) {
Inet6Address inet6Address = (Inet6Address) addr;
if (inet6Address.holder.family != InetAddress.IPv6) {
throw new IllegalArgumentException("invalid family type: "
+ inet6Address.holder.family);
}
} else {
throw new IllegalArgumentException("invalid address type: " + addr);
} }
return getByInetAddress0(addr); return getByInetAddress0(addr);
} }
......
/* /*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -50,6 +50,7 @@ import java.util.jar.Attributes.Name; ...@@ -50,6 +50,7 @@ import java.util.jar.Attributes.Name;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.jar.Manifest; import java.util.jar.Manifest;
import sun.misc.Resource; import sun.misc.Resource;
import sun.misc.SharedSecrets;
import sun.misc.URLClassPath; import sun.misc.URLClassPath;
import sun.net.www.ParseUtil; import sun.net.www.ParseUtil;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
...@@ -486,13 +487,13 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { ...@@ -486,13 +487,13 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
protected Package definePackage(String name, Manifest man, URL url) protected Package definePackage(String name, Manifest man, URL url)
throws IllegalArgumentException throws IllegalArgumentException
{ {
String path = name.replace('.', '/').concat("/");
String specTitle = null, specVersion = null, specVendor = null; String specTitle = null, specVersion = null, specVendor = null;
String implTitle = null, implVersion = null, implVendor = null; String implTitle = null, implVersion = null, implVendor = null;
String sealed = null; String sealed = null;
URL sealBase = null; URL sealBase = null;
Attributes attr = man.getAttributes(path); Attributes attr = SharedSecrets.javaUtilJarAccess()
.getTrustedAttributes(man, name.replace('.', '/').concat("/"));
if (attr != null) { if (attr != null) {
specTitle = attr.getValue(Name.SPECIFICATION_TITLE); specTitle = attr.getValue(Name.SPECIFICATION_TITLE);
specVersion = attr.getValue(Name.SPECIFICATION_VERSION); specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
...@@ -536,10 +537,12 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { ...@@ -536,10 +537,12 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
/* /*
* Returns true if the specified package name is sealed according to the * Returns true if the specified package name is sealed according to the
* given manifest. * given manifest.
*
* @throws SecurityException if the package name is untrusted in the manifest
*/ */
private boolean isSealed(String name, Manifest man) { private boolean isSealed(String name, Manifest man) {
String path = name.replace('.', '/').concat("/"); Attributes attr = SharedSecrets.javaUtilJarAccess()
Attributes attr = man.getAttributes(path); .getTrustedAttributes(man, name.replace('.', '/').concat("/"));
String sealed = null; String sealed = null;
if (attr != null) { if (attr != null) {
sealed = attr.getValue(Name.SEALED); sealed = attr.getValue(Name.SEALED);
......
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -191,10 +191,10 @@ class JarFile extends ZipFile { ...@@ -191,10 +191,10 @@ class JarFile extends ZipFile {
if (manEntry != null) { if (manEntry != null) {
if (verify) { if (verify) {
byte[] b = getBytes(manEntry); byte[] b = getBytes(manEntry);
man = new Manifest(new ByteArrayInputStream(b));
if (!jvInitialized) { if (!jvInitialized) {
jv = new JarVerifier(b); jv = new JarVerifier(b);
} }
man = new Manifest(jv, new ByteArrayInputStream(b));
} else { } else {
man = new Manifest(super.getInputStream(manEntry)); man = new Manifest(super.getInputStream(manEntry));
} }
......
/* /*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -879,4 +879,24 @@ class JarVerifier { ...@@ -879,4 +879,24 @@ class JarVerifier {
static CodeSource getUnsignedCS(URL url) { static CodeSource getUnsignedCS(URL url) {
return new VerifierCodeSource(null, url, (java.security.cert.Certificate[]) null); return new VerifierCodeSource(null, url, (java.security.cert.Certificate[]) null);
} }
/**
* Returns whether the name is trusted. Used by
* {@link Manifest#getTrustedAttributes(String)}.
*/
boolean isTrustedManifestEntry(String name) {
// How many signers? MANIFEST.MF is always verified
CodeSigner[] forMan = verifiedSigners.get(JarFile.MANIFEST_NAME);
if (forMan == null) {
return true;
}
// Check sigFileSigners first, because we are mainly dealing with
// non-file entries which will stay in sigFileSigners forever.
CodeSigner[] forName = sigFileSigners.get(name);
if (forName == null) {
forName = verifiedSigners.get(name);
}
// Returns trusted if all signers sign the entry
return forName != null && forName.length == forMan.length;
}
} }
/* /*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -60,4 +60,9 @@ class JavaUtilJarAccessImpl implements JavaUtilJarAccess { ...@@ -60,4 +60,9 @@ class JavaUtilJarAccessImpl implements JavaUtilJarAccess {
public List<Object> getManifestDigests(JarFile jar) { public List<Object> getManifestDigests(JarFile jar) {
return jar.getManifestDigests(); return jar.getManifestDigests();
} }
public Attributes getTrustedAttributes(Manifest man, String name) {
return man.getTrustedAttributes(name);
}
} }
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -48,15 +48,19 @@ import java.util.Iterator; ...@@ -48,15 +48,19 @@ import java.util.Iterator;
*/ */
public class Manifest implements Cloneable { public class Manifest implements Cloneable {
// manifest main attributes // manifest main attributes
private Attributes attr = new Attributes(); private final Attributes attr = new Attributes();
// manifest entries // manifest entries
private Map<String, Attributes> entries = new HashMap<>(); private final Map<String, Attributes> entries = new HashMap<>();
// associated JarVerifier, not null when called by JarFile::getManifest.
private final JarVerifier jv;
/** /**
* Constructs a new, empty Manifest. * Constructs a new, empty Manifest.
*/ */
public Manifest() { public Manifest() {
jv = null;
} }
/** /**
...@@ -66,7 +70,16 @@ public class Manifest implements Cloneable { ...@@ -66,7 +70,16 @@ public class Manifest implements Cloneable {
* @throws IOException if an I/O error has occurred * @throws IOException if an I/O error has occurred
*/ */
public Manifest(InputStream is) throws IOException { public Manifest(InputStream is) throws IOException {
this(null, is);
}
/**
* Constructs a new Manifest from the specified input stream
* and associates it with a JarVerifier.
*/
Manifest(JarVerifier jv, InputStream is) throws IOException {
read(is); read(is);
this.jv = jv;
} }
/** /**
...@@ -77,6 +90,7 @@ public class Manifest implements Cloneable { ...@@ -77,6 +90,7 @@ public class Manifest implements Cloneable {
public Manifest(Manifest man) { public Manifest(Manifest man) {
attr.putAll(man.getMainAttributes()); attr.putAll(man.getMainAttributes());
entries.putAll(man.getEntries()); entries.putAll(man.getEntries());
jv = man.jv;
} }
/** /**
...@@ -126,6 +140,23 @@ public class Manifest implements Cloneable { ...@@ -126,6 +140,23 @@ public class Manifest implements Cloneable {
return getEntries().get(name); return getEntries().get(name);
} }
/**
* Returns the Attributes for the specified entry name, if trusted.
*
* @param name entry name
* @return returns the same result as {@link #getAttributes(String)}
* @throws SecurityException if the associated jar is signed but this entry
* has been modified after signing (i.e. the section in the manifest
* does not exist in SF files of all signers).
*/
Attributes getTrustedAttributes(String name) {
Attributes result = getAttributes(name);
if (result != null && jv != null && ! jv.isTrustedManifestEntry(name)) {
throw new SecurityException("Untrusted manifest entry: " + name);
}
return result;
}
/** /**
* Clears the main Attributes as well as the entries in this Manifest. * Clears the main Attributes as well as the entries in this Manifest.
*/ */
......
...@@ -2703,7 +2703,7 @@ public class Cipher { ...@@ -2703,7 +2703,7 @@ public class Cipher {
// Input sanity check // Input sanity check
if ((src == null) || (offset < 0) || (len < 0) if ((src == null) || (offset < 0) || (len < 0)
|| ((len + offset) > src.length)) { || (len > (src.length - offset))) {
throw new IllegalArgumentException("Bad arguments"); throw new IllegalArgumentException("Bad arguments");
} }
......
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -50,6 +50,13 @@ import javax.crypto.IllegalBlockSizeException; ...@@ -50,6 +50,13 @@ import javax.crypto.IllegalBlockSizeException;
* that are not thrown by its ancestor classes. In particular, the * that are not thrown by its ancestor classes. In particular, the
* <code>skip</code> method skips, and the <code>available</code> * <code>skip</code> method skips, and the <code>available</code>
* method counts only data that have been processed by the encapsulated Cipher. * method counts only data that have been processed by the encapsulated Cipher.
* This class may catch BadPaddingException and other exceptions thrown by
* failed integrity checks during decryption. These exceptions are not
* re-thrown, so the client may not be informed that integrity checks
* failed. Because of this behavior, this class may not be suitable
* for use with decryption in an authenticated mode of operation (e.g. GCM).
* Applications that require authenticated encryption can use the Cipher API
* directly as an alternative to using this class.
* *
* <p> It is crucial for a programmer using this class not to use * <p> It is crucial for a programmer using this class not to use
* methods that are not defined or overriden in this class (such as a * methods that are not defined or overriden in this class (such as a
......
/* /*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -120,7 +120,7 @@ public class GCMParameterSpec implements AlgorithmParameterSpec { ...@@ -120,7 +120,7 @@ public class GCMParameterSpec implements AlgorithmParameterSpec {
// Input sanity check // Input sanity check
if ((src == null) ||(len < 0) || (offset < 0) if ((src == null) ||(len < 0) || (offset < 0)
|| ((len + offset) > src.length)) { || (len > (src.length - offset))) {
throw new IllegalArgumentException("Invalid buffer arguments"); throw new IllegalArgumentException("Invalid buffer arguments");
} }
......
/* /*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -30,8 +30,10 @@ import java.net.URL; ...@@ -30,8 +30,10 @@ import java.net.URL;
import java.security.CodeSource; import java.security.CodeSource;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.jar.Manifest;
public interface JavaUtilJarAccess { public interface JavaUtilJarAccess {
public boolean jarFileHasClassPathAttribute(JarFile jar) throws IOException; public boolean jarFileHasClassPathAttribute(JarFile jar) throws IOException;
...@@ -41,4 +43,5 @@ public interface JavaUtilJarAccess { ...@@ -41,4 +43,5 @@ public interface JavaUtilJarAccess {
public Enumeration<JarEntry> entries2(JarFile jar); public Enumeration<JarEntry> entries2(JarFile jar);
public void setEagerValidation(JarFile jar, boolean eager); public void setEagerValidation(JarFile jar, boolean eager);
public List<Object> getManifestDigests(JarFile jar); public List<Object> getManifestDigests(JarFile jar);
public Attributes getTrustedAttributes(Manifest man, String name);
} }
/* /*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -37,6 +37,7 @@ import java.util.jar.Attributes; ...@@ -37,6 +37,7 @@ import java.util.jar.Attributes;
import java.util.jar.Attributes.Name; import java.util.jar.Attributes.Name;
import java.net.JarURLConnection; import java.net.JarURLConnection;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.net.URLConnection; import java.net.URLConnection;
...@@ -69,6 +70,8 @@ public class URLClassPath { ...@@ -69,6 +70,8 @@ public class URLClassPath {
private static final boolean DEBUG_LOOKUP_CACHE; private static final boolean DEBUG_LOOKUP_CACHE;
private static final boolean DISABLE_JAR_CHECKING; private static final boolean DISABLE_JAR_CHECKING;
private static final boolean DISABLE_ACC_CHECKING; private static final boolean DISABLE_ACC_CHECKING;
private static final boolean DISABLE_CP_URL_CHECK;
private static final boolean DEBUG_CP_URL_CHECK;
static { static {
JAVA_VERSION = java.security.AccessController.doPrivileged( JAVA_VERSION = java.security.AccessController.doPrivileged(
...@@ -84,6 +87,13 @@ public class URLClassPath { ...@@ -84,6 +87,13 @@ public class URLClassPath {
p = AccessController.doPrivileged( p = AccessController.doPrivileged(
new GetPropertyAction("jdk.net.URLClassPath.disableRestrictedPermissions")); new GetPropertyAction("jdk.net.URLClassPath.disableRestrictedPermissions"));
DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false; DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
// This property will be removed in a later release
p = AccessController.doPrivileged(
new GetPropertyAction("jdk.net.URLClassPath.disableClassPathURLCheck"));
DISABLE_CP_URL_CHECK = p != null ? p.equals("true") || p.isEmpty() : false;
DEBUG_CP_URL_CHECK = "debug".equals(p);
} }
/* The original search path of URLs. */ /* The original search path of URLs. */
...@@ -1217,11 +1227,51 @@ public class URLClassPath { ...@@ -1217,11 +1227,51 @@ public class URLClassPath {
int i = 0; int i = 0;
while (st.hasMoreTokens()) { while (st.hasMoreTokens()) {
String path = st.nextToken(); String path = st.nextToken();
urls[i] = new URL(base, path); URL url = DISABLE_CP_URL_CHECK ? new URL(base, path) : safeResolve(base, path);
i++; if (url != null) {
urls[i] = url;
i++;
}
}
if (i == 0) {
urls = null;
} else if (i != urls.length) {
// Truncate nulls from end of array
urls = Arrays.copyOf(urls, i);
} }
return urls; return urls;
} }
/*
* Return a URL for the given path resolved against the base URL, or
* null if the resulting URL is invalid.
*/
static URL safeResolve(URL base, String path) {
String child = path.replace(File.separatorChar, '/');
try {
if (!URI.create(child).isAbsolute()) {
URL url = new URL(base, child);
if (base.getProtocol().equalsIgnoreCase("file")) {
return url;
} else {
String bp = base.getPath();
String urlp = url.getPath();
int pos = bp.lastIndexOf('/');
if (pos == -1) {
pos = bp.length() - 1;
}
if (urlp.regionMatches(0, bp, 0, pos + 1)
&& urlp.indexOf("..", pos) == -1) {
return url;
}
}
}
} catch (MalformedURLException | IllegalArgumentException e) {}
if (DEBUG_CP_URL_CHECK) {
System.err.println("Class-Path entry: \"" + path + "\" ignored in JAR file " + base);
}
return null;
}
} }
/* /*
......
/* /*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -2686,6 +2686,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { ...@@ -2686,6 +2686,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
// doesn't know about proxy. // doesn't know about proxy.
useProxyResponseCode = true; useProxyResponseCode = true;
} else { } else {
final URL prevURL = url;
// maintain previous headers, just change the name // maintain previous headers, just change the name
// of the file we're getting // of the file we're getting
url = locUrl; url = locUrl;
...@@ -2714,6 +2716,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection { ...@@ -2714,6 +2716,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
poster = null; poster = null;
if (!checkReuseConnection()) if (!checkReuseConnection())
connect(); connect();
if (!sameDestination(prevURL, url)) {
// Ensures pre-redirect user-set cookie will not be reset.
// CookieHandler, if any, will be queried to determine
// cookies for redirected URL, if any.
userCookies = null;
userCookies2 = null;
}
} else { } else {
if (!checkReuseConnection()) if (!checkReuseConnection())
connect(); connect();
...@@ -2736,11 +2746,52 @@ public class HttpURLConnection extends java.net.HttpURLConnection { ...@@ -2736,11 +2746,52 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
} }
requests.set("Host", host); requests.set("Host", host);
} }
if (!sameDestination(prevURL, url)) {
// Redirecting to a different destination will drop any
// security-sensitive headers, regardless of whether
// they are user-set or not. CookieHandler, if any, will be
// queried to determine cookies for redirected URL, if any.
userCookies = null;
userCookies2 = null;
requests.remove("Cookie");
requests.remove("Cookie2");
requests.remove("Authorization");
// check for preemptive authorization
AuthenticationInfo sauth =
AuthenticationInfo.getServerAuth(url);
if (sauth != null && sauth.supportsPreemptiveAuthorization() ) {
// Sets "Authorization"
requests.setIfNotSet(sauth.getHeaderName(), sauth.getHeaderValue(url,method));
currentServerCredentials = sauth;
}
}
} }
} }
return true; return true;
} }
/* Returns true iff the given URLs have the same host and effective port. */
private static boolean sameDestination(URL firstURL, URL secondURL) {
assert firstURL.getProtocol().equalsIgnoreCase(secondURL.getProtocol()):
"protocols not equal: " + firstURL + " - " + secondURL;
if (!firstURL.getHost().equalsIgnoreCase(secondURL.getHost()))
return false;
int firstPort = firstURL.getPort();
if (firstPort == -1)
firstPort = firstURL.getDefaultPort();
int secondPort = secondURL.getPort();
if (secondPort == -1)
secondPort = secondURL.getDefaultPort();
if (firstPort != secondPort)
return false;
return true;
}
/* dummy byte buffer for reading off socket prior to closing */ /* dummy byte buffer for reading off socket prior to closing */
byte[] cdata = new byte [128]; byte[] cdata = new byte [128];
......
/* /*
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -719,7 +719,8 @@ final class ClientHandshaker extends Handshaker { ...@@ -719,7 +719,8 @@ final class ClientHandshaker extends Handshaker {
session = new SSLSessionImpl(protocolVersion, cipherSuite, session = new SSLSessionImpl(protocolVersion, cipherSuite,
getLocalSupportedSignAlgs(), getLocalSupportedSignAlgs(),
mesg.sessionId, getHostSE(), getPortSE(), mesg.sessionId, getHostSE(), getPortSE(),
(extendedMasterSecretExt != null)); (extendedMasterSecretExt != null),
getEndpointIdentificationAlgorithmSE());
session.setRequestedServerNames(requestedServerNames); session.setRequestedServerNames(requestedServerNames);
setHandshakeSessionSE(session); setHandshakeSessionSE(session);
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
...@@ -1391,6 +1392,24 @@ final class ClientHandshaker extends Handshaker { ...@@ -1391,6 +1392,24 @@ final class ClientHandshaker extends Handshaker {
} }
} }
// ensure that the endpoint identification algorithm matches the
// one in the session
String identityAlg = getEndpointIdentificationAlgorithmSE();
if (session != null && identityAlg != null) {
String sessionIdentityAlg =
session.getEndpointIdentificationAlgorithm();
if (!Objects.equals(identityAlg, sessionIdentityAlg)) {
if (debug != null && Debug.isOn("session")) {
System.out.println("%% can't resume, endpoint id" +
" algorithm does not match, requested: " +
identityAlg + ", cached: " + sessionIdentityAlg);
}
session = null;
}
}
if (session != null) { if (session != null) {
if (debug != null) { if (debug != null) {
if (Debug.isOn("handshake") || Debug.isOn("session")) { if (Debug.isOn("handshake") || Debug.isOn("session")) {
......
/* /*
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -115,6 +115,10 @@ final class SSLSessionImpl extends ExtendedSSLSession { ...@@ -115,6 +115,10 @@ final class SSLSessionImpl extends ExtendedSSLSession {
private Principal peerPrincipal; private Principal peerPrincipal;
private Principal localPrincipal; private Principal localPrincipal;
// The endpoint identification algorithm used to check certificates
// in this session.
private final String endpointIdentificationAlgorithm;
/* /*
* Is the session currently re-established with a session-resumption * Is the session currently re-established with a session-resumption
* abbreviated initial handshake? * abbreviated initial handshake?
...@@ -146,7 +150,7 @@ final class SSLSessionImpl extends ExtendedSSLSession { ...@@ -146,7 +150,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
*/ */
private SSLSessionImpl() { private SSLSessionImpl() {
this(ProtocolVersion.NONE, CipherSuite.C_NULL, null, this(ProtocolVersion.NONE, CipherSuite.C_NULL, null,
new SessionId(false, null), null, -1, false); new SessionId(false, null), null, -1, false, null);
} }
/* /*
...@@ -157,10 +161,10 @@ final class SSLSessionImpl extends ExtendedSSLSession { ...@@ -157,10 +161,10 @@ final class SSLSessionImpl extends ExtendedSSLSession {
SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite, SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
Collection<SignatureAndHashAlgorithm> algorithms, Collection<SignatureAndHashAlgorithm> algorithms,
SecureRandom generator, String host, int port, SecureRandom generator, String host, int port,
boolean useExtendedMasterSecret) { boolean useExtendedMasterSecret, String endpointIdAlgorithm) {
this(protocolVersion, cipherSuite, algorithms, this(protocolVersion, cipherSuite, algorithms,
new SessionId(defaultRejoinable, generator), host, port, new SessionId(defaultRejoinable, generator), host, port,
useExtendedMasterSecret); useExtendedMasterSecret, endpointIdAlgorithm);
} }
/* /*
...@@ -169,7 +173,8 @@ final class SSLSessionImpl extends ExtendedSSLSession { ...@@ -169,7 +173,8 @@ final class SSLSessionImpl extends ExtendedSSLSession {
SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite, SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
Collection<SignatureAndHashAlgorithm> algorithms, Collection<SignatureAndHashAlgorithm> algorithms,
SessionId id, String host, int port, SessionId id, String host, int port,
boolean useExtendedMasterSecret) { boolean useExtendedMasterSecret,
String endpointIdAlgorithm){
this.protocolVersion = protocolVersion; this.protocolVersion = protocolVersion;
sessionId = id; sessionId = id;
peerCerts = null; peerCerts = null;
...@@ -182,6 +187,7 @@ final class SSLSessionImpl extends ExtendedSSLSession { ...@@ -182,6 +187,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
localSupportedSignAlgs = localSupportedSignAlgs =
SignatureAndHashAlgorithm.getAlgorithmNames(algorithms); SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
this.useExtendedMasterSecret = useExtendedMasterSecret; this.useExtendedMasterSecret = useExtendedMasterSecret;
this.endpointIdentificationAlgorithm = endpointIdAlgorithm;
if (debug != null && Debug.isOn("session")) { if (debug != null && Debug.isOn("session")) {
System.out.println("%% Initialized: " + this); System.out.println("%% Initialized: " + this);
...@@ -247,6 +253,10 @@ final class SSLSessionImpl extends ExtendedSSLSession { ...@@ -247,6 +253,10 @@ final class SSLSessionImpl extends ExtendedSSLSession {
localPrincipal = principal; localPrincipal = principal;
} }
String getEndpointIdentificationAlgorithm() {
return this.endpointIdentificationAlgorithm;
}
/** /**
* Returns true iff this session may be resumed ... sessions are * Returns true iff this session may be resumed ... sessions are
* usually resumable. Security policies may suggest otherwise, * usually resumable. Security policies may suggest otherwise,
......
/* /*
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -698,6 +698,25 @@ final class ServerHandshaker extends Handshaker { ...@@ -698,6 +698,25 @@ final class ServerHandshaker extends Handshaker {
} }
} }
// ensure that the endpoint identification algorithm matches the
// one in the session
String identityAlg = getEndpointIdentificationAlgorithmSE();
if (resumingSession && identityAlg != null) {
String sessionIdentityAlg =
previous.getEndpointIdentificationAlgorithm();
if (!Objects.equals(identityAlg, sessionIdentityAlg)) {
if (debug != null && Debug.isOn("session")) {
System.out.println("%% can't resume, endpoint id"
+ " algorithm does not match, requested: " +
identityAlg + ", cached: " +
sessionIdentityAlg);
}
resumingSession = false;
}
}
if (resumingSession) { if (resumingSession) {
CipherSuite suite = previous.getSuite(); CipherSuite suite = previous.getSuite();
// verify that the ciphersuite from the cached session // verify that the ciphersuite from the cached session
...@@ -769,7 +788,8 @@ final class ServerHandshaker extends Handshaker { ...@@ -769,7 +788,8 @@ final class ServerHandshaker extends Handshaker {
sslContext.getSecureRandom(), sslContext.getSecureRandom(),
getHostAddressSE(), getPortSE(), getHostAddressSE(), getPortSE(),
(requestedToUseEMS && (requestedToUseEMS &&
(protocolVersion.v >= ProtocolVersion.TLS10.v))); (protocolVersion.v >= ProtocolVersion.TLS10.v)),
getEndpointIdentificationAlgorithmSE());
if (protocolVersion.v >= ProtocolVersion.TLS12.v) { if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
if (peerSupportedSignAlgs != null) { if (peerSupportedSignAlgs != null) {
......
...@@ -35,6 +35,7 @@ import java.net.URL; ...@@ -35,6 +35,7 @@ import java.net.URL;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.text.Collator; import java.text.Collator;
import java.util.Locale; import java.util.Locale;
...@@ -58,6 +59,25 @@ public class KeyStoreUtil { ...@@ -58,6 +59,25 @@ public class KeyStoreUtil {
collator.setStrength(Collator.PRIMARY); collator.setStrength(Collator.PRIMARY);
}; };
/**
* Returns true if the certificate is self-signed, false otherwise.
*/
public static boolean isSelfSigned(X509Certificate cert) {
return signedBy(cert, cert);
}
public static boolean signedBy(X509Certificate end, X509Certificate ca) {
if (!ca.getSubjectX500Principal().equals(end.getIssuerX500Principal())) {
return false;
}
try {
end.verify(ca.getPublicKey());
return true;
} catch (Exception e) {
return false;
}
}
/** /**
* Returns true if KeyStore has a password. This is true except for * Returns true if KeyStore has a password. This is true except for
* MSCAPI KeyStores * MSCAPI KeyStores
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
package sun.security.tools.jarsigner; package sun.security.tools.jarsigner;
import java.io.*; import java.io.*;
import java.security.cert.CertPathValidatorException;
import java.security.cert.PKIXBuilderParameters;
import java.util.*; import java.util.*;
import java.util.zip.*; import java.util.zip.*;
import java.util.jar.*; import java.util.jar.*;
...@@ -46,11 +48,9 @@ import java.net.SocketTimeoutException; ...@@ -46,11 +48,9 @@ import java.net.SocketTimeoutException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.security.cert.CertPath; import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateNotYetValidException;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor; import java.security.cert.TrustAnchor;
import java.util.Map.Entry; import java.util.Map.Entry;
import sun.security.pkcs.PKCS7; import sun.security.pkcs.PKCS7;
...@@ -58,6 +58,8 @@ import sun.security.pkcs.SignerInfo; ...@@ -58,6 +58,8 @@ import sun.security.pkcs.SignerInfo;
import sun.security.timestamp.TimestampToken; import sun.security.timestamp.TimestampToken;
import sun.security.tools.KeyStoreUtil; import sun.security.tools.KeyStoreUtil;
import sun.security.tools.PathList; import sun.security.tools.PathList;
import sun.security.validator.Validator;
import sun.security.validator.ValidatorException;
import sun.security.x509.*; import sun.security.x509.*;
import sun.security.util.*; import sun.security.util.*;
import java.util.Base64; import java.util.Base64;
...@@ -173,22 +175,34 @@ public class Main { ...@@ -173,22 +175,34 @@ public class Main {
private boolean noTimestamp = false; private boolean noTimestamp = false;
private Date expireDate = new Date(0L); // used in noTimestamp warning private Date expireDate = new Date(0L); // used in noTimestamp warning
// Severe warnings // Severe warnings.
// jarsigner used to check signer cert chain validity and key usages
// itself and set various warnings. Later CertPath validation is
// added but chainNotValidated is only flagged when no other existing
// warnings are set. TSA cert chain check is added separately and
// only tsaChainNotValidated is set, i.e. has no affect on hasExpiredCert,
// notYetValidCert, or any badXyzUsage.
private int weakAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg
private boolean hasExpiredCert = false; private boolean hasExpiredCert = false;
private boolean notYetValidCert = false; private boolean notYetValidCert = false;
private boolean chainNotValidated = false; private boolean chainNotValidated = false;
private boolean tsaChainNotValidated = false;
private boolean notSignedByAlias = false; private boolean notSignedByAlias = false;
private boolean aliasNotInStore = false; private boolean aliasNotInStore = false;
private boolean hasUnsignedEntry = false; private boolean hasUnsignedEntry = false;
private boolean badKeyUsage = false; private boolean badKeyUsage = false;
private boolean badExtendedKeyUsage = false; private boolean badExtendedKeyUsage = false;
private boolean badNetscapeCertType = false; private boolean badNetscapeCertType = false;
private boolean signerSelfSigned = false;
private Throwable chainNotValidatedReason = null;
private Throwable tsaChainNotValidatedReason = null;
private boolean seeWeak = false; private boolean seeWeak = false;
CertificateFactory certificateFactory; PKIXBuilderParameters pkixParameters;
CertPathValidator validator;
PKIXParameters pkixParameters;
public void run(String args[]) { public void run(String args[]) {
try { try {
...@@ -275,7 +289,8 @@ public class Main { ...@@ -275,7 +289,8 @@ public class Main {
if (strict) { if (strict) {
int exitCode = 0; int exitCode = 0;
if (chainNotValidated || hasExpiredCert || notYetValidCert) { if (weakAlg != 0 || chainNotValidated
|| hasExpiredCert || notYetValidCert || signerSelfSigned) {
exitCode |= 4; exitCode |= 4;
} }
if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) { if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
...@@ -287,6 +302,9 @@ public class Main { ...@@ -287,6 +302,9 @@ public class Main {
if (notSignedByAlias || aliasNotInStore) { if (notSignedByAlias || aliasNotInStore) {
exitCode |= 32; exitCode |= 32;
} }
if (tsaChainNotValidated) {
exitCode |= 64;
}
if (exitCode != 0) { if (exitCode != 0) {
System.exit(exitCode); System.exit(exitCode);
} }
...@@ -807,6 +825,9 @@ public class Main { ...@@ -807,6 +825,9 @@ public class Main {
System.out.println(rb.getString("no.manifest.")); System.out.println(rb.getString("no.manifest."));
} }
// If there is a time stamp block inside the PKCS7 block file
boolean hasTimestampBlock = false;
// Even if the verbose option is not specified, all out strings // Even if the verbose option is not specified, all out strings
// must be generated so seeWeak can be updated. // must be generated so seeWeak can be updated.
if (!digestMap.isEmpty() if (!digestMap.isEmpty()
...@@ -835,6 +856,7 @@ public class Main { ...@@ -835,6 +856,7 @@ public class Main {
PublicKey key = signer.getPublicKey(); PublicKey key = signer.getPublicKey();
PKCS7 tsToken = si.getTsToken(); PKCS7 tsToken = si.getTsToken();
if (tsToken != null) { if (tsToken != null) {
hasTimestampBlock = true;
SignerInfo tsSi = tsToken.getSignerInfos()[0]; SignerInfo tsSi = tsToken.getSignerInfos()[0];
X509Certificate tsSigner = tsSi.getCertificate(tsToken); X509Certificate tsSigner = tsSi.getCertificate(tsToken);
byte[] encTsTokenInfo = tsToken.getContentInfo().getData(); byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
...@@ -890,6 +912,12 @@ public class Main { ...@@ -890,6 +912,12 @@ public class Main {
} }
System.out.println(); System.out.println();
// If signer is a trusted cert or private entry in user's own
// keystore, it can be self-signed.
if (!aliasNotInStore) {
signerSelfSigned = false;
}
if (!anySigned) { if (!anySigned) {
if (seeWeak) { if (seeWeak) {
if (verbose != null) { if (verbose != null) {
...@@ -910,8 +938,8 @@ public class Main { ...@@ -910,8 +938,8 @@ public class Main {
boolean errorAppeared = false; boolean errorAppeared = false;
if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
notYetValidCert || chainNotValidated || hasExpiredCert || notYetValidCert || chainNotValidated || hasExpiredCert ||
hasUnsignedEntry || hasUnsignedEntry || signerSelfSigned || (weakAlg != 0) ||
aliasNotInStore || notSignedByAlias) { aliasNotInStore || notSignedByAlias || tsaChainNotValidated) {
if (strict) { if (strict) {
System.out.println(rb.getString("jar.verified.with.signer.errors.")); System.out.println(rb.getString("jar.verified.with.signer.errors."));
...@@ -925,6 +953,12 @@ public class Main { ...@@ -925,6 +953,12 @@ public class Main {
warningAppeared = true; warningAppeared = true;
} }
if (weakAlg != 0) {
// In fact, jarsigner verification did not catch this
// since it has not read the JarFile content itself.
// Everything is done with JarFile API.
}
if (badKeyUsage) { if (badKeyUsage) {
System.out.println( System.out.println(
rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.")); rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
...@@ -954,8 +988,15 @@ public class Main { ...@@ -954,8 +988,15 @@ public class Main {
} }
if (chainNotValidated) { if (chainNotValidated) {
System.out.println( System.out.println(String.format(
rb.getString("This.jar.contains.entries.whose.certificate.chain.is.not.validated.")); rb.getString("This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1"),
chainNotValidatedReason.getLocalizedMessage()));
}
if (tsaChainNotValidated) {
System.out.println(String.format(
rb.getString("This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1"),
tsaChainNotValidatedReason.getLocalizedMessage()));
} }
if (notSignedByAlias) { if (notSignedByAlias) {
...@@ -966,6 +1007,11 @@ public class Main { ...@@ -966,6 +1007,11 @@ public class Main {
if (aliasNotInStore) { if (aliasNotInStore) {
System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.")); System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
} }
if (signerSelfSigned) {
System.out.println(rb.getString(
"This.jar.contains.entries.whose.signer.certificate.is.self.signed."));
}
} else { } else {
System.out.println(rb.getString("jar.verified.")); System.out.println(rb.getString("jar.verified."));
} }
...@@ -980,8 +1026,15 @@ public class Main { ...@@ -980,8 +1026,15 @@ public class Main {
"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.")); "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
} }
if (noTimestamp) { if (noTimestamp) {
System.out.println( if (hasTimestampBlock) {
String.format(rb.getString("no.timestamp.verifying"), expireDate)); // JarSigner API has not seen the timestamp,
// might have ignored it due to weak alg, etc.
System.out.println(
String.format(rb.getString("bad.timestamp.verifying"), expireDate));
} else {
System.out.println(
String.format(rb.getString("no.timestamp.verifying"), expireDate));
}
} }
} }
if (warningAppeared || errorAppeared) { if (warningAppeared || errorAppeared) {
...@@ -1032,16 +1085,23 @@ public class Main { ...@@ -1032,16 +1085,23 @@ public class Main {
private static MessageFormat expiredTimeForm = null; private static MessageFormat expiredTimeForm = null;
private static MessageFormat expiringTimeForm = null; private static MessageFormat expiringTimeForm = null;
/* /**
* Display some details about a certificate: * Returns a string about a certificate:
* *
* [<tab>] <cert-type> [", " <subject-DN>] [" (" <keystore-entry-alias> ")"] * [<tab>] <cert-type> [", " <subject-DN>] [" (" <keystore-entry-alias> ")"]
* [<validity-period> | <expiry-warning>] * [<validity-period> | <expiry-warning>]
* [<key-usage-warning>]
*
* Note: no newline character at the end.
* *
* Note: no newline character at the end * When isTsCert is true, this method sets global flags like hasExpiredCert,
* notYetValidCert, badKeyUsage, badExtendedKeyUsage, badNetscapeCertType.
*
* @param isTsCert true if c is in the TSA cert chain, false otherwise.
* @param checkUsage true to check code signer keyUsage
*/ */
String printCert(String tab, Certificate c, boolean checkValidityPeriod, String printCert(boolean isTsCert, String tab, Certificate c,
Date timestamp, boolean checkUsage) { Date timestamp, boolean checkUsage) throws Exception {
StringBuilder certStr = new StringBuilder(); StringBuilder certStr = new StringBuilder();
String space = rb.getString("SPACE"); String space = rb.getString("SPACE");
...@@ -1061,7 +1121,7 @@ public class Main { ...@@ -1061,7 +1121,7 @@ public class Main {
certStr.append(space).append(alias); certStr.append(space).append(alias);
} }
if (checkValidityPeriod && x509Cert != null) { if (x509Cert != null) {
certStr.append("\n").append(tab).append("["); certStr.append("\n").append(tab).append("[");
Date notAfter = x509Cert.getNotAfter(); Date notAfter = x509Cert.getNotAfter();
...@@ -1074,7 +1134,7 @@ public class Main { ...@@ -1074,7 +1134,7 @@ public class Main {
x509Cert.checkValidity(); x509Cert.checkValidity();
// test if cert will expire within six months // test if cert will expire within six months
if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) { if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) {
hasExpiringCert = true; if (!isTsCert) hasExpiringCert = true;
if (expiringTimeForm == null) { if (expiringTimeForm == null) {
expiringTimeForm = new MessageFormat( expiringTimeForm = new MessageFormat(
rb.getString("certificate.will.expire.on")); rb.getString("certificate.will.expire.on"));
...@@ -1095,7 +1155,7 @@ public class Main { ...@@ -1095,7 +1155,7 @@ public class Main {
certStr.append(validityTimeForm.format(source)); certStr.append(validityTimeForm.format(source));
} }
} catch (CertificateExpiredException cee) { } catch (CertificateExpiredException cee) {
hasExpiredCert = true; if (!isTsCert) hasExpiredCert = true;
if (expiredTimeForm == null) { if (expiredTimeForm == null) {
expiredTimeForm = new MessageFormat( expiredTimeForm = new MessageFormat(
...@@ -1105,7 +1165,7 @@ public class Main { ...@@ -1105,7 +1165,7 @@ public class Main {
certStr.append(expiredTimeForm.format(source)); certStr.append(expiredTimeForm.format(source));
} catch (CertificateNotYetValidException cnyve) { } catch (CertificateNotYetValidException cnyve) {
notYetValidCert = true; if (!isTsCert) notYetValidCert = true;
if (notYetTimeForm == null) { if (notYetTimeForm == null) {
notYetTimeForm = new MessageFormat( notYetTimeForm = new MessageFormat(
...@@ -1218,7 +1278,25 @@ public class Main { ...@@ -1218,7 +1278,25 @@ public class Main {
} }
void signJar(String jarName, String alias, String[] args) void signJar(String jarName, String alias, String[] args)
throws Exception { throws Exception {
DisabledAlgorithmConstraints dac =
new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
if (digestalg != null && !dac.permits(
Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), digestalg, null)) {
weakAlg |= 1;
}
if (tSADigestAlg != null && !dac.permits(
Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), tSADigestAlg, null)) {
weakAlg |= 4;
}
if (sigalg != null && !dac.permits(
Collections.singleton(CryptoPrimitive.SIGNATURE), sigalg, null)) {
weakAlg |= 2;
}
boolean aliasUsed = false; boolean aliasUsed = false;
X509Certificate tsaCert = null; X509Certificate tsaCert = null;
...@@ -1494,7 +1572,7 @@ public class Main { ...@@ -1494,7 +1572,7 @@ public class Main {
tsaURI); tsaURI);
} }
System.out.println(rb.getString("TSA.certificate.") + System.out.println(rb.getString("TSA.certificate.") +
printCert("", tsaCert, false, null, false)); printCert(true, "", tsaCert, null, false));
} }
if (signingMechanism != null) { if (signingMechanism != null) {
System.out.println( System.out.println(
...@@ -1557,6 +1635,30 @@ public class Main { ...@@ -1557,6 +1635,30 @@ public class Main {
} }
} }
// The JarSigner API always accepts the timestamp received.
// We need to extract the certs from the signed jar to
// validate it.
if (!noTimestamp) {
try (JarFile check = new JarFile(signedJarFile)) {
PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry(
"META-INF/" + sigfile + "." + privateKey.getAlgorithm())));
SignerInfo si = p7.getSignerInfos()[0];
PKCS7 tsToken = si.getTsToken();
SignerInfo tsSi = tsToken.getSignerInfos()[0];
try {
validateCertChain(Validator.VAR_TSA_SERVER,
tsSi.getCertificateChain(tsToken), null);
} catch (Exception e) {
tsaChainNotValidated = true;
tsaChainNotValidatedReason = e;
}
} catch (Exception e) {
if (debug) {
e.printStackTrace();
}
}
}
// no IOException thrown in the follow try clause, so disable // no IOException thrown in the follow try clause, so disable
// the try clause. // the try clause.
// try { // try {
...@@ -1586,8 +1688,10 @@ public class Main { ...@@ -1586,8 +1688,10 @@ public class Main {
} }
boolean warningAppeared = false; boolean warningAppeared = false;
if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || if (weakAlg != 0 || badKeyUsage || badExtendedKeyUsage
notYetValidCert || chainNotValidated || hasExpiredCert) { || badNetscapeCertType || notYetValidCert
|| chainNotValidated || tsaChainNotValidated
|| hasExpiredCert || signerSelfSigned) {
if (strict) { if (strict) {
System.out.println(rb.getString("jar.signed.with.signer.errors.")); System.out.println(rb.getString("jar.signed.with.signer.errors."));
System.out.println(); System.out.println();
...@@ -1623,8 +1727,37 @@ public class Main { ...@@ -1623,8 +1727,37 @@ public class Main {
} }
if (chainNotValidated) { if (chainNotValidated) {
System.out.println(String.format(
rb.getString("The.signer.s.certificate.chain.is.invalid.reason.1"),
chainNotValidatedReason.getLocalizedMessage()));
}
if (tsaChainNotValidated) {
System.out.println(String.format(
rb.getString("The.tsa.certificate.chain.is.invalid.reason.1"),
tsaChainNotValidatedReason.getLocalizedMessage()));
}
if (signerSelfSigned) {
System.out.println( System.out.println(
rb.getString("The.signer.s.certificate.chain.is.not.validated.")); rb.getString("The.signer.s.certificate.is.self.signed."));
}
if ((weakAlg & 1) == 1) {
System.out.println(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
digestalg, "-digestalg"));
}
if ((weakAlg & 2) == 2) {
System.out.println(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
sigalg, "-sigalg"));
}
if ((weakAlg & 4) == 4) {
System.out.println(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
tSADigestAlg, "-tsadigestalg"));
} }
} else { } else {
System.out.println(rb.getString("jar.signed.")); System.out.println(rb.getString("jar.signed."));
...@@ -1700,18 +1833,18 @@ public class Main { ...@@ -1700,18 +1833,18 @@ public class Main {
/** /**
* Returns a string of singer info, with a newline at the end * Returns a string of singer info, with a newline at the end
*/ */
private String signerInfo(CodeSigner signer, String tab) { private String signerInfo(CodeSigner signer, String tab) throws Exception {
if (cacheForSignerInfo.containsKey(signer)) { if (cacheForSignerInfo.containsKey(signer)) {
return cacheForSignerInfo.get(signer); return cacheForSignerInfo.get(signer);
} }
StringBuffer s = new StringBuffer(); StringBuilder sb = new StringBuilder();
List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates(); List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
// display the signature timestamp, if present // display the signature timestamp, if present
Date timestamp; Date timestamp;
Timestamp ts = signer.getTimestamp(); Timestamp ts = signer.getTimestamp();
if (ts != null) { if (ts != null) {
s.append(printTimestamp(tab, ts)); sb.append(printTimestamp(tab, ts));
s.append('\n'); sb.append('\n');
timestamp = ts.getTimestamp(); timestamp = ts.getTimestamp();
} else { } else {
timestamp = null; timestamp = null;
...@@ -1720,28 +1853,41 @@ public class Main { ...@@ -1720,28 +1853,41 @@ public class Main {
// display the certificate(s). The first one is end-entity cert and // display the certificate(s). The first one is end-entity cert and
// its KeyUsage should be checked. // its KeyUsage should be checked.
boolean first = true; boolean first = true;
sb.append(tab).append(rb.getString("...Signer")).append('\n');
for (Certificate c : certs) { for (Certificate c : certs) {
s.append(printCert(tab, c, true, timestamp, first)); sb.append(printCert(false, tab, c, timestamp, first));
s.append('\n'); sb.append('\n');
first = false; first = false;
} }
try { try {
validateCertChain(certs); validateCertChain(Validator.VAR_CODE_SIGNING, certs, ts);
} catch (Exception e) { } catch (Exception e) {
if (debug) { chainNotValidated = true;
e.printStackTrace(); chainNotValidatedReason = e;
sb.append(tab).append(rb.getString(".Invalid.certificate.chain."))
.append(e.getLocalizedMessage()).append("]\n");
}
if (ts != null) {
sb.append(tab).append(rb.getString("...TSA")).append('\n');
for (Certificate c : ts.getSignerCertPath().getCertificates()) {
sb.append(printCert(true, tab, c, timestamp, false));
sb.append('\n');
} }
if (e.getCause() != null && try {
(e.getCause() instanceof CertificateExpiredException || validateCertChain(Validator.VAR_TSA_SERVER,
e.getCause() instanceof CertificateNotYetValidException)) { ts.getSignerCertPath().getCertificates(), null);
// No more warning, we alreay have hasExpiredCert or notYetValidCert } catch (Exception e) {
} else { tsaChainNotValidated = true;
chainNotValidated = true; tsaChainNotValidatedReason = e;
s.append(tab + rb.getString(".CertPath.not.validated.") + sb.append(tab).append(rb.getString(".Invalid.TSA.certificate.chain."))
e.getLocalizedMessage() + "]\n"); // TODO .append(e.getLocalizedMessage()).append("]\n");
} }
} }
String result = s.toString(); if (certs.size() == 1
&& KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) {
signerSelfSigned = true;
}
String result = sb.toString();
cacheForSignerInfo.put(signer, result); cacheForSignerInfo.put(signer, result);
return result; return result;
} }
...@@ -1793,9 +1939,6 @@ public class Main { ...@@ -1793,9 +1939,6 @@ public class Main {
} }
try { try {
certificateFactory = CertificateFactory.getInstance("X.509");
validator = CertPathValidator.getInstance("PKIX");
Set<TrustAnchor> tas = new HashSet<>(); Set<TrustAnchor> tas = new HashSet<>();
try { try {
KeyStore caks = KeyStoreUtil.getCacertsKeyStore(); KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
...@@ -1871,7 +2014,7 @@ public class Main { ...@@ -1871,7 +2014,7 @@ public class Main {
} }
} finally { } finally {
try { try {
pkixParameters = new PKIXParameters(tas); pkixParameters = new PKIXBuilderParameters(tas, null);
pkixParameters.setRevocationEnabled(false); pkixParameters.setRevocationEnabled(false);
} catch (InvalidAlgorithmParameterException ex) { } catch (InvalidAlgorithmParameterException ex) {
// Only if tas is empty // Only if tas is empty
...@@ -1987,7 +2130,7 @@ public class Main { ...@@ -1987,7 +2130,7 @@ public class Main {
} }
} }
void getAliasInfo(String alias) { void getAliasInfo(String alias) throws Exception {
Key key = null; Key key = null;
...@@ -2033,21 +2176,18 @@ public class Main { ...@@ -2033,21 +2176,18 @@ public class Main {
// We don't meant to print anything, the next call // We don't meant to print anything, the next call
// checks validity and keyUsage etc // checks validity and keyUsage etc
printCert("", certChain[0], true, null, true); printCert(false, "", certChain[0], null, true);
try { try {
validateCertChain(Arrays.asList(certChain)); validateCertChain(Validator.VAR_CODE_SIGNING,
Arrays.asList(certChain), null);
} catch (Exception e) { } catch (Exception e) {
if (debug) { chainNotValidated = true;
e.printStackTrace(); chainNotValidatedReason = e;
} }
if (e.getCause() != null &&
(e.getCause() instanceof CertificateExpiredException || if (KeyStoreUtil.isSelfSigned(certChain[0])) {
e.getCause() instanceof CertificateNotYetValidException)) { signerSelfSigned = true;
// No more warning, we alreay have hasExpiredCert or notYetValidCert
} else {
chainNotValidated = true;
}
} }
try { try {
...@@ -2101,19 +2241,55 @@ public class Main { ...@@ -2101,19 +2241,55 @@ public class Main {
System.exit(1); System.exit(1);
} }
void validateCertChain(List<? extends Certificate> certs) throws Exception { /**
int cpLen = 0; * Validates a cert chain.
out: for (; cpLen<certs.size(); cpLen++) { *
for (TrustAnchor ta: pkixParameters.getTrustAnchors()) { * @param parameter this might be a timestamp
if (ta.getTrustedCert().equals(certs.get(cpLen))) { */
break out; void validateCertChain(String variant, List<? extends Certificate> certs,
Object parameter)
throws Exception {
try {
Validator.getInstance(Validator.TYPE_PKIX,
variant,
pkixParameters)
.validate(certs.toArray(new X509Certificate[certs.size()]),
null, parameter);
} catch (Exception e) {
if (debug) {
e.printStackTrace();
}
// Exception might be dismissed if another warning flag
// is already set by printCert. This is only done for
// code signing certs.
if (variant.equals(Validator.VAR_CODE_SIGNING) &&
e instanceof ValidatorException) {
// Throw cause if it's CertPathValidatorException,
if (e.getCause() != null &&
e.getCause() instanceof CertPathValidatorException) {
e = (Exception) e.getCause();
Throwable t = e.getCause();
if ((t instanceof CertificateExpiredException &&
hasExpiredCert) ||
(t instanceof CertificateNotYetValidException &&
notYetValidCert)) {
// we already have hasExpiredCert and notYetValidCert
return;
}
}
if (e instanceof ValidatorException) {
ValidatorException ve = (ValidatorException)e;
if (ve.getErrorType() == ValidatorException.T_EE_EXTENSIONS &&
(badKeyUsage || badExtendedKeyUsage || badNetscapeCertType)) {
// We already have badKeyUsage, badExtendedKeyUsage
// and badNetscapeCertType
return;
}
} }
} }
} throw e;
if (cpLen > 0) {
CertPath cp = certificateFactory.generateCertPath(
(cpLen == certs.size())? certs: certs.subList(0, cpLen));
validator.validate(cp, pkixParameters);
} }
} }
......
/* /*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -199,7 +199,8 @@ public class Resources extends java.util.ListResourceBundle { ...@@ -199,7 +199,8 @@ public class Resources extends java.util.ListResourceBundle {
{"certificate.is.not.valid.until", {"certificate.is.not.valid.until",
"certificate is not valid until {0}"}, "certificate is not valid until {0}"},
{"certificate.will.expire.on", "certificate will expire on {0}"}, {"certificate.will.expire.on", "certificate will expire on {0}"},
{".CertPath.not.validated.", "[CertPath not validated: "}, {".Invalid.certificate.chain.", "[Invalid certificate chain: "},
{".Invalid.TSA.certificate.chain.", "[Invalid TSA certificate chain: "},
{"requesting.a.signature.timestamp", {"requesting.a.signature.timestamp",
"requesting a signature timestamp"}, "requesting a signature timestamp"},
{"TSA.location.", "TSA location: "}, {"TSA.location.", "TSA location: "},
...@@ -216,6 +217,8 @@ public class Resources extends java.util.ListResourceBundle { ...@@ -216,6 +217,8 @@ public class Resources extends java.util.ListResourceBundle {
{"entry.was.signed.on", "entry was signed on {0}"}, {"entry.was.signed.on", "entry was signed on {0}"},
{"Warning.", "Warning: "}, {"Warning.", "Warning: "},
{"Error.", "Error: "}, {"Error.", "Error: "},
{"...Signer", ">>> Signer"},
{"...TSA", ">>> TSA"},
{"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.", {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
"This jar contains unsigned entries which have not been integrity-checked. "}, "This jar contains unsigned entries which have not been integrity-checked. "},
{"This.jar.contains.entries.whose.signer.certificate.has.expired.", {"This.jar.contains.entries.whose.signer.certificate.has.expired.",
...@@ -224,6 +227,8 @@ public class Resources extends java.util.ListResourceBundle { ...@@ -224,6 +227,8 @@ public class Resources extends java.util.ListResourceBundle {
"This jar contains entries whose signer certificate will expire within six months. "}, "This jar contains entries whose signer certificate will expire within six months. "},
{"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.", {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.",
"This jar contains entries whose signer certificate is not yet valid. "}, "This jar contains entries whose signer certificate is not yet valid. "},
{"This.jar.contains.entries.whose.signer.certificate.is.self.signed.",
"This jar contains entries whose signer certificate is self-signed."},
{"Re.run.with.the.verbose.option.for.more.details.", {"Re.run.with.the.verbose.option.for.more.details.",
"Re-run with the -verbose option for more details."}, "Re-run with the -verbose option for more details."},
{"Re.run.with.the.verbose.and.certs.options.for.more.details.", {"Re.run.with.the.verbose.and.certs.options.for.more.details.",
...@@ -248,14 +253,24 @@ public class Resources extends java.util.ListResourceBundle { ...@@ -248,14 +253,24 @@ public class Resources extends java.util.ListResourceBundle {
"This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing."}, "This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing."},
{".{0}.extension.does.not.support.code.signing.", {".{0}.extension.does.not.support.code.signing.",
"[{0} extension does not support code signing]"}, "[{0} extension does not support code signing]"},
{"The.signer.s.certificate.chain.is.not.validated.", {"The.signer.s.certificate.chain.is.invalid.reason.1",
"The signer's certificate chain is not validated."}, "The signer's certificate chain is invalid. Reason: %s"},
{"This.jar.contains.entries.whose.certificate.chain.is.not.validated.", {"The.tsa.certificate.chain.is.invalid.reason.1",
"This jar contains entries whose certificate chain is not validated."}, "The TSA certificate chain is invalid. Reason: %s"},
{"The.signer.s.certificate.is.self.signed.",
"The signer's certificate is self-signed."},
{"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.",
"The %1$s algorithm specified for the %2$s option is considered a security risk."},
{"This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1",
"This jar contains entries whose certificate chain is invalid. Reason: %s"},
{"This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1",
"This jar contains entries whose TSA certificate chain is invalid. Reason: %s"},
{"no.timestamp.signing", {"no.timestamp.signing",
"No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."}, "No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
{"no.timestamp.verifying", {"no.timestamp.verifying",
"This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."}, "This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
{"bad.timestamp.verifying",
"This jar contains signatures that include an invalid timestamp. Without a valid timestamp, users may not be able to validate this jar after any of the signer certificates expire (as early as %1$tY-%1$tm-%1$td).\nRerun jarsigner with -J-Djava.security.debug=jar for more information."},
{"Unknown.password.type.", "Unknown password type: "}, {"Unknown.password.type.", "Unknown password type: "},
{"Cannot.find.environment.variable.", {"Cannot.find.environment.variable.",
"Cannot find environment variable: "}, "Cannot find environment variable: "},
......
...@@ -1352,7 +1352,7 @@ public final class Main { ...@@ -1352,7 +1352,7 @@ public final class Main {
for (Certificate ca: keyStore.getCertificateChain(alias)) { for (Certificate ca: keyStore.getCertificateChain(alias)) {
if (ca instanceof X509Certificate) { if (ca instanceof X509Certificate) {
X509Certificate xca = (X509Certificate)ca; X509Certificate xca = (X509Certificate)ca;
if (!isSelfSigned(xca)) { if (!KeyStoreUtil.isSelfSigned(xca)) {
dumpCert(xca, out); dumpCert(xca, out);
} }
} }
...@@ -2869,7 +2869,7 @@ public final class Main { ...@@ -2869,7 +2869,7 @@ public final class Main {
// if certificate is self-signed, make sure it verifies // if certificate is self-signed, make sure it verifies
boolean selfSigned = false; boolean selfSigned = false;
if (isSelfSigned(cert)) { if (KeyStoreUtil.isSelfSigned(cert)) {
cert.verify(cert.getPublicKey()); cert.verify(cert.getPublicKey());
selfSigned = true; selfSigned = true;
} }
...@@ -3172,25 +3172,6 @@ public final class Main { ...@@ -3172,25 +3172,6 @@ public final class Main {
} }
} }
/**
* Returns true if the certificate is self-signed, false otherwise.
*/
private boolean isSelfSigned(X509Certificate cert) {
return signedBy(cert, cert);
}
private boolean signedBy(X509Certificate end, X509Certificate ca) {
if (!ca.getSubjectDN().equals(end.getIssuerDN())) {
return false;
}
try {
end.verify(ca.getPublicKey());
return true;
} catch (Exception e) {
return false;
}
}
/** /**
* Locates a signer for a given certificate from a given keystore and * Locates a signer for a given certificate from a given keystore and
* returns the signer's certificate. * returns the signer's certificate.
...@@ -3531,7 +3512,7 @@ public final class Main { ...@@ -3531,7 +3512,7 @@ public final class Main {
// find a cert in the reply who signs thisCert // find a cert in the reply who signs thisCert
int j; int j;
for (j=i; j<replyCerts.length; j++) { for (j=i; j<replyCerts.length; j++) {
if (signedBy(thisCert, (X509Certificate)replyCerts[j])) { if (KeyStoreUtil.signedBy(thisCert, (X509Certificate)replyCerts[j])) {
tmpCert = replyCerts[i]; tmpCert = replyCerts[i];
replyCerts[i] = replyCerts[j]; replyCerts[i] = replyCerts[j];
replyCerts[j] = tmpCert; replyCerts[j] = tmpCert;
...@@ -3689,7 +3670,7 @@ public final class Main { ...@@ -3689,7 +3670,7 @@ public final class Main {
private boolean buildChain(Pair<String,X509Certificate> certToVerify, private boolean buildChain(Pair<String,X509Certificate> certToVerify,
Vector<Pair<String,X509Certificate>> chain, Vector<Pair<String,X509Certificate>> chain,
Hashtable<Principal, Vector<Pair<String,X509Certificate>>> certs) { Hashtable<Principal, Vector<Pair<String,X509Certificate>>> certs) {
if (isSelfSigned(certToVerify.snd)) { if (KeyStoreUtil.isSelfSigned(certToVerify.snd)) {
// reached self-signed root cert; // reached self-signed root cert;
// no verification needed because it's trusted. // no verification needed because it's trusted.
chain.addElement(certToVerify); chain.addElement(certToVerify);
......
...@@ -719,7 +719,8 @@ public class SignatureFileVerifier { ...@@ -719,7 +719,8 @@ public class SignatureFileVerifier {
if (signers == null) { if (signers == null) {
signers = new ArrayList<>(); signers = new ArrayList<>();
} }
// Append the new code signer // Append the new code signer. If timestamp is invalid, this
// jar will be treated as unsigned.
signers.add(new CodeSigner(certChain, info.getTimestamp())); signers.add(new CodeSigner(certChain, info.getTimestamp()));
if (debug != null) { if (debug != null) {
......
...@@ -335,10 +335,18 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 ...@@ -335,10 +335,18 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
jobject obj = NULL; jobject obj = NULL;
jboolean match = JNI_FALSE; jboolean match = JNI_FALSE;
#if defined(AF_INET6) #if defined(AF_INET6)
int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6; int family = getInetAddress_family(env, iaObj);
JNU_CHECK_EXCEPTION_RETURN(env, NULL); JNU_CHECK_EXCEPTION_RETURN(env, NULL);
if (family == IPv4) {
family = AF_INET;
} else if (family == IPv6) {
family = AF_INET6;
} else {
return NULL; // Invalid family
}
#else #else
int family = AF_INET; int family = AF_INET;
#endif #endif
ifs = enumInterfaces(env); ifs = enumInterfaces(env);
if (ifs == NULL) { if (ifs == NULL) {
...@@ -357,7 +365,9 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 ...@@ -357,7 +365,9 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
int address1 = htonl( int address1 = htonl(
((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr); ((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr);
int address2 = getInetAddress_addr(env, iaObj); int address2 = getInetAddress_addr(env, iaObj);
JNU_CHECK_EXCEPTION_RETURN(env, NULL); if ((*env)->ExceptionCheck(env)) {
goto cleanup;
}
if (address1 == address2) { if (address1 == address2) {
match = JNI_TRUE; match = JNI_TRUE;
break; break;
...@@ -402,6 +412,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 ...@@ -402,6 +412,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
obj = createNetworkInterface(env, curr); obj = createNetworkInterface(env, curr);
} }
cleanup:
// release the interface list // release the interface list
freeif(ifs); freeif(ifs);
......
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -677,7 +677,7 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -677,7 +677,7 @@ final class Win32ShellFolder2 extends ShellFolder {
} }
try { try {
return invoke(new Callable<File[]>() { File[] files = invoke(new Callable<File[]>() {
public File[] call() throws InterruptedException { public File[] call() throws InterruptedException {
if (!isDirectory()) { if (!isDirectory()) {
return null; return null;
...@@ -732,6 +732,9 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -732,6 +732,9 @@ final class Win32ShellFolder2 extends ShellFolder {
: list.toArray(new ShellFolder[list.size()]); : list.toArray(new ShellFolder[list.size()]);
} }
}, InterruptedException.class); }, InterruptedException.class);
return Win32ShellFolderManager2.checkFiles(files);
} catch (InterruptedException e) { } catch (InterruptedException e) {
return new File[0]; return new File[0];
} }
......
/* /*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -379,21 +379,30 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -379,21 +379,30 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
return null; return null;
} }
private File checkFile(File file) { private static File checkFile(File file) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
return (sm == null || file == null) ? file : checkFile(file, sm); return (sm == null || file == null) ? file : checkFile(file, sm);
} }
private File checkFile(File file, SecurityManager sm) { private static File checkFile(File file, SecurityManager sm) {
try { try {
sm.checkRead(file.getPath()); sm.checkRead(file.getPath());
if (file instanceof Win32ShellFolder2) {
Win32ShellFolder2 f = (Win32ShellFolder2)file;
if (f.isLink()) {
Win32ShellFolder2 link = (Win32ShellFolder2)f.getLinkLocation();
if (link != null)
sm.checkRead(link.getPath());
}
}
return file; return file;
} catch (SecurityException se) { } catch (SecurityException se) {
return null; return null;
} }
} }
private File[] checkFiles(File[] files) { static File[] checkFiles(File[] files) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm == null || files == null || files.length == 0) { if (sm == null || files == null || files.length == 0) {
return files; return files;
...@@ -401,7 +410,7 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -401,7 +410,7 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
return checkFiles(Arrays.stream(files), sm); return checkFiles(Arrays.stream(files), sm);
} }
private File[] checkFiles(List<File> files) { private static File[] checkFiles(List<File> files) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm == null || files.isEmpty()) { if (sm == null || files.isEmpty()) {
return files.toArray(new File[files.size()]); return files.toArray(new File[files.size()]);
...@@ -409,7 +418,7 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -409,7 +418,7 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
return checkFiles(files.stream(), sm); return checkFiles(files.stream(), sm);
} }
private File[] checkFiles(Stream<File> filesStream, SecurityManager sm) { private static File[] checkFiles(Stream<File> filesStream, SecurityManager sm) {
return filesStream.filter((file) -> checkFile(file, sm) != null) return filesStream.filter((file) -> checkFile(file, sm) != null)
.toArray(File[]::new); .toArray(File[]::new);
} }
......
...@@ -287,6 +287,7 @@ int enumInterfaces(JNIEnv *env, netif **netifPP) ...@@ -287,6 +287,7 @@ int enumInterfaces(JNIEnv *env, netif **netifPP)
if (curr->name == NULL || curr->displayName == NULL) { if (curr->name == NULL || curr->displayName == NULL) {
if (curr->name) free(curr->name); if (curr->name) free(curr->name);
if (curr->displayName) free(curr->displayName); if (curr->displayName) free(curr->displayName);
free(curr);
curr = NULL; curr = NULL;
} }
} }
...@@ -593,7 +594,10 @@ jobject createNetworkInterface ...@@ -593,7 +594,10 @@ jobject createNetworkInterface
/* default ctor will set family to AF_INET */ /* default ctor will set family to AF_INET */
setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr)); setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr));
JNU_CHECK_EXCEPTION_RETURN(env, NULL); if ((*env)->ExceptionCheck(env)) {
free_netaddr(netaddrP);
return NULL;
}
if (addrs->mask != -1) { if (addrs->mask != -1) {
ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
if (ibObj == NULL) { if (ibObj == NULL) {
...@@ -607,7 +611,10 @@ jobject createNetworkInterface ...@@ -607,7 +611,10 @@ jobject createNetworkInterface
return NULL; return NULL;
} }
setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr)); setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr));
JNU_CHECK_EXCEPTION_RETURN(env, NULL); if ((*env)->ExceptionCheck(env)) {
free_netaddr(netaddrP);
return NULL;
}
(*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);
(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
...@@ -618,6 +625,7 @@ jobject createNetworkInterface ...@@ -618,6 +625,7 @@ jobject createNetworkInterface
if (iaObj) { if (iaObj) {
int ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); int ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr));
if (ret == JNI_FALSE) { if (ret == JNI_FALSE) {
free_netaddr(netaddrP);
return NULL; return NULL;
} }
......
...@@ -488,8 +488,9 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) ...@@ -488,8 +488,9 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)
jobjectArray addrArr, bindsArr, childArr; jobjectArray addrArr, bindsArr, childArr;
netaddr *addrs; netaddr *addrs;
jint addr_index; jint addr_index;
int netaddrCount=ifs->naddrs; int netaddrCount = ifs->naddrs;
netaddr *netaddrP=ifs->addrs; netaddr *netaddrP = ifs->addrs;
netaddr *netaddrPToFree = NULL;
jint bind_index; jint bind_index;
/* /*
...@@ -520,21 +521,23 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) ...@@ -520,21 +521,23 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)
* Note that 0 is a valid number of addresses. * Note that 0 is a valid number of addresses.
*/ */
if (netaddrCount < 0) { if (netaddrCount < 0) {
netaddrCount = enumAddresses_win(env, ifs, &netaddrP); netaddrCount = enumAddresses_win(env, ifs, &netaddrPToFree);
if (netaddrCount == -1) { if (netaddrCount == -1) {
return NULL; return NULL;
} }
netaddrP = netaddrPToFree;
} }
addrArr = (*env)->NewObjectArray(env, netaddrCount, ia_class, NULL); addrArr = (*env)->NewObjectArray(env, netaddrCount, ia_class, NULL);
if (addrArr == NULL) { if (addrArr == NULL) {
free_netaddr(netaddrPToFree);
return NULL; return NULL;
} }
bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL); bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL);
if (bindsArr == NULL) { if (bindsArr == NULL) {
free_netaddr(netaddrP); free_netaddr(netaddrPToFree);
return NULL; return NULL;
} }
addrs = netaddrP; addrs = netaddrP;
...@@ -546,26 +549,32 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) ...@@ -546,26 +549,32 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)
if (addrs->addr.him.sa_family == AF_INET) { if (addrs->addr.him.sa_family == AF_INET) {
iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID); iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
if (iaObj == NULL) { if (iaObj == NULL) {
free_netaddr(netaddrPToFree);
return NULL; return NULL;
} }
/* default ctor will set family to AF_INET */ /* default ctor will set family to AF_INET */
setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr)); setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr));
if ((*env)->ExceptionCheck(env)) {
JNU_CHECK_EXCEPTION_RETURN(env, NULL); free_netaddr(netaddrPToFree);
return NULL;
}
ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
if (ibObj == NULL) { if (ibObj == NULL) {
free_netaddr(netaddrP); free_netaddr(netaddrPToFree);
return NULL; return NULL;
} }
(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID); ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
if (ia2Obj == NULL) { if (ia2Obj == NULL) {
free_netaddr(netaddrP); free_netaddr(netaddrPToFree);
return NULL; return NULL;
} }
setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr)); setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr));
JNU_CHECK_EXCEPTION_RETURN(env, NULL); if ((*env)->ExceptionCheck(env)) {
free_netaddr(netaddrPToFree);
return NULL;
}
(*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);
(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
...@@ -574,10 +583,12 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) ...@@ -574,10 +583,12 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)
int ret; int ret;
iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID); iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
if (iaObj == NULL) { if (iaObj == NULL) {
free_netaddr(netaddrPToFree);
return NULL; return NULL;
} }
ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr));
if (ret == JNI_FALSE) { if (ret == JNI_FALSE) {
free_netaddr(netaddrPToFree);
return NULL; return NULL;
} }
scope = addrs->addr.him6.sin6_scope_id; scope = addrs->addr.him6.sin6_scope_id;
...@@ -587,8 +598,8 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) ...@@ -587,8 +598,8 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)
} }
ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
if (ibObj == NULL) { if (ibObj == NULL) {
free_netaddr(netaddrP); free_netaddr(netaddrPToFree);
return NULL; return NULL;
} }
(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
...@@ -601,6 +612,8 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) ...@@ -601,6 +612,8 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)
(*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr); (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
(*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr); (*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr);
free_netaddr(netaddrPToFree);
/* /*
* Windows doesn't have virtual interfaces, so child array * Windows doesn't have virtual interfaces, so child array
* is always empty. * is always empty.
...@@ -640,7 +653,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0_XP ...@@ -640,7 +653,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0_XP
} }
/* if found create a NetworkInterface */ /* if found create a NetworkInterface */
if (curr != NULL) {; if (curr != NULL) {
netifObj = createNetworkInterfaceXP(env, curr); netifObj = createNetworkInterfaceXP(env, curr);
} }
...@@ -767,6 +780,7 @@ JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll_XP ...@@ -767,6 +780,7 @@ JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll_XP
/* allocate a NetworkInterface array */ /* allocate a NetworkInterface array */
netIFArr = (*env)->NewObjectArray(env, count, cls, NULL); netIFArr = (*env)->NewObjectArray(env, count, cls, NULL);
if (netIFArr == NULL) { if (netIFArr == NULL) {
free_netif(ifList);
return NULL; return NULL;
} }
...@@ -781,6 +795,7 @@ JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll_XP ...@@ -781,6 +795,7 @@ JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll_XP
netifObj = createNetworkInterfaceXP(env, curr); netifObj = createNetworkInterfaceXP(env, curr);
if (netifObj == NULL) { if (netifObj == NULL) {
free_netif(ifList);
return NULL; return NULL;
} }
......
...@@ -445,7 +445,6 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, ...@@ -445,7 +445,6 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
"Protocol family not supported"); "Protocol family not supported");
return; return;
} }
JNU_CHECK_EXCEPTION(env);
if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
return; return;
......
...@@ -183,7 +183,6 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed ...@@ -183,7 +183,6 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
{ {
HCRYPTPROV hCryptProv = NULL; HCRYPTPROV hCryptProv = NULL;
BYTE* pbData = NULL;
jbyte* reseedBytes = NULL; jbyte* reseedBytes = NULL;
jbyte* seedBytes = NULL; jbyte* seedBytes = NULL;
jbyteArray result = NULL; jbyteArray result = NULL;
...@@ -227,28 +226,17 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed ...@@ -227,28 +226,17 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
result = NULL; result = NULL;
} else if (length > 0) { } else {
pbData = new (env) BYTE[length];
if (pbData == NULL) {
__leave;
}
if (::CryptGenRandom(
hCryptProv,
length,
pbData) == FALSE) {
ThrowException(env, PROVIDER_EXCEPTION, GetLastError()); if (length > 0) {
__leave; seed = env->NewByteArray(length);
if (seed == NULL) {
__leave;
}
} else {
length = env->GetArrayLength(seed);
} }
result = env->NewByteArray(length);
env->SetByteArrayRegion(result, 0, length, (jbyte*) pbData);
} else { // length == 0
length = env->GetArrayLength(seed);
if ((seedBytes = env->GetByteArrayElements(seed, 0)) == NULL) { if ((seedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {
__leave; __leave;
} }
...@@ -273,9 +261,6 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed ...@@ -273,9 +261,6 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
if (reseedBytes) if (reseedBytes)
env->ReleaseByteArrayElements(seed, reseedBytes, JNI_ABORT); env->ReleaseByteArrayElements(seed, reseedBytes, JNI_ABORT);
if (pbData)
delete [] pbData;
if (seedBytes) if (seedBytes)
env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig
......
...@@ -27,9 +27,8 @@ ...@@ -27,9 +27,8 @@
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import javax.sound.sampled.*; import com.sun.media.sound.RIFFReader;
import com.sun.media.sound.RIFFWriter;
import com.sun.media.sound.*;
public class Skip { public class Skip {
...@@ -40,6 +39,11 @@ public class Skip { ...@@ -40,6 +39,11 @@ public class Skip {
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
test(false);
test(true);
}
private static void test(boolean customStream) throws Exception {
RIFFWriter writer = null; RIFFWriter writer = null;
RIFFReader reader = null; RIFFReader reader = null;
File tempfile = File.createTempFile("test",".riff"); File tempfile = File.createTempFile("test",".riff");
...@@ -51,7 +55,17 @@ public class Skip { ...@@ -51,7 +55,17 @@ public class Skip {
chunk.write((byte)44); chunk.write((byte)44);
writer.close(); writer.close();
writer = null; writer = null;
FileInputStream fis = new FileInputStream(tempfile); final FileInputStream fis;
if (customStream) {
fis = new FileInputStream(tempfile);
} else {
fis = new FileInputStream(tempfile) {
@Override
public long skip(long n) {
return 0;
}
};
}
reader = new RIFFReader(fis); reader = new RIFFReader(fis);
RIFFReader readchunk = reader.nextChunk(); RIFFReader readchunk = reader.nextChunk();
reader.skip(1); reader.skip(1);
......
/*
* Copyright (c) 2013, 2018, 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.
*/
package jdk.testlibrary;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.Arrays;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.FileObject;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
/**
* {@code InMemoryJavaCompiler} can be used for compiling a {@link
* CharSequence} to a {@code byte[]}.
*
* The compiler will not use the file system at all, instead using a {@link
* ByteArrayOutputStream} for storing the byte code. For the source code, any
* kind of {@link CharSequence} can be used, e.g. {@link String}, {@link
* StringBuffer} or {@link StringBuilder}.
*
* The {@code InMemoryCompiler} can easily be used together with a {@code
* ByteClassLoader} to easily compile and load source code in a {@link String}:
*
* <pre>
* {@code
* import com.oracle.java.testlibrary.InMemoryJavaCompiler;
* import com.oracle.java.testlibrary.ByteClassLoader;
*
* class Example {
* public static void main(String[] args) {
* String className = "Foo";
* String sourceCode = "public class " + className + " {" +
* " public void bar() {" +
* " System.out.println("Hello from bar!");" +
* " }" +
* "}";
* byte[] byteCode = InMemoryJavaCompiler.compile(className, sourceCode);
* Class fooClass = ByteClassLoader.load(className, byteCode);
* }
* }
* }
* </pre>
*/
public class InMemoryJavaCompiler {
private static class MemoryJavaFileObject extends SimpleJavaFileObject {
private final String className;
private final CharSequence sourceCode;
private final ByteArrayOutputStream byteCode;
public MemoryJavaFileObject(String className, CharSequence sourceCode) {
super(URI.create("string:///" + className.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE);
this.className = className;
this.sourceCode = sourceCode;
this.byteCode = new ByteArrayOutputStream();
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return sourceCode;
}
@Override
public OutputStream openOutputStream() throws IOException {
return byteCode;
}
public byte[] getByteCode() {
return byteCode.toByteArray();
}
public String getClassName() {
return className;
}
}
private static class FileManagerWrapper extends ForwardingJavaFileManager {
private MemoryJavaFileObject file;
public FileManagerWrapper(MemoryJavaFileObject file) {
super(getCompiler().getStandardFileManager(null, null, null));
this.file = file;
}
@Override
public JavaFileObject getJavaFileForOutput(Location location, String className,
Kind kind, FileObject sibling)
throws IOException {
if (!file.getClassName().equals(className)) {
throw new IOException("Expected class with name " + file.getClassName() +
", but got " + className);
}
return file;
}
}
/**
* Compiles the class with the given name and source code.
*
* @param className The name of the class
* @param sourceCode The source code for the class with name {@code className}
* @throws RuntimeException if the compilation did not succeed
* @return The resulting byte code from the compilation
*/
public static byte[] compile(String className, CharSequence sourceCode) {
MemoryJavaFileObject file = new MemoryJavaFileObject(className, sourceCode);
CompilationTask task = getCompilationTask(file);
if(!task.call()) {
throw new RuntimeException("Could not compile " + className + " with source code " + sourceCode);
}
return file.getByteCode();
}
private static JavaCompiler getCompiler() {
return ToolProvider.getSystemJavaCompiler();
}
private static CompilationTask getCompilationTask(MemoryJavaFileObject file) {
return getCompiler().getTask(null, new FileManagerWrapper(file), null, null, null, Arrays.asList(file));
}
}
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -23,16 +23,21 @@ ...@@ -23,16 +23,21 @@
package jdk.testlibrary; package jdk.testlibrary;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.InvalidPathException; import java.nio.file.InvalidPathException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
...@@ -44,6 +49,72 @@ import java.util.jar.Manifest; ...@@ -44,6 +49,72 @@ import java.util.jar.Manifest;
*/ */
public final class JarUtils { public final class JarUtils {
/**
* Creates a JAR file.
*
* Equivalent to {@code jar cfm <jarfile> <manifest> -C <dir> file...}
*
* The input files are resolved against the given directory. Any input
* files that are directories are processed recursively.
*/
public static void createJarFile(Path jarfile, Manifest man, Path dir, Path... file)
throws IOException
{
// create the target directory
Path parent = jarfile.getParent();
if (parent != null)
Files.createDirectories(parent);
List<Path> entries = new ArrayList<>();
for (Path entry : file) {
Files.find(dir.resolve(entry), Integer.MAX_VALUE,
(p, attrs) -> attrs.isRegularFile())
.map(e -> dir.relativize(e))
.forEach(entries::add);
}
try (OutputStream out = Files.newOutputStream(jarfile);
JarOutputStream jos = new JarOutputStream(out))
{
if (man != null) {
JarEntry je = new JarEntry(JarFile.MANIFEST_NAME);
jos.putNextEntry(je);
man.write(jos);
jos.closeEntry();
}
for (Path entry : entries) {
String name = toJarEntryName(entry);
jos.putNextEntry(new JarEntry(name));
Files.copy(dir.resolve(entry), jos);
jos.closeEntry();
}
}
}
/**
* Creates a JAR file.
*
* Equivalent to {@code jar cf <jarfile> -C <dir> file...}
*
* The input files are resolved against the given directory. Any input
* files that are directories are processed recursively.
*/
public static void createJarFile(Path jarfile, Path dir, Path... file)
throws IOException
{
createJarFile(jarfile, null, dir, file);
}
/**
* Creates a JAR file from the contents of a directory.
*
* Equivalent to {@code jar cf <jarfile> -C <dir> .}
*/
public static void createJarFile(Path jarfile, Path dir) throws IOException {
createJarFile(jarfile, dir, Paths.get("."));
}
/** /**
* Create jar file with specified files. If a specified file does not exist, * Create jar file with specified files. If a specified file does not exist,
* a new jar entry will be created with the file name itself as the content. * a new jar entry will be created with the file name itself as the content.
...@@ -126,6 +197,11 @@ public final class JarUtils { ...@@ -126,6 +197,11 @@ public final class JarUtils {
changes = new HashMap<>(changes); changes = new HashMap<>(changes);
System.out.printf("Creating %s from %s...\n", dest, src); System.out.printf("Creating %s from %s...\n", dest, src);
if (dest.equals(src)) {
throw new IOException("src and dest cannot be the same");
}
try (JarOutputStream jos = new JarOutputStream( try (JarOutputStream jos = new JarOutputStream(
new FileOutputStream(dest))) { new FileOutputStream(dest))) {
...@@ -153,6 +229,24 @@ public final class JarUtils { ...@@ -153,6 +229,24 @@ public final class JarUtils {
System.out.println(); System.out.println();
} }
/**
* Update the Manifest inside a jar.
*
* @param src the original jar file name
* @param dest the new jar file name
* @param man the Manifest
*
* @throws IOException
*/
public static void updateManifest(String src, String dest, Manifest man)
throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
man.write(bout);
Map<String, Object> map = new HashMap<>();
map.put(JarFile.MANIFEST_NAME, bout.toByteArray());
updateJar(src, dest, map);
}
private static void updateEntry(JarOutputStream jos, String name, Object content) private static void updateEntry(JarOutputStream jos, String name, Object content)
throws IOException { throws IOException {
if (content instanceof Boolean) { if (content instanceof Boolean) {
...@@ -172,4 +266,14 @@ public final class JarUtils { ...@@ -172,4 +266,14 @@ public final class JarUtils {
} }
} }
} }
/**
* Map a file path to the equivalent name in a JAR file
*/
private static String toJarEntryName(Path file) {
Path normalized = file.normalize();
return normalized.subpath(0, normalized.getNameCount()) // drop root
.toString()
.replace(File.separatorChar, '/');
}
} }
...@@ -39,7 +39,7 @@ public final class OutputAnalyzer { ...@@ -39,7 +39,7 @@ public final class OutputAnalyzer {
private final String stdout; private final String stdout;
private final String stderr; private final String stderr;
private final int exitValue; private final int exitValue; // useless now. output contains exit value.
/** /**
* Create an OutputAnalyzer, a utility class for verifying output and exit * Create an OutputAnalyzer, a utility class for verifying output and exit
......
/* /*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,6 +25,7 @@ package jdk.testlibrary; ...@@ -25,6 +25,7 @@ package jdk.testlibrary;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean; import java.lang.management.RuntimeMXBean;
...@@ -353,9 +354,31 @@ public final class ProcessTools { ...@@ -353,9 +354,31 @@ public final class ProcessTools {
* @return The output from the process. * @return The output from the process.
*/ */
public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Throwable { public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Throwable {
return executeProcess(pb, null);
}
/**
* Executes a process, pipe some text into its STDIN, waits for it
* to finish and returns the process output. The process will have exited
* before this method returns.
* @param pb The ProcessBuilder to execute.
* @param input The text to pipe into STDIN. Can be null.
* @return The {@linkplain OutputAnalyzer} instance wrapping the process.
*/
public static OutputAnalyzer executeProcess(ProcessBuilder pb, String input)
throws Throwable {
OutputAnalyzer output = null; OutputAnalyzer output = null;
Process p = null;
try { try {
output = new OutputAnalyzer(pb.start()); p = pb.start();
if (input != null) {
try (OutputStream os = p.getOutputStream();
PrintStream ps = new PrintStream(os)) {
ps.print(input);
ps.flush();
}
}
output = new OutputAnalyzer(p);
return output; return output;
} catch (Throwable t) { } catch (Throwable t) {
System.out.println("executeProcess() failed: " + t); System.out.println("executeProcess() failed: " + t);
......
...@@ -49,10 +49,7 @@ public class SecurityTools { ...@@ -49,10 +49,7 @@ public class SecurityTools {
launcher.addToolArg(arg); launcher.addToolArg(arg);
} }
} }
String[] cmds = launcher.getCommand(); return new ProcessBuilder(launcher.getCommand());
String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" "));
System.out.println("Command line: [" + cmdLine + "]");
return new ProcessBuilder(cmds);
} }
// keytool // keytool
...@@ -69,7 +66,7 @@ public class SecurityTools { ...@@ -69,7 +66,7 @@ public class SecurityTools {
pb.redirectInput(ProcessBuilder.Redirect.from(new File(RESPONSE_FILE))); pb.redirectInput(ProcessBuilder.Redirect.from(new File(RESPONSE_FILE)));
try { try {
return ProcessTools.executeProcess(pb); return execute(pb);
} catch (Throwable t) { } catch (Throwable t) {
throw new RuntimeException("keytool failure: " + t); throw new RuntimeException("keytool failure: " + t);
} finally { } finally {
...@@ -101,11 +98,20 @@ public class SecurityTools { ...@@ -101,11 +98,20 @@ public class SecurityTools {
public static OutputAnalyzer jarsigner(List<String> args) public static OutputAnalyzer jarsigner(List<String> args)
throws Exception { throws Exception {
return execute(getProcessBuilder("jarsigner", args));
}
private static OutputAnalyzer execute(ProcessBuilder pb) throws Exception {
try { try {
return ProcessTools.executeProcess( OutputAnalyzer oa = ProcessTools.executeCommand(pb);
getProcessBuilder("jarsigner", args)); System.out.println("Exit value: " + oa.getExitValue());
return oa;
} catch (Throwable t) { } catch (Throwable t) {
throw new RuntimeException("jarsigner error: " + t); if (t instanceof Exception) {
throw (Exception) t;
} else {
throw new Exception(t);
}
} }
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
*/ */
/* @test /* @test
* @bug 8193833 * @bug 8158963
* *
* @summary Disable RMI over HTTP by default * @summary Disable RMI over HTTP by default
* *
......
/* /*
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
*/ */
import com.sun.net.httpserver.*; import com.sun.net.httpserver.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
...@@ -36,16 +38,18 @@ import java.security.KeyStore; ...@@ -36,16 +38,18 @@ import java.security.KeyStore;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.Signature; import java.security.Signature;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.ArrayList; import java.time.Instant;
import java.util.Arrays; import java.time.temporal.ChronoUnit;
import java.util.Calendar; import java.util.*;
import java.util.List;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import sun.misc.IOUtils; import sun.misc.IOUtils;
import jdk.testlibrary.*; import jdk.testlibrary.SecurityTools;
import jdk.testlibrary.OutputAnalyzer;
import jdk.testlibrary.JarUtils; import jdk.testlibrary.JarUtils;
import sun.security.pkcs.ContentInfo; import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7; import sun.security.pkcs.PKCS7;
...@@ -58,9 +62,12 @@ import sun.security.util.ObjectIdentifier; ...@@ -58,9 +62,12 @@ import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId; import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name; import sun.security.x509.X500Name;
import jdk.testlibrary.Utils;
/* /*
* @test * @test
* @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8169688 8171121 * @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8169688 8171121
* 8180289
* @summary checking response of timestamp * @summary checking response of timestamp
* @modules java.base/sun.security.pkcs * @modules java.base/sun.security.pkcs
* java.base/sun.security.timestamp * java.base/sun.security.timestamp
...@@ -68,7 +75,7 @@ import sun.security.x509.X500Name; ...@@ -68,7 +75,7 @@ import sun.security.x509.X500Name;
* java.base/sun.security.util * java.base/sun.security.util
* java.base/sun.security.tools.keytool * java.base/sun.security.tools.keytool
* @library /lib/testlibrary * @library /lib/testlibrary
* @run main/timeout=600 TimestampCheck * @run main/othervm/timeout=600 TimestampCheck
*/ */
public class TimestampCheck { public class TimestampCheck {
...@@ -114,12 +121,12 @@ public class TimestampCheck { ...@@ -114,12 +121,12 @@ public class TimestampCheck {
*/ */
byte[] sign(byte[] input, String path) throws Exception { byte[] sign(byte[] input, String path) throws Exception {
DerValue value = new DerValue(input); DerValue value = new DerValue(input);
System.err.println("\nIncoming Request\n==================="); System.out.println("\nIncoming Request\n===================");
System.err.println("Version: " + value.data.getInteger()); System.out.println("Version: " + value.data.getInteger());
DerValue messageImprint = value.data.getDerValue(); DerValue messageImprint = value.data.getDerValue();
AlgorithmId aid = AlgorithmId.parse( AlgorithmId aid = AlgorithmId.parse(
messageImprint.data.getDerValue()); messageImprint.data.getDerValue());
System.err.println("AlgorithmId: " + aid); System.out.println("AlgorithmId: " + aid);
ObjectIdentifier policyId = new ObjectIdentifier(defaultPolicyId); ObjectIdentifier policyId = new ObjectIdentifier(defaultPolicyId);
BigInteger nonce = null; BigInteger nonce = null;
...@@ -127,25 +134,24 @@ public class TimestampCheck { ...@@ -127,25 +134,24 @@ public class TimestampCheck {
DerValue v = value.data.getDerValue(); DerValue v = value.data.getDerValue();
if (v.tag == DerValue.tag_Integer) { if (v.tag == DerValue.tag_Integer) {
nonce = v.getBigInteger(); nonce = v.getBigInteger();
System.err.println("nonce: " + nonce); System.out.println("nonce: " + nonce);
} else if (v.tag == DerValue.tag_Boolean) { } else if (v.tag == DerValue.tag_Boolean) {
System.err.println("certReq: " + v.getBoolean()); System.out.println("certReq: " + v.getBoolean());
} else if (v.tag == DerValue.tag_ObjectId) { } else if (v.tag == DerValue.tag_ObjectId) {
policyId = v.getOID(); policyId = v.getOID();
System.err.println("PolicyID: " + policyId); System.out.println("PolicyID: " + policyId);
} }
} }
System.err.println("\nResponse\n==================="); System.out.println("\nResponse\n===================");
FileInputStream is = new FileInputStream(keystore); FileInputStream is = new FileInputStream(keystore);
KeyStore ks = KeyStore.getInstance("JCEKS"); KeyStore ks = KeyStore.getInstance("JCEKS");
ks.load(is, "changeit".toCharArray()); ks.load(is, "changeit".toCharArray());
is.close(); is.close();
String alias = "ts"; // If path starts with "ts", use the TSA it points to.
if (path.startsWith("bad") || path.equals("weak")) { // Otherwise, always use "ts".
alias = "ts" + path; String alias = path.startsWith("ts") ? path : "ts";
}
if (path.equals("diffpolicy")) { if (path.equals("diffpolicy")) {
policyId = new ObjectIdentifier(defaultPolicyId); policyId = new ObjectIdentifier(defaultPolicyId);
...@@ -192,8 +198,11 @@ public class TimestampCheck { ...@@ -192,8 +198,11 @@ public class TimestampCheck {
tst.putInteger(1); tst.putInteger(1);
Calendar cal = Calendar.getInstance(); Instant instant = Instant.now();
tst.putGeneralizedTime(cal.getTime()); if (path.equals("tsold")) {
instant = instant.minus(20, ChronoUnit.DAYS);
}
tst.putGeneralizedTime(Date.from(instant));
if (path.equals("diffnonce")) { if (path.equals("diffnonce")) {
tst.putInteger(1234); tst.putInteger(1234);
...@@ -220,10 +229,10 @@ public class TimestampCheck { ...@@ -220,10 +229,10 @@ public class TimestampCheck {
"1.2.840.113549.1.9.16.1.4"), "1.2.840.113549.1.9.16.1.4"),
new DerValue(tstInfo2.toByteArray())); new DerValue(tstInfo2.toByteArray()));
System.err.println("Signing..."); System.out.println("Signing...");
System.err.println(new X500Name(signer System.out.println(new X500Name(signer
.getIssuerX500Principal().getName())); .getIssuerX500Principal().getName()));
System.err.println(signer.getSerialNumber()); System.out.println(signer.getSerialNumber());
SignerInfo signerInfo = new SignerInfo( SignerInfo signerInfo = new SignerInfo(
new X500Name(signer.getIssuerX500Principal().getName()), new X500Name(signer.getIssuerX500Principal().getName()),
...@@ -296,25 +305,53 @@ public class TimestampCheck { ...@@ -296,25 +305,53 @@ public class TimestampCheck {
prepare(); prepare();
try (Handler tsa = Handler.init(0, "tsks");) { try (Handler tsa = Handler.init(0, "ks");) {
tsa.start(); tsa.start();
int port = tsa.getPort(); int port = tsa.getPort();
host = "http://localhost:" + port + "/"; host = "http://localhost:" + port + "/";
if (args.length == 0) { // Run this test if (args.length == 0) { // Run this test
sign("none")
.shouldContain("is not timestamped") sign("normal")
.shouldNotContain("Warning")
.shouldHaveExitValue(0); .shouldHaveExitValue(0);
sign("badku") verify("normal.jar")
.shouldNotContain("Warning")
.shouldHaveExitValue(0); .shouldHaveExitValue(0);
checkBadKU("badku.jar");
sign("normal") // Simulate signing at a previous date:
.shouldNotContain("is not timestamped") // 1. tsold will create a timestamp of 20 days ago.
// 2. oldsigner expired 10 days ago.
// jarsigner will show a warning at signing.
signVerbose("tsold", "unsigned.jar", "tsold.jar", "oldsigner")
.shouldHaveExitValue(4);
// It verifies perfectly.
verify("tsold.jar", "-verbose", "-certs")
.shouldNotContain("Warning")
.shouldHaveExitValue(0); .shouldHaveExitValue(0);
signVerbose(null, "unsigned.jar", "none.jar", "signer")
.shouldContain("is not timestamped")
.shouldHaveExitValue(0);
signVerbose(null, "unsigned.jar", "badku.jar", "badku")
.shouldHaveExitValue(8);
checkBadKU("badku.jar");
// 8180289: unvalidated TSA cert chain
sign("tsnoca")
.shouldContain("TSA certificate chain is invalid")
.shouldHaveExitValue(64);
verify("tsnoca.jar", "-verbose", "-certs")
.shouldHaveExitValue(64)
.shouldContain("jar verified")
.shouldContain("Invalid TSA certificate chain")
.shouldContain("TSA certificate chain is invalid");
sign("nononce") sign("nononce")
.shouldHaveExitValue(1); .shouldHaveExitValue(1);
sign("diffnonce") sign("diffnonce")
...@@ -325,11 +362,11 @@ public class TimestampCheck { ...@@ -325,11 +362,11 @@ public class TimestampCheck {
.shouldHaveExitValue(1); .shouldHaveExitValue(1);
sign("fullchain") sign("fullchain")
.shouldHaveExitValue(0); // Success, 6543440 solved. .shouldHaveExitValue(0); // Success, 6543440 solved.
sign("bad1") sign("tsbad1")
.shouldHaveExitValue(1); .shouldHaveExitValue(1);
sign("bad2") sign("tsbad2")
.shouldHaveExitValue(1); .shouldHaveExitValue(1);
sign("bad3") sign("tsbad3")
.shouldHaveExitValue(1); .shouldHaveExitValue(1);
sign("nocert") sign("nocert")
.shouldHaveExitValue(1); .shouldHaveExitValue(1);
...@@ -341,119 +378,171 @@ public class TimestampCheck { ...@@ -341,119 +378,171 @@ public class TimestampCheck {
sign("diffpolicy", "-tsapolicyid", "1.2.3") sign("diffpolicy", "-tsapolicyid", "1.2.3")
.shouldHaveExitValue(1); .shouldHaveExitValue(1);
sign("tsaalg", "-tsadigestalg", "SHA") sign("sha1alg", "-tsadigestalg", "SHA")
.shouldHaveExitValue(0); .shouldHaveExitValue(0);
checkTimestamp("tsaalg.jar", defaultPolicyId, "SHA-1"); checkTimestamp("sha1alg.jar", defaultPolicyId, "SHA-1");
sign("weak", "-digestalg", "MD5", sign("tsweak", "-digestalg", "MD5",
"-sigalg", "MD5withRSA", "-tsadigestalg", "MD5") "-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
.shouldHaveExitValue(0); .shouldHaveExitValue(68);
checkWeak("weak.jar"); checkWeak("tsweak.jar");
signWithAliasAndTsa("halfWeak", "old.jar", "old", "-digestalg", "MD5") signVerbose("tsweak", "unsigned.jar", "tsweak2.jar", "signer")
.shouldHaveExitValue(0); .shouldHaveExitValue(64)
.shouldContain("TSA certificate chain is invalid");
// Weak timestamp is an error and jar treated unsigned
verify("tsweak2.jar", "-verbose")
.shouldHaveExitValue(16)
.shouldContain("treated as unsigned")
.shouldMatch("Timestamp.*512.*weak");
signVerbose("normal", "unsigned.jar", "halfWeak.jar", "signer",
"-digestalg", "MD5")
.shouldHaveExitValue(4);
checkHalfWeak("halfWeak.jar"); checkHalfWeak("halfWeak.jar");
// sign with DSA key // sign with DSA key
signWithAliasAndTsa("sign1", "old.jar", "dsakey") signVerbose("normal", "unsigned.jar", "sign1.jar", "dsakey")
.shouldHaveExitValue(0); .shouldHaveExitValue(0);
// sign with RSAkeysize < 1024 // sign with RSAkeysize < 1024
signWithAliasAndTsa("sign2", "sign1.jar", "weakkeysize") signVerbose("normal", "sign1.jar", "sign2.jar", "weakkeysize")
.shouldHaveExitValue(0); .shouldHaveExitValue(4);
checkMultiple("sign2.jar"); checkMultiple("sign2.jar");
// When .SF or .RSA is missing or invalid // When .SF or .RSA is missing or invalid
checkMissingOrInvalidFiles("normal.jar"); checkMissingOrInvalidFiles("normal.jar");
if (Files.exists(Paths.get("ts2.cert"))) {
checkInvalidTsaCertKeyUsage();
}
} else { // Run as a standalone server } else { // Run as a standalone server
System.err.println("Press Enter to quit server"); System.out.println("Press Enter to quit server");
System.in.read(); System.in.read();
} }
} }
} }
private static void checkInvalidTsaCertKeyUsage() throws Exception {
// Hack: Rewrite the TSA cert inside normal.jar into ts2.jar.
// Both the cert and the serial number must be rewritten.
byte[] tsCert = Files.readAllBytes(Paths.get("ts.cert"));
byte[] ts2Cert = Files.readAllBytes(Paths.get("ts2.cert"));
byte[] tsSerial = getCert(tsCert)
.getSerialNumber().toByteArray();
byte[] ts2Serial = getCert(ts2Cert)
.getSerialNumber().toByteArray();
byte[] oldBlock;
try (JarFile normal = new JarFile("normal.jar")) {
oldBlock = Utils.readAllBytes(normal.getInputStream(
normal.getJarEntry("META-INF/SIGNER.RSA")));
}
JarUtils.updateJar("normal.jar", "ts2.jar",
mapOf("META-INF/SIGNER.RSA",
updateBytes(updateBytes(oldBlock, tsCert, ts2Cert),
tsSerial, ts2Serial)));
verify("ts2.jar", "-verbose", "-certs")
.shouldHaveExitValue(64)
.shouldContain("jar verified")
.shouldContain("Invalid TSA certificate chain: Extended key usage does not permit use for TSA server");
}
public static X509Certificate getCert(byte[] data)
throws CertificateException, IOException {
return (X509Certificate)
CertificateFactory.getInstance("X.509")
.generateCertificate(new ByteArrayInputStream(data));
}
private static byte[] updateBytes(byte[] old, byte[] from, byte[] to) {
int pos = 0;
while (true) {
if (pos + from.length > old.length) {
return null;
}
if (Arrays.equals(Arrays.copyOfRange(old, pos, pos+from.length), from)) {
byte[] result = old.clone();
System.arraycopy(to, 0, result, pos, from.length);
return result;
}
pos++;
}
}
private static void checkMissingOrInvalidFiles(String s) private static void checkMissingOrInvalidFiles(String s)
throws Throwable { throws Throwable {
JarUtils.updateJar(s, "1.jar", "-", "META-INF/OLD.SF");
JarUtils.updateJar(s, "1.jar", mapOf("META-INF/SIGNER.SF", Boolean.FALSE));
verify("1.jar", "-verbose") verify("1.jar", "-verbose")
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldContain("treated as unsigned") .shouldContain("treated as unsigned")
.shouldContain("Missing signature-related file META-INF/OLD.SF"); .shouldContain("Missing signature-related file META-INF/SIGNER.SF");
JarUtils.updateJar(s, "2.jar", "-", "META-INF/OLD.RSA"); JarUtils.updateJar(s, "2.jar", mapOf("META-INF/SIGNER.RSA", Boolean.FALSE));
verify("2.jar", "-verbose") verify("2.jar", "-verbose")
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldContain("treated as unsigned") .shouldContain("treated as unsigned")
.shouldContain("Missing block file for signature-related file META-INF/OLD.SF"); .shouldContain("Missing block file for signature-related file META-INF/SIGNER.SF");
JarUtils.updateJar(s, "3.jar", "META-INF/OLD.SF"); JarUtils.updateJar(s, "3.jar", mapOf("META-INF/SIGNER.SF", "dummy"));
verify("3.jar", "-verbose") verify("3.jar", "-verbose")
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldContain("treated as unsigned") .shouldContain("treated as unsigned")
.shouldContain("Unparsable signature-related file META-INF/OLD.SF"); .shouldContain("Unparsable signature-related file META-INF/SIGNER.SF");
JarUtils.updateJar(s, "4.jar", "META-INF/OLD.RSA"); JarUtils.updateJar(s, "4.jar", mapOf("META-INF/SIGNER.RSA", "dummy"));
verify("4.jar", "-verbose") verify("4.jar", "-verbose")
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldContain("treated as unsigned") .shouldContain("treated as unsigned")
.shouldContain("Unparsable signature-related file META-INF/OLD.RSA"); .shouldContain("Unparsable signature-related file META-INF/SIGNER.RSA");
} }
static OutputAnalyzer jarsigner(List<String> extra) static OutputAnalyzer jarsigner(List<String> extra)
throws Throwable { throws Exception {
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner") List<String> args = new ArrayList<>(
.addVMArg("-Duser.language=en") listOf("-keystore", "ks", "-storepass", "changeit"));
.addVMArg("-Duser.country=US") args.addAll(extra);
.addToolArg("-keystore") return SecurityTools.jarsigner(args);
.addToolArg("tsks")
.addToolArg("-storepass")
.addToolArg("changeit");
for (String s : extra) {
if (s.startsWith("-J")) {
launcher.addVMArg(s.substring(2));
} else {
launcher.addToolArg(s);
}
}
System.err.println("COMMAND: ");
for (String cmd : launcher.getCommand()) {
System.err.print(cmd + " ");
}
System.err.println();
return ProcessTools.executeCommand(launcher.getCommand());
} }
static OutputAnalyzer verify(String file, String... extra) static OutputAnalyzer verify(String file, String... extra)
throws Throwable { throws Exception {
List<String> args = new ArrayList<>(); List<String> args = new ArrayList<>();
args.add("-verify"); args.add("-verify");
args.add("-strict");
args.add(file); args.add(file);
args.addAll(Arrays.asList(extra)); args.addAll(Arrays.asList(extra));
return jarsigner(args); return jarsigner(args);
} }
static void checkBadKU(String file) throws Throwable { static void checkBadKU(String file) throws Exception {
System.err.println("BadKU: " + file); System.err.println("BadKU: " + file);
verify(file) verify(file)
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldContain("treated as unsigned") .shouldContain("treated as unsigned")
.shouldContain("re-run jarsigner with debug enabled"); .shouldContain("re-run jarsigner with debug enabled");
verify(file, "-verbose") verify(file, "-verbose")
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldContain("Signed by") .shouldContain("Signed by")
.shouldContain("treated as unsigned") .shouldContain("treated as unsigned")
.shouldContain("re-run jarsigner with debug enabled"); .shouldContain("re-run jarsigner with debug enabled");
verify(file, "-J-Djava.security.debug=jar") verify(file, "-J-Djava.security.debug=jar")
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldContain("SignatureException: Key usage restricted") .shouldContain("SignatureException: Key usage restricted")
.shouldContain("treated as unsigned") .shouldContain("treated as unsigned")
.shouldContain("re-run jarsigner with debug enabled"); .shouldContain("re-run jarsigner with debug enabled");
} }
static void checkWeak(String file) throws Throwable { static void checkWeak(String file) throws Exception {
verify(file) verify(file)
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldContain("treated as unsigned") .shouldContain("treated as unsigned")
.shouldMatch("weak algorithm that is now disabled.") .shouldMatch("weak algorithm that is now disabled.")
.shouldMatch("Re-run jarsigner with the -verbose option for more details"); .shouldMatch("Re-run jarsigner with the -verbose option for more details");
verify(file, "-verbose") verify(file, "-verbose")
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldContain("treated as unsigned") .shouldContain("treated as unsigned")
.shouldMatch("weak algorithm that is now disabled by") .shouldMatch("weak algorithm that is now disabled by")
.shouldMatch("Digest algorithm: .*weak") .shouldMatch("Digest algorithm: .*weak")
...@@ -462,18 +551,18 @@ public class TimestampCheck { ...@@ -462,18 +551,18 @@ public class TimestampCheck {
.shouldNotMatch("Timestamp signature algorithm: .*weak.*weak") .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak")
.shouldMatch("Timestamp signature algorithm: .*key.*weak"); .shouldMatch("Timestamp signature algorithm: .*key.*weak");
verify(file, "-J-Djava.security.debug=jar") verify(file, "-J-Djava.security.debug=jar")
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldMatch("SignatureException:.*disabled"); .shouldMatch("SignatureException:.*disabled");
} }
static void checkHalfWeak(String file) throws Throwable { static void checkHalfWeak(String file) throws Exception {
verify(file) verify(file)
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldContain("treated as unsigned") .shouldContain("treated as unsigned")
.shouldMatch("weak algorithm that is now disabled.") .shouldMatch("weak algorithm that is now disabled.")
.shouldMatch("Re-run jarsigner with the -verbose option for more details"); .shouldMatch("Re-run jarsigner with the -verbose option for more details");
verify(file, "-verbose") verify(file, "-verbose")
.shouldHaveExitValue(0) .shouldHaveExitValue(16)
.shouldContain("treated as unsigned") .shouldContain("treated as unsigned")
.shouldMatch("weak algorithm that is now disabled by") .shouldMatch("weak algorithm that is now disabled by")
.shouldMatch("Digest algorithm: .*weak") .shouldMatch("Digest algorithm: .*weak")
...@@ -483,7 +572,7 @@ public class TimestampCheck { ...@@ -483,7 +572,7 @@ public class TimestampCheck {
.shouldNotMatch("Timestamp signature algorithm: .*key.*weak"); .shouldNotMatch("Timestamp signature algorithm: .*key.*weak");
} }
static void checkMultiple(String file) throws Throwable { static void checkMultiple(String file) throws Exception {
verify(file) verify(file)
.shouldHaveExitValue(0) .shouldHaveExitValue(0)
.shouldContain("jar verified"); .shouldContain("jar verified");
...@@ -500,7 +589,7 @@ public class TimestampCheck { ...@@ -500,7 +589,7 @@ public class TimestampCheck {
static void checkTimestamp(String file, String policyId, String digestAlg) static void checkTimestamp(String file, String policyId, String digestAlg)
throws Exception { throws Exception {
try (JarFile jf = new JarFile(file)) { try (JarFile jf = new JarFile(file)) {
JarEntry je = jf.getJarEntry("META-INF/OLD.RSA"); JarEntry je = jf.getJarEntry("META-INF/SIGNER.RSA");
try (InputStream is = jf.getInputStream(je)) { try (InputStream is = jf.getInputStream(je)) {
byte[] content = IOUtils.readFully(is, -1, true); byte[] content = IOUtils.readFully(is, -1, true);
PKCS7 p7 = new PKCS7(content); PKCS7 p7 = new PKCS7(content);
...@@ -526,26 +615,38 @@ public class TimestampCheck { ...@@ -526,26 +615,38 @@ public class TimestampCheck {
static int which = 0; static int which = 0;
/** /**
* Sign with a TSA path. Always use alias "signer" to sign "unsigned.jar".
* The signed jar name is always path.jar.
*
* @param extra more args given to jarsigner * @param extra more args given to jarsigner
*/ */
static OutputAnalyzer sign(String path, String... extra) static OutputAnalyzer sign(String path, String... extra)
throws Throwable { throws Exception {
String alias = path.equals("badku") ? "badku" : "old"; return signVerbose(
return signWithAliasAndTsa(path, "old.jar", alias, extra); path,
"unsigned.jar",
path + ".jar",
"signer",
extra);
} }
static OutputAnalyzer signWithAliasAndTsa (String path, String jar, static OutputAnalyzer signVerbose(
String alias, String...extra) throws Throwable { String path, // TSA URL path
String oldJar,
String newJar,
String alias, // signer
String...extra) throws Exception {
which++; which++;
System.err.println("\n>> Test #" + which + ": " + Arrays.toString(extra)); System.out.println("\n>> Test #" + which);
List<String> args = new ArrayList<>(); List<String> args = new ArrayList<>();
args.add("-J-Djava.security.egd=file:/dev/./urandom"); args.add("-strict");
args.add("-verbose");
args.add("-debug"); args.add("-debug");
args.add("-signedjar"); args.add("-signedjar");
args.add(path + ".jar"); args.add(newJar);
args.add(jar); args.add(oldJar);
args.add(alias); args.add(alias);
if (!path.equals("none") && !path.equals("badku")) { if (path != null) {
args.add("-tsa"); args.add("-tsa");
args.add(host + path); args.add(host + path);
} }
...@@ -554,24 +655,54 @@ public class TimestampCheck { ...@@ -554,24 +655,54 @@ public class TimestampCheck {
} }
static void prepare() throws Exception { static void prepare() throws Exception {
jdk.testlibrary.JarUtils.createJar("old.jar", "A"); JarUtils.createJar("unsigned.jar", "A");
Files.deleteIfExists(Paths.get("tsks")); Files.deleteIfExists(Paths.get("ks"));
keytool("-alias ca -genkeypair -ext bc -dname CN=CA"); keytool("-alias signer -genkeypair -ext bc -dname CN=signer");
keytool("-alias old -genkeypair -dname CN=old"); keytool("-alias oldsigner -genkeypair -dname CN=oldsigner");
keytool("-alias dsakey -genkeypair -keyalg DSA -dname CN=dsakey"); keytool("-alias dsakey -genkeypair -keyalg DSA -dname CN=dsakey");
keytool("-alias weakkeysize -genkeypair -keysize 512 -dname CN=weakkeysize"); keytool("-alias weakkeysize -genkeypair -keysize 512 -dname CN=weakkeysize");
keytool("-alias badku -genkeypair -dname CN=badku"); keytool("-alias badku -genkeypair -dname CN=badku");
keytool("-alias ts -genkeypair -dname CN=ts"); keytool("-alias ts -genkeypair -dname CN=ts");
keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsbad1"); keytool("-alias tsold -genkeypair -dname CN=tsold");
keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsweak");
keytool("-alias tsbad1 -genkeypair -dname CN=tsbad1"); keytool("-alias tsbad1 -genkeypair -dname CN=tsbad1");
keytool("-alias tsbad2 -genkeypair -dname CN=tsbad2"); keytool("-alias tsbad2 -genkeypair -dname CN=tsbad2");
keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3"); keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3");
keytool("-alias tsnoca -genkeypair -dname CN=tsnoca");
// tsnoca's issuer will be removed from keystore later
keytool("-alias ca -genkeypair -ext bc -dname CN=CA");
gencert("tsnoca", "-ext eku:critical=ts");
keytool("-delete -alias ca");
keytool("-alias ca -genkeypair -ext bc -dname CN=CA -startdate -40d");
gencert("old"); gencert("signer");
gencert("oldsigner", "-startdate -30d -validity 20");
gencert("dsakey"); gencert("dsakey");
gencert("weakkeysize"); gencert("weakkeysize");
gencert("badku", "-ext ku:critical=keyAgreement"); gencert("badku", "-ext ku:critical=keyAgreement");
gencert("ts", "-ext eku:critical=ts"); gencert("ts", "-ext eku:critical=ts");
for (int i = 0; i < 5; i++) {
// Issue another cert for "ts" with a different EKU.
// Length might be different because serial number is
// random. Try several times until a cert with the same
// length is generated so we can substitute ts.cert
// embedded in the PKCS7 block with ts2.cert.
// If cannot create one, related test will be ignored.
keytool("-gencert -alias ca -infile ts.req -outfile ts2.cert " +
"-ext eku:critical=1.3.6.1.5.5.7.3.9");
if (Files.size(Paths.get("ts.cert")) != Files.size(Paths.get("ts2.cert"))) {
Files.delete(Paths.get("ts2.cert"));
System.out.println("Warning: cannot create same length");
} else {
break;
}
}
gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 45");
gencert("tsweak", "-ext eku:critical=ts"); gencert("tsweak", "-ext eku:critical=ts");
gencert("tsbad1"); gencert("tsbad1");
gencert("tsbad2", "-ext eku=ts"); gencert("tsbad2", "-ext eku=ts");
...@@ -590,8 +721,16 @@ public class TimestampCheck { ...@@ -590,8 +721,16 @@ public class TimestampCheck {
} }
static void keytool(String cmd) throws Exception { static void keytool(String cmd) throws Exception {
cmd = "-keystore tsks -storepass changeit -keypass changeit " + cmd = "-keystore ks -storepass changeit -keypass changeit " +
"-keyalg rsa -validity 200 " + cmd; "-keyalg rsa -validity 200 " + cmd;
sun.security.tools.keytool.Main.main(cmd.split(" ")); sun.security.tools.keytool.Main.main(cmd.split(" "));
} }
static <K,V> Map<K,V> mapOf(K k1, V v1) {
return Collections.singletonMap(k1, v1);
}
static <E> List<E> listOf(E... elements) {
return Arrays.asList(elements);
}
} }
...@@ -46,6 +46,7 @@ public class TsacertOptionTest { ...@@ -46,6 +46,7 @@ public class TsacertOptionTest {
+ ".txt"; + ".txt";
private static final String PASSWORD = "changeit"; private static final String PASSWORD = "changeit";
private static final String KEYSTORE = "ks.jks"; private static final String KEYSTORE = "ks.jks";
private static final String CA_KEY_ALIAS = "ca";
private static final String SIGNING_KEY_ALIAS = "sign_alias"; private static final String SIGNING_KEY_ALIAS = "sign_alias";
private static final String TSA_KEY_ALIAS = "ts"; private static final String TSA_KEY_ALIAS = "ts";
private static final String KEY_ALG = "RSA"; private static final String KEY_ALG = "RSA";
...@@ -73,20 +74,52 @@ public class TsacertOptionTest { ...@@ -73,20 +74,52 @@ public class TsacertOptionTest {
// look for free network port for TSA service // look for free network port for TSA service
int port = jdk.testlibrary.Utils.getFreePort(); int port = jdk.testlibrary.Utils.getFreePort();
String host = jdk.testlibrary.Utils.getHostname(); String host = "127.0.0.1";
String tsaUrl = "http://" + host + ":" + port; String tsaUrl = "http://" + host + ":" + port;
// create key pair for jar signing // create key pair for jar signing
ProcessTools.executeCommand(KEYTOOL, ProcessTools.executeCommand(KEYTOOL,
"-genkey", "-genkey",
"-alias", SIGNING_KEY_ALIAS, "-alias", CA_KEY_ALIAS,
"-keyalg", KEY_ALG, "-keyalg", KEY_ALG,
"-keysize", Integer.toString(KEY_SIZE), "-keysize", Integer.toString(KEY_SIZE),
"-keystore", KEYSTORE, "-keystore", KEYSTORE,
"-storepass", PASSWORD, "-storepass", PASSWORD,
"-keypass", PASSWORD, "-keypass", PASSWORD,
"-dname", "CN=Test", "-dname", "CN=CA",
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0); "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
ProcessTools.executeCommand(KEYTOOL,
"-genkey",
"-alias", SIGNING_KEY_ALIAS,
"-keyalg", KEY_ALG,
"-keysize", Integer.toString(KEY_SIZE),
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
"-dname", "CN=Test").shouldHaveExitValue(0);
ProcessTools.executeCommand(KEYTOOL,
"-certreq",
"-alias", SIGNING_KEY_ALIAS,
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
"-file", "certreq").shouldHaveExitValue(0);
ProcessTools.executeCommand(KEYTOOL,
"-gencert",
"-alias", CA_KEY_ALIAS,
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
"-validity", Integer.toString(VALIDITY),
"-infile", "certreq",
"-outfile", "cert").shouldHaveExitValue(0);
ProcessTools.executeCommand(KEYTOOL,
"-importcert",
"-alias", SIGNING_KEY_ALIAS,
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
"-file", "cert").shouldHaveExitValue(0);
// create key pair for TSA service // create key pair for TSA service
// SubjectInfoAccess extension contains URL to TSA service // SubjectInfoAccess extension contains URL to TSA service
......
/*
* Copyright (c) 2015, 2017, 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 jdk.testlibrary.JDKToolLauncher;
import jdk.testlibrary.JarUtils;
import jdk.testlibrary.OutputAnalyzer;
import jdk.testlibrary.ProcessTools;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
/**
* @test
* @bug 8024302 8026037 8130132
* @summary warnings, errors and -strict
* @library /lib/testlibrary
*/
public class Warning {
public static void main(String[] args) throws Throwable {
Files.deleteIfExists(Paths.get("ks"));
newCert("ca", "-validity 365000");
recreateJar();
newCert("a");
run("jarsigner", "a.jar a")
.shouldContain("is self-signed");
run("jarsigner", "a.jar a -strict")
.shouldContain("is self-signed")
.shouldHaveExitValue(4);
// Trusted entry can be self-signed without a warning
run("jarsigner", "-verify a.jar")
.shouldNotContain("is self-signed")
.shouldNotContain("not signed by alias in this keystore");
run("keytool", "-delete -alias a");
// otherwise a warning will be shown
run("jarsigner", "-verify a.jar")
.shouldContain("is self-signed")
.shouldContain("not signed by alias in this keystore");
recreateJar();
newCert("b");
issueCert("b");
run("jarsigner", "a.jar b")
.shouldNotContain("is self-signed");
run("jarsigner", "-verify a.jar")
.shouldNotContain("is self-signed");
run("jarsigner", "a.jar b -digestalg MD5")
.shouldContain("-digestalg option is considered a security risk.");
run("jarsigner", "a.jar b -digestalg MD5 -strict")
.shouldHaveExitValue(4)
.shouldContain("-digestalg option is considered a security risk.");
run("jarsigner", "a.jar b -sigalg MD5withRSA")
.shouldContain("-sigalg option is considered a security risk");
issueCert("b", "-sigalg MD5withRSA");
run("jarsigner", "a.jar b")
.shouldMatch("chain is invalid. Reason:.*MD5withRSA");
recreateJar();
newCert("c", "-keysize 512");
issueCert("c");
run("jarsigner", "a.jar c")
.shouldContain("chain is invalid. " +
"Reason: Algorithm constraints check failed");
recreateJar();
newCert("s1"); issueCert("s1", "-startdate 2000/01/01 -validity 36525");
run("jarsigner", "a.jar s1")
.shouldHaveExitValue(0)
.shouldContain("Warning:")
.shouldNotContain("Error:")
.shouldContain("timestamp").shouldContain("2100-01-01")
.shouldNotContain("with signer errors");
run("jarsigner", "a.jar s1 -strict")
.shouldHaveExitValue(0)
.shouldContain("Warning:")
.shouldNotContain("Error:")
.shouldContain("timestamp").shouldContain("2100-01-01")
.shouldNotContain("with signer errors");
run("jarsigner", "a.jar s1 -verify")
.shouldHaveExitValue(0)
.shouldContain("Warning:")
.shouldNotContain("Error:")
.shouldContain("timestamp").shouldContain("2100-01-01")
.shouldNotContain("with signer errors");
run("jarsigner", "a.jar s1 -verify -strict")
.shouldHaveExitValue(0)
.shouldContain("Warning:")
.shouldNotContain("Error:")
.shouldContain("timestamp").shouldContain("2100-01-01")
.shouldNotContain("with signer errors");
recreateJar();
newCert("s2"); issueCert("s2", "-validity 100");
run("jarsigner", "a.jar s2")
.shouldHaveExitValue(0)
.shouldContain("Warning:")
.shouldNotContain("Error:")
.shouldContain("timestamp")
.shouldContain("will expire")
.shouldNotContain("with signer errors");
run("jarsigner", "a.jar s2 -strict")
.shouldHaveExitValue(0)
.shouldContain("Warning:")
.shouldNotContain("Error:")
.shouldContain("timestamp")
.shouldContain("will expire")
.shouldNotContain("with signer errors");
run("jarsigner", "a.jar s2 -verify")
.shouldHaveExitValue(0)
.shouldContain("Warning:")
.shouldNotContain("Error:")
.shouldContain("timestamp")
.shouldContain("will expire")
.shouldNotContain("with signer errors");
run("jarsigner", "a.jar s2 -verify -strict")
.shouldHaveExitValue(0)
.shouldContain("Warning:")
.shouldNotContain("Error:")
.shouldContain("timestamp")
.shouldContain("will expire")
.shouldNotContain("with signer errors");
recreateJar();
newCert("s3"); issueCert("s3", "-startdate -200d -validity 100");
run("jarsigner", "a.jar s3")
.shouldHaveExitValue(0)
.shouldContain("Warning:")
.shouldContain("has expired")
.shouldNotContain("with signer errors")
.shouldNotContain("Error:");
run("jarsigner", "a.jar s3 -strict")
.shouldHaveExitValue(4)
.shouldContain("with signer errors")
.shouldMatch("(?s).*Error:.*has expired.*Warning:.*");
run("jarsigner", "a.jar s3 -verify")
.shouldHaveExitValue(0)
.shouldContain("Warning:")
.shouldNotContain("with signer errors")
.shouldNotContain("Error:");
run("jarsigner", "a.jar s3 -verify -strict")
.shouldHaveExitValue(4)
.shouldContain("with signer errors")
.shouldMatch("(?s).*Error:.*has expired.*Warning:.*");
}
// Creates a new jar without signature
static void recreateJar() throws Exception {
JarUtils.createJar("a.jar", "ks");
}
// Creates a self-signed cert for alias with zero or more -genkey options
static void newCert(String alias, String... more) throws Throwable {
String args = "-genkeypair -alias " + alias + " -dname CN=" + alias;
for (String s: more) {
args += " " + s;
}
run("keytool", args).shouldHaveExitValue(0);
}
// Asks ca to issue a cert to alias with zero or more -gencert options
static void issueCert(String alias, String...more) throws Throwable {
String req = run("keytool", "-certreq -alias " + alias)
.shouldHaveExitValue(0).getStdout();
String args = "-gencert -alias ca -rfc";
for (String s: more) {
args += " " + s;
}
String cert = run("keytool", args, req)
.shouldHaveExitValue(0).getStdout();
run("keytool", "-import -alias " + alias, cert).shouldHaveExitValue(0);
}
// Runs a java tool with command line arguments
static OutputAnalyzer run(String command, String args)
throws Throwable {
return run(command, args, null);
}
// Runs a java tool with command line arguments and an optional input block
static OutputAnalyzer run(String command, String args, String input)
throws Throwable {
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(command);
launcher.addVMArg("-Duser.language=en").addVMArg("-Duser.country=US");
switch (command) {
case "keytool":
for (String s: new String[] {
"-keystore", "ks", "-storepass", "changeit",
"-storetype", "jks",
"-keypass", "changeit", "-keyalg", "rsa", "-debug"}) {
launcher.addToolArg(s);
}
break;
case "jarsigner":
for (String s: new String[] {
"-keystore", "ks", "-storepass", "changeit",
"-storetype", "jks"}) {
launcher.addToolArg(s);
}
break;
}
for (String arg: args.split(" ")) {
launcher.addToolArg(arg);
}
String[] cmd = launcher.getCommand();
ProcessBuilder pb = new ProcessBuilder(cmd);
OutputAnalyzer out = ProcessTools.executeProcess(pb, input);
System.out.println("======================");
System.out.println(Arrays.toString(cmd));
String msg = " stdout: [" + out.getStdout() + "];\n"
+ " stderr: [" + out.getStderr() + "]\n"
+ " exitValue = " + out.getExitValue() + "\n";
System.out.println(msg);
return out;
}
}
# #
# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -91,7 +91,7 @@ echo $RESULT ...@@ -91,7 +91,7 @@ echo $RESULT
#[ $RESULT = 0 ] || exit 2 #[ $RESULT = 0 ] || exit 2
# Test 3: When no keystore is specified, the error is only # Test 3: When no keystore is specified, the error is only
# "chain not validated" # "chain invalid"
$JARSIGNER -strict -verify a.jar $JARSIGNER -strict -verify a.jar
RESULT=$? RESULT=$?
...@@ -99,7 +99,7 @@ echo $RESULT ...@@ -99,7 +99,7 @@ echo $RESULT
#[ $RESULT = 4 ] || exit 3 #[ $RESULT = 4 ] || exit 3
# Test 4: When unrelated keystore is specified, the error is # Test 4: When unrelated keystore is specified, the error is
# "chain not validated" and "not alias in keystore" # "chain invalid" and "not alias in keystore"
$JARSIGNER -keystore unrelated.jks -strict -verify a.jar $JARSIGNER -keystore unrelated.jks -strict -verify a.jar
RESULT=$? RESULT=$?
......
# #
# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
# #
# @test # @test
# @bug 6802846 # @bug 6802846 8172529
# @summary jarsigner needs enhanced cert validation(options) # @summary jarsigner needs enhanced cert validation(options)
# #
# @run shell concise_jarsigner.sh # @run shell/timeout=240 concise_jarsigner.sh
# #
if [ "${TESTJAVA}" = "" ] ; then if [ "${TESTJAVA}" = "" ] ; then
...@@ -47,12 +47,15 @@ esac ...@@ -47,12 +47,15 @@ esac
# Choose 1024-bit RSA to make sure it runs fine and fast on all platforms. In # Choose 1024-bit RSA to make sure it runs fine and fast on all platforms. In
# fact, every keyalg/keysize combination is OK for this test. # fact, every keyalg/keysize combination is OK for this test.
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore js.jks -keyalg rsa -keysize 1024" TESTTOOLVMOPTS="$TESTTOOLVMOPTS -J-Duser.language=en -J-Duser.country=US"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
JAVAC=$TESTJAVA${FS}bin${FS}javac
rm js.jks KS=js.ks
KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS -keyalg rsa -keysize 1024"
JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}"
JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -debug"
JAVAC="$TESTJAVA${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS}"
rm $KS
echo class A1 {} > A1.java echo class A1 {} > A1.java
echo class A2 {} > A2.java echo class A2 {} > A2.java
...@@ -68,14 +71,14 @@ YEAR=`date +%Y` ...@@ -68,14 +71,14 @@ YEAR=`date +%Y`
# First part: output format # First part: output format
# ========================================================== # ==========================================================
$KT -genkeypair -alias a1 -dname CN=a1 -validity 365 $KT -genkeypair -alias a1 -dname CN=a1 -validity 366
$KT -genkeypair -alias a2 -dname CN=a2 -validity 365 $KT -genkeypair -alias a2 -dname CN=a2 -validity 366
# a.jar includes 8 unsigned, 2 signed by a1 and a2, 2 signed by a3 # a.jar includes 8 unsigned, 2 signed by a1 and a2, 2 signed by a3
$JAR cvf a.jar A1.class A2.class $JAR cvf a.jar A1.class A2.class
$JARSIGNER -keystore js.jks -storepass changeit a.jar a1 $JARSIGNER -keystore $KS -storepass changeit a.jar a1
$JAR uvf a.jar A3.class A4.class $JAR uvf a.jar A3.class A4.class
$JARSIGNER -keystore js.jks -storepass changeit a.jar a2 $JARSIGNER -keystore $KS -storepass changeit a.jar a2
$JAR uvf a.jar A5.class A6.class $JAR uvf a.jar A5.class A6.class
# Verify OK # Verify OK
...@@ -87,15 +90,15 @@ $JARSIGNER -verify a.jar -strict ...@@ -87,15 +90,15 @@ $JARSIGNER -verify a.jar -strict
[ $? = 20 ] || exit $LINENO [ $? = 20 ] || exit $LINENO
# 16(hasUnsignedEntry) # 16(hasUnsignedEntry)
$JARSIGNER -verify a.jar -strict -keystore js.jks $JARSIGNER -verify a.jar -strict -keystore $KS -storepass changeit
[ $? = 16 ] || exit $LINENO [ $? = 16 ] || exit $LINENO
# 16(hasUnsignedEntry)+32(notSignedByAlias) # 16(hasUnsignedEntry)+32(notSignedByAlias)
$JARSIGNER -verify a.jar a1 -strict -keystore js.jks $JARSIGNER -verify a.jar a1 -strict -keystore $KS -storepass changeit
[ $? = 48 ] || exit $LINENO [ $? = 48 ] || exit $LINENO
# 16(hasUnsignedEntry) # 16(hasUnsignedEntry)
$JARSIGNER -verify a.jar a1 a2 -strict -keystore js.jks $JARSIGNER -verify a.jar a1 a2 -strict -keystore $KS -storepass changeit
[ $? = 16 ] || exit $LINENO [ $? = 16 ] || exit $LINENO
# 12 entries all together # 12 entries all together
...@@ -135,43 +138,52 @@ LINES=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep "more)" | wc -l` ...@@ -135,43 +138,52 @@ LINES=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep "more)" | wc -l`
[ $LINES = 4 ] || exit $LINENO [ $LINES = 4 ] || exit $LINENO
# ========================================================== # ==========================================================
# Second part: exit code 2, 4, 8 # Second part: exit code 2, 4, 8.
# 16 and 32 already covered in the first part # 16 and 32 already covered in the first part
# ========================================================== # ==========================================================
$KT -genkeypair -alias expired -dname CN=expired -startdate -10m
$KT -genkeypair -alias notyetvalid -dname CN=notyetvalid -startdate +1m
$KT -genkeypair -alias badku -dname CN=badku -ext KU=cRLSign -validity 365
$KT -genkeypair -alias badeku -dname CN=badeku -ext EKU=sa -validity 365
$KT -genkeypair -alias goodku -dname CN=goodku -ext KU=dig -validity 365
$KT -genkeypair -alias goodeku -dname CN=goodeku -ext EKU=codesign -validity 365
# badchain signed by ca, but ca is removed later
$KT -genkeypair -alias badchain -dname CN=badchain -validity 365
$KT -genkeypair -alias ca -dname CN=ca -ext bc -validity 365 $KT -genkeypair -alias ca -dname CN=ca -ext bc -validity 365
$KT -certreq -alias badchain | $KT -gencert -alias ca -validity 365 | \ $KT -genkeypair -alias expired -dname CN=expired
$KT -importcert -alias badchain $KT -certreq -alias expired | $KT -gencert -alias ca -startdate -10m | $KT -import -alias expired
$KT -delete -alias ca $KT -genkeypair -alias notyetvalid -dname CN=notyetvalid
$KT -certreq -alias notyetvalid | $KT -gencert -alias ca -startdate +1m | $KT -import -alias notyetvalid
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expired $KT -genkeypair -alias badku -dname CN=badku
$KT -certreq -alias badku | $KT -gencert -alias ca -ext KU=cRLSign -validity 365 | $KT -import -alias badku
$KT -genkeypair -alias badeku -dname CN=badeku
$KT -certreq -alias badeku | $KT -gencert -alias ca -ext EKU=sa -validity 365 | $KT -import -alias badeku
$KT -genkeypair -alias goodku -dname CN=goodku
$KT -certreq -alias goodku | $KT -gencert -alias ca -ext KU=dig -validity 365 | $KT -import -alias goodku
$KT -genkeypair -alias goodeku -dname CN=goodeku
$KT -certreq -alias goodeku | $KT -gencert -alias ca -ext EKU=codesign -validity 365 | $KT -import -alias goodeku
$JARSIGNER -strict -keystore $KS -storepass changeit a.jar expired
[ $? = 4 ] || exit $LINENO [ $? = 4 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar notyetvalid $JARSIGNER -strict -keystore $KS -storepass changeit a.jar notyetvalid
[ $? = 4 ] || exit $LINENO [ $? = 4 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badku $JARSIGNER -strict -keystore $KS -storepass changeit a.jar badku
[ $? = 8 ] || exit $LINENO [ $? = 8 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badeku $JARSIGNER -strict -keystore $KS -storepass changeit a.jar badeku
[ $? = 8 ] || exit $LINENO [ $? = 8 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodku $JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodku
[ $? = 0 ] || exit $LINENO [ $? = 0 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodeku $JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodeku
[ $? = 0 ] || exit $LINENO [ $? = 0 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badchain # badchain signed by ca1, but ca1 is removed later
$KT -genkeypair -alias badchain -dname CN=badchain -validity 365
$KT -genkeypair -alias ca1 -dname CN=ca1 -ext bc -validity 365
$KT -certreq -alias badchain | $KT -gencert -alias ca1 -validity 365 | \
$KT -importcert -alias badchain
# save ca1.cert for easy replay
$KT -exportcert -file ca1.cert -alias ca1
$KT -delete -alias ca1
$JARSIGNER -strict -keystore $KS -storepass changeit a.jar badchain
[ $? = 4 ] || exit $LINENO [ $? = 4 ] || exit $LINENO
$JARSIGNER -verify a.jar $JARSIGNER -verify a.jar
...@@ -181,23 +193,55 @@ $JARSIGNER -verify a.jar ...@@ -181,23 +193,55 @@ $JARSIGNER -verify a.jar
# Third part: -certchain test # Third part: -certchain test
# ========================================================== # ==========================================================
# altchain signed by ca2, but ca2 is removed later # altchain signed by ca2
$KT -genkeypair -alias altchain -dname CN=altchain -validity 365 $KT -genkeypair -alias altchain -dname CN=altchain -validity 365
$KT -genkeypair -alias ca2 -dname CN=ca2 -ext bc -validity 365 $KT -genkeypair -alias ca2 -dname CN=ca2 -ext bc -validity 365
$KT -certreq -alias altchain | $KT -gencert -alias ca2 -validity 365 -rfc > certchain $KT -certreq -alias altchain | $KT -gencert -alias ca2 -validity 365 -rfc > certchain
$KT -exportcert -alias ca2 -rfc >> certchain $KT -exportcert -alias ca2 -rfc >> certchain
$KT -delete -alias ca2
# Now altchain is still self-signed # Self-signed cert does not work
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar altchain $JARSIGNER -strict -keystore $KS -storepass changeit a.jar altchain
[ $? = 4 ] || exit $LINENO
# -certchain works
$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
[ $? = 0 ] || exit $LINENO [ $? = 0 ] || exit $LINENO
# If -certchain is used, then it's bad # if ca2 is removed, -certchain still work because altchain is a self-signed entry and
$JARSIGNER -strict -keystore js.jks -storepass changeit -certchain certchain a.jar altchain # it is trusted by jarsigner
# save ca2.cert for easy replay
$KT -exportcert -file ca2.cert -alias ca2
$KT -delete -alias ca2
$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
[ $? = 0 ] || exit $LINENO
# if cert is imported, -certchain won't work because this certificate entry is not trusted
$KT -importcert -file certchain -alias altchain -noprompt
$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
[ $? = 4 ] || exit $LINENO [ $? = 4 ] || exit $LINENO
$JARSIGNER -verify a.jar $JARSIGNER -verify a.jar
[ $? = 0 ] || exit $LINENO [ $? = 0 ] || exit $LINENO
# ==========================================================
# 8172529
# ==========================================================
$KT -genkeypair -alias ee -dname CN=ee
$KT -genkeypair -alias caone -dname CN=caone
$KT -genkeypair -alias catwo -dname CN=catwo
$KT -certreq -alias ee | $KT -gencert -alias catwo -rfc > ee.cert
$KT -certreq -alias catwo | $KT -gencert -alias caone -sigalg MD5withRSA -rfc > catwo.cert
# This certchain contains a cross-signed weak catwo.cert
cat ee.cert catwo.cert | $KT -importcert -alias ee
$JAR cvf a.jar A1.class
$JARSIGNER -strict -keystore $KS -storepass changeit a.jar ee
[ $? = 0 ] || exit $LINENO
$JARSIGNER -strict -keystore $KS -storepass changeit -verify a.jar
[ $? = 0 ] || exit $LINENO
echo OK echo OK
exit 0 exit 0
...@@ -53,11 +53,20 @@ rm $KS $JFILE ...@@ -53,11 +53,20 @@ rm $KS $JFILE
echo A > A echo A > A
$JAR cvf $JFILE A $JAR cvf $JFILE A
$KT -alias a -dname CN=a -keyalg ec -genkey -validity 300 || exit 11 $KT -alias ca -dname CN=ca -keyalg ec -genkey -validity 300 || exit 11
$KT -alias b -dname CN=b -keyalg ec -genkey -validity 300 || exit 12
$KT -alias a -dname CN=a -keyalg ec -genkey || exit 11
$KT -alias a -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias a || exit 111
$KT -alias b -dname CN=b -keyalg ec -genkey || exit 12
$KT -alias b -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias b || exit 121
# Ensure that key length is sufficient for the intended hash (SHA512withECDSA) # Ensure that key length is sufficient for the intended hash (SHA512withECDSA)
$KT -alias c -dname CN=c -keyalg ec -genkey -validity 300 -keysize 521 || exit 13 $KT -alias c -dname CN=c -keyalg ec -genkey -keysize 521 || exit 13
$KT -alias c -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias c || exit 131
$KT -alias x -dname CN=x -keyalg ec -genkey -validity 300 || exit 14 $KT -alias x -dname CN=x -keyalg ec -genkey -validity 300 || exit 14
$KT -alias x -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias x || exit 141
$JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 21 $JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 21
$JARSIGNER -keystore $KS -storepass changeit $JFILE b -debug -strict -sigalg SHA1withECDSA || exit 22 $JARSIGNER -keystore $KS -storepass changeit $JFILE b -debug -strict -sigalg SHA1withECDSA || exit 22
......
...@@ -57,12 +57,14 @@ rm $KS $JFILE 2> /dev/null ...@@ -57,12 +57,14 @@ rm $KS $JFILE 2> /dev/null
echo "Key: Value" > manifest echo "Key: Value" > manifest
$JAR cvfm $JFILE manifest $JAR cvfm $JFILE manifest
$KT -alias a -dname CN=a -genkey -validity 300 || exit 1 $KT -alias ca -dname CN=ca -genkey -validity 300 || exit 1
$JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 2 $KT -alias a -dname CN=a -genkey -validity 300 || exit 2
$KT -alias a -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias a || exit 3
$JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 4
$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE a -debug -strict \ $JARSIGNER -keystore $KS -storepass changeit -verify $JFILE a -debug -strict \
> onlymanifest.out || exit 3 > onlymanifest.out || exit 5
grep unsigned onlymanifest.out && exit 4 grep unsigned onlymanifest.out && exit 6
exit 0 exit 0
#
# Copyright (c) 2013, 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 8024302
# @bug 8026037
# @summary Clarify jar verifications
#
if [ "${TESTJAVA}" = "" ] ; then
JAVAC_CMD=`which javac`
TESTJAVA=`dirname $JAVAC_CMD`/..
fi
# set platform-dependent variables
OS=`uname -s`
case "$OS" in
Windows_* )
FS="\\"
;;
* )
FS="/"
;;
esac
KS=warnings.jks
JFILE=warnings.jar
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \
-keystore $KS"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner -keystore $KS -storepass changeit"
rm $KS 2> /dev/null
LANG=C
export LANG
echo 12345 > file
ERR=""
# Normal signer expiring on 2100-01-01
$KT -alias s1 -dname CN=s1 -genkey -startdate 2000/01/01 -validity 36525 || ERR="$ERR keytool s1,"
# Cert expiring soon, informational warning
$KT -alias s2 -dname CN=s2 -genkey -validity 100 || ERR="$ERR keytool s2,"
# Cert expired, severe warning
$KT -alias s3 -dname CN=s3 -genkey -startdate -200d -validity 100 || ERR="$ERR keytool s3,"
# noTimestamp is informatiional warning and includes a date
$JAR cvf $JFILE file
$JARSIGNER $JFILE s1 > output1 || ERR="$ERR jarsigner s1,"
$JARSIGNER -strict $JFILE s1 >> output1 || ERR="$ERR jarsigner s1 strict,"
$JARSIGNER -verify $JFILE s1 >> output1 || ERR="$ERR jarsigner s1,"
$JARSIGNER -verify -strict $JFILE s1 >> output1 || ERR="$ERR jarsigner s1 strict,"
cat output1 | grep Warning || ERR="$ERR s1 warning,"
cat output1 | grep Error && ERR="$ERR s1 error,"
cat output1 | grep timestamp | grep 2100-01-01 || ERR="$ERR s1 timestamp,"
cat output1 | grep "with signer errors" && ERR="$ERR s1 err,"
# hasExpiringCert is informatiional warning
$JAR cvf $JFILE file
$JARSIGNER $JFILE s2 > output2 || ERR="$ERR jarsigner s2,"
$JARSIGNER -strict $JFILE s2 >> output2 || ERR="$ERR jarsigner s2 strict,"
$JARSIGNER -verify $JFILE s2 >> output2 || ERR="$ERR jarsigner s2,"
$JARSIGNER -verify -strict $JFILE s2 >> output2 || ERR="$ERR jarsigner s2 strict,"
cat output2 | grep Warning || ERR="$ERR s2 warning,"
cat output2 | grep Error && ERR="$ERR s2 error,"
cat output2 | grep timestamp || ERR="$ERR s2 timestamp,"
cat output2 | grep "will expire" || ERR="$ERR s2 expiring,"
cat output2 | grep "with signer errors" && ERR="$ERR s2 err,"
# hasExpiredCert is severe warning
$JAR cvf $JFILE file
$JARSIGNER $JFILE s3 > output3 || ERR="$ERR jarsigner s3,"
$JARSIGNER -strict $JFILE s3 > output3s && ERR="$ERR jarsigner s3 strict,"
$JARSIGNER -verify $JFILE s3 >> output3 || ERR="$ERR jarsigner s3,"
$JARSIGNER -verify -strict $JFILE s3 >> output3s && ERR="$ERR jarsigner s3 strict,"
# warning without -strict
cat output3 | grep Warning || ERR="$ERR s3 warning,"
cat output3 | grep Error && ERR="$ERR s3 error,"
cat output3 | grep "with signer errors" && ERR="$ERR s3 err,"
# error with -strict
cat output3s | grep Warning || ERR="$ERR s3s warning,"
cat output3s | grep Error || ERR="$ERR s3s error,"
cat output3s | grep "with signer errors" || ERR="$ERR s3 err,"
if [ "$ERR" = "" ]; then
exit 0
else
echo "ERR is $ERR"
exit 1
fi
/* /*
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -63,7 +63,7 @@ public abstract class Test { ...@@ -63,7 +63,7 @@ public abstract class Test {
static final String CHAIN_NOT_VALIDATED_VERIFYING_WARNING static final String CHAIN_NOT_VALIDATED_VERIFYING_WARNING
= "This jar contains entries " = "This jar contains entries "
+ "whose certificate chain is not validated."; + "whose certificate chain is invalid.";
static final String ALIAS_NOT_IN_STORE_VERIFYING_WARNING static final String ALIAS_NOT_IN_STORE_VERIFYING_WARNING
= "This jar contains signed entries " = "This jar contains signed entries "
...@@ -95,7 +95,7 @@ public abstract class Test { ...@@ -95,7 +95,7 @@ public abstract class Test {
+ "doesn't allow code signing."; + "doesn't allow code signing.";
static final String CHAIN_NOT_VALIDATED_SIGNING_WARNING static final String CHAIN_NOT_VALIDATED_SIGNING_WARNING
= "The signer's certificate chain is not validated."; = "The signer's certificate chain is invalid.";
static final String HAS_EXPIRING_CERT_SIGNING_WARNING static final String HAS_EXPIRING_CERT_SIGNING_WARNING
= "The signer certificate will expire within six months."; = "The signer certificate will expire within six months.";
......
#
# Copyright (c) 2014, 2017, 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 8044755
# @summary Add a test for algorithm constraints check in jarsigner
#
if [ "${TESTJAVA}" = "" ] ; then
JAVAC_CMD=`which javac`
TESTJAVA=`dirname $JAVAC_CMD`/..
fi
# The sigalg used is MD2withRSA, which is obsolete.
KT="$TESTJAVA/bin/keytool ${TESTTOOLVMOPTS} -keystore ks
-storepass changeit -keypass changeit
-keyalg rsa -sigalg MD2withRSA -debug"
JS="$TESTJAVA/bin/jarsigner ${TESTTOOLVMOPTS} -keystore ks
-storepass changeit -strict -debug"
JAR="$TESTJAVA/bin/jar ${TESTTOOLVMOPTS}"
rm ks 2> /dev/null
$KT -genkeypair -alias ca -dname CN=CA -ext bc
$KT -genkeypair -alias signer -dname CN=Signer
$KT -certreq -alias signer | \
$KT -gencert -alias ca -ext ku=dS -rfc | \
$KT -importcert -alias signer
$JAR cvf a.jar ks
# We always trust a TrustedCertificateEntry
$JS a.jar ca | grep "chain is invalid" && exit 1
# An end-entity cert must follow algorithm constraints
$JS a.jar signer | grep "chain is invalid" || exit 2
exit 0
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册