Merge
This commit is contained in:
commit
a6132067a5
@ -72,10 +72,13 @@ import sun.net.util.IPAddressUtil;
|
||||
*
|
||||
* <h3> Address types </h3>
|
||||
*
|
||||
* <blockquote><table class="borderless">
|
||||
* <table class="striped" style="margin-left:2em">
|
||||
* <caption style="display:none">Description of unicast and multicast address types</caption>
|
||||
* <thead>
|
||||
* <tr><th scope="col">Address Type</th><th scope="col">Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><th style="vertical-align:top"><i>unicast</i></th>
|
||||
* <tr><th scope="row" style="vertical-align:top">unicast</th>
|
||||
* <td>An identifier for a single interface. A packet sent to
|
||||
* a unicast address is delivered to the interface identified by
|
||||
* that address.
|
||||
@ -94,12 +97,12 @@ import sun.net.util.IPAddressUtil;
|
||||
* IP address loops around and becomes IP input on the local
|
||||
* host. This address is often used when testing a
|
||||
* client.</td></tr>
|
||||
* <tr><th style="vertical-align:top"><i>multicast</i></th>
|
||||
* <tr><th scope="row" style="vertical-align:top">multicast</th>
|
||||
* <td>An identifier for a set of interfaces (typically belonging
|
||||
* to different nodes). A packet sent to a multicast address is
|
||||
* delivered to all interfaces identified by that address.</td></tr>
|
||||
* </tbody>
|
||||
* </table></blockquote>
|
||||
* </table>
|
||||
*
|
||||
* <h4> IP address scope </h4>
|
||||
*
|
||||
@ -163,8 +166,7 @@ import sun.net.util.IPAddressUtil;
|
||||
* <p> Two Java security properties control the TTL values used for
|
||||
* positive and negative host name resolution caching:
|
||||
*
|
||||
* <blockquote>
|
||||
* <dl>
|
||||
* <dl style="margin-left:2em">
|
||||
* <dt><b>networkaddress.cache.ttl</b></dt>
|
||||
* <dd>Indicates the caching policy for successful name lookups from
|
||||
* the name service. The value is specified as an integer to indicate
|
||||
@ -183,7 +185,6 @@ import sun.net.util.IPAddressUtil;
|
||||
* A value of -1 indicates "cache forever".
|
||||
* </dd>
|
||||
* </dl>
|
||||
* </blockquote>
|
||||
*
|
||||
* @author Chris Warth
|
||||
* @see java.net.InetAddress#getByAddress(byte[])
|
||||
|
@ -132,23 +132,23 @@ import java.lang.NullPointerException; // for javadoc
|
||||
*
|
||||
* <p> All told, then, a URI instance has the following nine components:
|
||||
*
|
||||
* <blockquote><table class="borderless">
|
||||
* <table class="striped" style="margin-left:2em">
|
||||
* <caption style="display:none">Describes the components of a URI:scheme,scheme-specific-part,authority,user-info,host,port,path,query,fragment</caption>
|
||||
* <thead>
|
||||
* <tr><th><i>Component</i></th><th><i>Type</i></th></tr>
|
||||
* <tr><th scope="col">Component</th><th scope="col">Type</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td>scheme</td><td>{@code String}</td></tr>
|
||||
* <tr><td>scheme-specific-part </td><td>{@code String}</td></tr>
|
||||
* <tr><td>authority</td><td>{@code String}</td></tr>
|
||||
* <tr><td>user-info</td><td>{@code String}</td></tr>
|
||||
* <tr><td>host</td><td>{@code String}</td></tr>
|
||||
* <tr><td>port</td><td>{@code int}</td></tr>
|
||||
* <tr><td>path</td><td>{@code String}</td></tr>
|
||||
* <tr><td>query</td><td>{@code String}</td></tr>
|
||||
* <tr><td>fragment</td><td>{@code String}</td></tr>
|
||||
* <tbody style="text-align:left">
|
||||
* <tr><th scope="row">scheme</th><td>{@code String}</td></tr>
|
||||
* <tr><th scope="row">scheme-specific-part</th><td>{@code String}</td></tr>
|
||||
* <tr><th scope="row">authority</th><td>{@code String}</td></tr>
|
||||
* <tr><th scope="row">user-info</th><td>{@code String}</td></tr>
|
||||
* <tr><th scope="row">host</th><td>{@code String}</td></tr>
|
||||
* <tr><th scope="row">port</th><td>{@code int}</td></tr>
|
||||
* <tr><th scope="row">path</th><td>{@code String}</td></tr>
|
||||
* <tr><th scope="row">query</th><td>{@code String}</td></tr>
|
||||
* <tr><th scope="row">fragment</th><td>{@code String}</td></tr>
|
||||
* </tbody>
|
||||
* </table></blockquote>
|
||||
* </table>
|
||||
*
|
||||
* In a given instance any particular component is either <i>undefined</i> or
|
||||
* <i>defined</i> with a distinct value. Undefined string components are
|
||||
@ -253,32 +253,35 @@ import java.lang.NullPointerException; // for javadoc
|
||||
* which are taken from that specification, are used below to describe these
|
||||
* constraints:
|
||||
*
|
||||
* <blockquote><table class="borderless">
|
||||
* <table class="striped" style="margin-left:2em">
|
||||
* <caption style="display:none">Describes categories alpha,digit,alphanum,unreserved,punct,reserved,escaped,and other</caption>
|
||||
* <tbody>
|
||||
* <tr><th style="vertical-align:top"><i>alpha</i></th>
|
||||
* <thead>
|
||||
* <tr><th scope="col">Category</th><th scope="col">Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody style="text-align:left">
|
||||
* <tr><th scope="row" style="vertical-align:top">alpha</th>
|
||||
* <td>The US-ASCII alphabetic characters,
|
||||
* {@code 'A'} through {@code 'Z'}
|
||||
* and {@code 'a'} through {@code 'z'}</td></tr>
|
||||
* <tr><th style="vertical-align:top"><i>digit</i></th>
|
||||
* <tr><th scope="row" style="vertical-align:top">digit</th>
|
||||
* <td>The US-ASCII decimal digit characters,
|
||||
* {@code '0'} through {@code '9'}</td></tr>
|
||||
* <tr><th style="vertical-align:top"><i>alphanum</i></th>
|
||||
* <tr><th scope="row" style="vertical-align:top">alphanum</th>
|
||||
* <td>All <i>alpha</i> and <i>digit</i> characters</td></tr>
|
||||
* <tr><th style="vertical-align:top"><i>unreserved</i> </th>
|
||||
* <tr><th scope="row" style="vertical-align:top">unreserved</th>
|
||||
* <td>All <i>alphanum</i> characters together with those in the string
|
||||
* {@code "_-!.~'()*"}</td></tr>
|
||||
* <tr><th style="vertical-align:top"><i>punct</i></th>
|
||||
* <tr><th scope="row" style="vertical-align:top">punct</th>
|
||||
* <td>The characters in the string {@code ",;:$&+="}</td></tr>
|
||||
* <tr><th style="vertical-align:top"><i>reserved</i></th>
|
||||
* <tr><th scope="row" style="vertical-align:top">reserved</th>
|
||||
* <td>All <i>punct</i> characters together with those in the string
|
||||
* {@code "?/[]@"}</td></tr>
|
||||
* <tr><th style="vertical-align:top"><i>escaped</i></th>
|
||||
* <tr><th scope="row" style="vertical-align:top">escaped</th>
|
||||
* <td>Escaped octets, that is, triplets consisting of the percent
|
||||
* character ({@code '%'}) followed by two hexadecimal digits
|
||||
* ({@code '0'}-{@code '9'}, {@code 'A'}-{@code 'F'}, and
|
||||
* {@code 'a'}-{@code 'f'})</td></tr>
|
||||
* <tr><th style="vertical-align:top"><i>other</i></th>
|
||||
* <tr><th scope="row" style="vertical-align:top">other</th>
|
||||
* <td>The Unicode characters that are not in the US-ASCII character set,
|
||||
* are not control characters (according to the {@link
|
||||
* java.lang.Character#isISOControl(char) Character.isISOControl}
|
||||
@ -287,7 +290,7 @@ import java.lang.NullPointerException; // for javadoc
|
||||
* method) <i>(<b>Deviation from RFC 2396</b>, which is
|
||||
* limited to US-ASCII)</i></td></tr>
|
||||
* </tbody>
|
||||
* </table></blockquote>
|
||||
* </table>
|
||||
*
|
||||
* <p><a id="legal-chars"></a> The set of all legal URI characters consists of
|
||||
* the <i>unreserved</i>, <i>reserved</i>, <i>escaped</i>, and <i>other</i>
|
||||
|
@ -51,31 +51,16 @@ import sun.security.action.GetPropertyAction;
|
||||
* The abstract class {@code URLConnection} is the superclass
|
||||
* of all classes that represent a communications link between the
|
||||
* application and a URL. Instances of this class can be used both to
|
||||
* read from and to write to the resource referenced by the URL. In
|
||||
* general, creating a connection to a URL is a multistep process:
|
||||
*
|
||||
* <div style="text-align:center"><table class="plain" style="margin:0 auto">
|
||||
* <caption style="display:none">Describes the process of creating a connection to a URL: openConnection() and connect() over time.</caption>
|
||||
* <thead>
|
||||
* <tr><th>{@code openConnection()}</th>
|
||||
* <th>{@code connect()}</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td>Manipulate parameters that affect the connection to the remote
|
||||
* resource.</td>
|
||||
* <td>Interact with the resource; query header fields and
|
||||
* contents.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* ---------------------------->
|
||||
* <br>time</div>
|
||||
* read from and to write to the resource referenced by the URL.
|
||||
*
|
||||
* <p>
|
||||
* In general, creating a connection to a URL is a multistep process:
|
||||
* <ol>
|
||||
* <li>The connection object is created by invoking the
|
||||
* {@code openConnection} method on a URL.
|
||||
* {@link URL#openConnection() openConnection} method on a URL.
|
||||
* <li>The setup parameters and general request properties are manipulated.
|
||||
* <li>The actual connection to the remote object is made, using the
|
||||
* {@code connect} method.
|
||||
* {@link #connect() connect} method.
|
||||
* <li>The remote object becomes available. The header fields and the contents
|
||||
* of the remote object can be accessed.
|
||||
* </ol>
|
||||
|
@ -72,22 +72,22 @@ import java.security.Permission;
|
||||
* separated by '/' characters. <i>path</i> may also be empty. The path is specified
|
||||
* in a similar way to the path in {@link java.io.FilePermission}. There are
|
||||
* three different ways as the following examples show:
|
||||
* <table class="plain">
|
||||
* <table class="striped">
|
||||
* <caption>URL Examples</caption>
|
||||
* <thead>
|
||||
* <tr><th>Example url</th><th>Description</th></tr>
|
||||
* <tr><th scope="col">Example url</th><th scope="col">Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td style="white-space:nowrap;">http://www.oracle.com/a/b/c.html</td>
|
||||
* <tbody style="text-align:left">
|
||||
* <tr><th scope="row" style="white-space:nowrap;">http://www.oracle.com/a/b/c.html</th>
|
||||
* <td>A url which identifies a specific (single) resource</td>
|
||||
* </tr>
|
||||
* <tr><td>http://www.oracle.com/a/b/*</td>
|
||||
* <tr><th scope="row">http://www.oracle.com/a/b/*</th>
|
||||
* <td>The '*' character refers to all resources in the same "directory" - in
|
||||
* other words all resources with the same number of path components, and
|
||||
* which only differ in the final path component, represented by the '*'.
|
||||
* </td>
|
||||
* </tr>
|
||||
* <tr><td>http://www.oracle.com/a/b/-</td>
|
||||
* <tr><th scope="row">http://www.oracle.com/a/b/-</th>
|
||||
* <td>The '-' character refers to all resources recursively below the
|
||||
* preceding path (eg. http://www.oracle.com/a/b/c/d/e.html matches this
|
||||
* example).
|
||||
@ -114,11 +114,12 @@ import java.security.Permission;
|
||||
* methods and permitted request headers of the permission (respectively). The two lists
|
||||
* are separated by a colon ':' character and elements of each list are comma separated.
|
||||
* Some examples are:
|
||||
* <pre>
|
||||
* "POST,GET,DELETE"
|
||||
* "GET:X-Foo-Request,X-Bar-Request"
|
||||
* "POST,GET:Header1,Header2"
|
||||
* </pre>
|
||||
* <ul>
|
||||
* <li>"POST,GET,DELETE"
|
||||
* <li>"GET:X-Foo-Request,X-Bar-Request"
|
||||
* <li>"POST,GET:Header1,Header2"
|
||||
* </ul>
|
||||
* <p>
|
||||
* The first example specifies the methods: POST, GET and DELETE, but no request headers.
|
||||
* The second example specifies one request method and two headers. The third
|
||||
* example specifies two request methods, and two headers.
|
||||
@ -253,16 +254,16 @@ public final class URLPermission extends Permission {
|
||||
* <table class="plain">
|
||||
* <caption>Examples of Path Matching</caption>
|
||||
* <thead>
|
||||
* <tr><th>this's path</th><th>p's path</th><th>match</th></tr>
|
||||
* <tr><th scope="col">this's path</th><th scope="col">p's path</th><th>match</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td>/a/b</td><td>/a/b</td><td>yes</td></tr>
|
||||
* <tr><td>/a/b/*</td><td>/a/b/c</td><td>yes</td></tr>
|
||||
* <tr><td>/a/b/*</td><td>/a/b/c/d</td><td>no</td></tr>
|
||||
* <tr><td>/a/b/-</td><td>/a/b/c/d</td><td>yes</td></tr>
|
||||
* <tr><td>/a/b/-</td><td>/a/b/c/d/e</td><td>yes</td></tr>
|
||||
* <tr><td>/a/b/-</td><td>/a/b/c/*</td><td>yes</td></tr>
|
||||
* <tr><td>/a/b/*</td><td>/a/b/c/-</td><td>no</td></tr>
|
||||
* <tbody style="text-align:left">
|
||||
* <tr><th scope="row">/a/b</th><th scope="row">/a/b</th><td>yes</td></tr>
|
||||
* <tr><th scope="row" rowspan="3">/a/b/*</th><th scope="row">/a/b/c</th><td>yes</td></tr>
|
||||
* <tr> <th scope="row">/a/b/c/d</th><td>no</td></tr>
|
||||
* <tr> <th scope="row">/a/b/c/-</th><td>no</td></tr>
|
||||
* <tr><th scope="row" rowspan="3">/a/b/-</th><th scope="row">/a/b/c/d</th><td>yes</td></tr>
|
||||
* <tr> <th scope="row">/a/b/c/d/e</th><td>yes</td></tr>
|
||||
* <tr> <th scope="row">/a/b/c/*</th><td>yes</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
*/
|
||||
|
@ -23,7 +23,7 @@
|
||||
or visit www.oracle.com if you need additional information or have any
|
||||
questions.
|
||||
-->
|
||||
<HTML>
|
||||
<HTML lang="EN">
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
||||
<TITLE>Networking Properties</TITLE>
|
||||
@ -35,7 +35,7 @@ alter the mechanisms and behavior of the various classes of the
|
||||
java.net package. Some are checked only once at startup of the VM,
|
||||
and therefore are best set using the -D option of the java command,
|
||||
while others have a more dynamic nature and can also be changed using
|
||||
the <a href="../../lang/System.html#setProperty(java.lang.String,%20java.lang.String)">System.setProperty()</a> API.
|
||||
the <a href="../../lang/System.html#setProperty-java.lang.String-java.lang.String-">System.setProperty()</a> API.
|
||||
The purpose of this document is to list
|
||||
and detail all of these properties.</P>
|
||||
<P>If there is no special note, a property value is checked every time it is used.</P>
|
||||
|
@ -263,18 +263,18 @@ public class DrbgParameters {
|
||||
* Capability effective = ((DrbgParametes.Initiate) s.getParameters())
|
||||
* .getCapability();</pre>
|
||||
* </blockquote>
|
||||
* <table class="plain">
|
||||
* <table class="striped">
|
||||
* <caption style="display:none">requested and effective capabilities</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th>Requested Value</th>
|
||||
* <th>Possible Effective Values</th>
|
||||
* <th scope="col">Requested Value</th>
|
||||
* <th scope="col">Possible Effective Values</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td>NONE</td><td>NONE, RESEED_ONLY, PR_AND_RESEED</td></tr>
|
||||
* <tr><td>RESEED_ONLY</td><td>RESEED_ONLY, PR_AND_RESEED</td></tr>
|
||||
* <tr><td>PR_AND_RESEED</td><td>PR_AND_RESEED</td></tr>
|
||||
* <tbody style="text-align:left">
|
||||
* <tr><th scope="row">NONE</th><td>NONE, RESEED_ONLY, PR_AND_RESEED</td></tr>
|
||||
* <tr><th scope="row">RESEED_ONLY</th><td>RESEED_ONLY, PR_AND_RESEED</td></tr>
|
||||
* <tr><th scope="row">PR_AND_RESEED</th><td>PR_AND_RESEED</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* <p>
|
||||
|
@ -61,19 +61,19 @@ import java.util.function.Function;
|
||||
* security framework. Services of this type cannot be added, removed,
|
||||
* or modified by applications.
|
||||
* The following attributes are automatically placed in each Provider object:
|
||||
* <table class="plain">
|
||||
* <table class="striped">
|
||||
* <caption><b>Attributes Automatically Placed in a Provider Object</b></caption>
|
||||
* <thead>
|
||||
* <tr><th>Name</th><th>Value</th>
|
||||
* <tr><th scope="col">Name</th><th scope="col">Value</th>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td>{@code Provider.id name}</td>
|
||||
* <tbody style="text-align:left">
|
||||
* <tr><th scope="row">{@code Provider.id name}</th>
|
||||
* <td>{@code String.valueOf(provider.getName())}</td>
|
||||
* <tr><td>{@code Provider.id version}</td>
|
||||
* <tr><th scope="row">{@code Provider.id version}</th>
|
||||
* <td>{@code String.valueOf(provider.getVersionStr())}</td>
|
||||
* <tr><td>{@code Provider.id info}</td>
|
||||
* <tr><th scope="row">{@code Provider.id info}</th>
|
||||
* <td>{@code String.valueOf(provider.getInfo())}</td>
|
||||
* <tr><td>{@code Provider.id className}</td>
|
||||
* <tr><th scope="row">{@code Provider.id className}</th>
|
||||
* <td>{@code provider.getClass().getName()}</td>
|
||||
* </tbody>
|
||||
* </table>
|
||||
|
@ -153,33 +153,33 @@ public interface X509Extension {
|
||||
* by periods.
|
||||
*
|
||||
* <p>For example:<br>
|
||||
* <table class="plain">
|
||||
* <table class="striped">
|
||||
* <caption style="display:none">Examples of OIDs and extension names</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th>OID <em>(Object Identifier)</em></th>
|
||||
* <th>Extension Name</th></tr>
|
||||
* <th scope="col">OID <em>(Object Identifier)</em></th>
|
||||
* <th scope="col">Extension Name</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td>2.5.29.14</td>
|
||||
* <tbody style="text-align:left">
|
||||
* <tr><th scope="row">2.5.29.14</th>
|
||||
* <td>SubjectKeyIdentifier</td></tr>
|
||||
* <tr><td>2.5.29.15</td>
|
||||
* <tr><th scope="row">2.5.29.15</th>
|
||||
* <td>KeyUsage</td></tr>
|
||||
* <tr><td>2.5.29.16</td>
|
||||
* <tr><th scope="row">2.5.29.16</th>
|
||||
* <td>PrivateKeyUsage</td></tr>
|
||||
* <tr><td>2.5.29.17</td>
|
||||
* <tr><th scope="row">2.5.29.17</th>
|
||||
* <td>SubjectAlternativeName</td></tr>
|
||||
* <tr><td>2.5.29.18</td>
|
||||
* <tr><th scope="row">2.5.29.18</th>
|
||||
* <td>IssuerAlternativeName</td></tr>
|
||||
* <tr><td>2.5.29.19</td>
|
||||
* <tr><th scope="row">2.5.29.19</th>
|
||||
* <td>BasicConstraints</td></tr>
|
||||
* <tr><td>2.5.29.30</td>
|
||||
* <tr><th scope="row">2.5.29.30</th>
|
||||
* <td>NameConstraints</td></tr>
|
||||
* <tr><td>2.5.29.33</td>
|
||||
* <tr><th scope="row">2.5.29.33</th>
|
||||
* <td>PolicyMappings</td></tr>
|
||||
* <tr><td>2.5.29.35</td>
|
||||
* <tr><th scope="row">2.5.29.35</th>
|
||||
* <td>AuthorityKeyIdentifier</td></tr>
|
||||
* <tr><td>2.5.29.36</td>
|
||||
* <tr><th scope="row">2.5.29.36</th>
|
||||
* <td>PolicyConstraints</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
|
@ -81,13 +81,24 @@ class ZipUtils {
|
||||
* Converts DOS time to Java time (number of milliseconds since epoch).
|
||||
*/
|
||||
public static long dosToJavaTime(long dtime) {
|
||||
LocalDateTime ldt = LocalDateTime.of(
|
||||
(int) (((dtime >> 25) & 0x7f) + 1980),
|
||||
(int) ((dtime >> 21) & 0x0f),
|
||||
(int) ((dtime >> 16) & 0x1f),
|
||||
(int) ((dtime >> 11) & 0x1f),
|
||||
(int) ((dtime >> 5) & 0x3f),
|
||||
(int) ((dtime << 1) & 0x3e));
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
int hour = (int) ((dtime >> 11) & 0x1f);
|
||||
int minute = (int) ((dtime >> 5) & 0x3f);
|
||||
int second = (int) ((dtime << 1) & 0x3e);
|
||||
if ((dtime >> 16) == 0) {
|
||||
// Interpret the 0 DOS date as 1979-11-30 for compatibility with
|
||||
// other implementations.
|
||||
year = 1979;
|
||||
month = 11;
|
||||
day = 30;
|
||||
} else {
|
||||
year = (int) (((dtime >> 25) & 0x7f) + 1980);
|
||||
month = (int) ((dtime >> 21) & 0x0f);
|
||||
day = (int) ((dtime >> 16) & 0x1f);
|
||||
}
|
||||
LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second);
|
||||
return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond(
|
||||
ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS);
|
||||
}
|
||||
|
@ -1292,7 +1292,7 @@ public abstract class SSLEngine {
|
||||
* href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
|
||||
* Application-Layer Protocol Negotiation (ALPN), can negotiate
|
||||
* application-level values between peers.
|
||||
* <p>
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
@ -1317,7 +1317,7 @@ public abstract class SSLEngine {
|
||||
* Like {@link #getHandshakeSession()},
|
||||
* a connection may be in the middle of a handshake. The
|
||||
* application protocol may or may not yet be available.
|
||||
* <p>
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
|
@ -646,7 +646,7 @@ public class SSLParameters {
|
||||
* requested by the peer, the underlying protocol will determine what
|
||||
* action to take. (For example, ALPN will send a
|
||||
* {@code "no_application_protocol"} alert and terminate the connection.)
|
||||
* <p>
|
||||
*
|
||||
* @implSpec
|
||||
* This method will make a copy of the {@code protocols} array.
|
||||
*
|
||||
|
@ -702,7 +702,7 @@ public abstract class SSLSocket extends Socket
|
||||
* href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
|
||||
* Application-Layer Protocol Negotiation (ALPN), can negotiate
|
||||
* application-level values between peers.
|
||||
* <p>
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
@ -727,7 +727,7 @@ public abstract class SSLSocket extends Socket
|
||||
* Like {@link #getHandshakeSession()},
|
||||
* a connection may be in the middle of a handshake. The
|
||||
* application protocol may or may not yet be available.
|
||||
* <p>
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.incubator.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import jdk.incubator.http.internal.common.ExceptionallyCloseable;
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronous version of SSLConnection.
|
||||
*
|
||||
* There are two concrete implementations of this class: AsyncSSLConnection
|
||||
* and AsyncSSLTunnelConnection.
|
||||
* This abstraction is useful when downgrading from HTTP/2 to HTTP/1.1 over
|
||||
* an SSL connection. See ExchangeImpl::get in the case where an ALPNException
|
||||
* is thrown.
|
||||
*
|
||||
* Note: An AsyncSSLConnection wraps a PlainHttpConnection, while an
|
||||
* AsyncSSLTunnelConnection wraps a PlainTunnelingConnection.
|
||||
* If both these wrapped classes where made to inherit from a
|
||||
* common abstraction then it might be possible to merge
|
||||
* AsyncSSLConnection and AsyncSSLTunnelConnection back into
|
||||
* a single class - and simply use different factory methods to
|
||||
* create different wrappees, but this is left up for further cleanup.
|
||||
*
|
||||
*/
|
||||
abstract class AbstractAsyncSSLConnection extends HttpConnection
|
||||
implements AsyncConnection, ExceptionallyCloseable {
|
||||
|
||||
|
||||
AbstractAsyncSSLConnection(InetSocketAddress addr, HttpClientImpl client) {
|
||||
super(addr, client);
|
||||
}
|
||||
|
||||
abstract SSLEngine getEngine();
|
||||
abstract AsyncSSLDelegate sslDelegate();
|
||||
abstract HttpConnection plainConnection();
|
||||
abstract HttpConnection downgrade();
|
||||
|
||||
@Override
|
||||
final boolean isSecure() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Blocking read functions not used here
|
||||
@Override
|
||||
protected final ByteBuffer readImpl() throws IOException {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
// whenReceivedResponse only used in HTTP/1.1 (Http1Exchange)
|
||||
// AbstractAsyncSSLConnection is only used with HTTP/2
|
||||
@Override
|
||||
final CompletableFuture<Void> whenReceivingResponse() {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
}
|
@ -35,14 +35,12 @@ import java.util.function.Supplier;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import jdk.incubator.http.internal.common.ByteBufferReference;
|
||||
import jdk.incubator.http.internal.common.ExceptionallyCloseable;
|
||||
import jdk.incubator.http.internal.common.Utils;
|
||||
|
||||
/**
|
||||
* Asynchronous version of SSLConnection.
|
||||
*/
|
||||
class AsyncSSLConnection extends HttpConnection
|
||||
implements AsyncConnection, ExceptionallyCloseable {
|
||||
class AsyncSSLConnection extends AbstractAsyncSSLConnection {
|
||||
|
||||
final AsyncSSLDelegate sslDelegate;
|
||||
final PlainHttpConnection plainConnection;
|
||||
@ -61,15 +59,14 @@ class AsyncSSLConnection extends HttpConnection
|
||||
plainConnection.configureMode(mode);
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> configureModeAsync(Void ignore) {
|
||||
CompletableFuture<Void> cf = new CompletableFuture<>();
|
||||
try {
|
||||
configureMode(Mode.ASYNC);
|
||||
cf.complete(null);
|
||||
} catch (Throwable t) {
|
||||
cf.completeExceptionally(t);
|
||||
}
|
||||
return cf;
|
||||
@Override
|
||||
PlainHttpConnection plainConnection() {
|
||||
return plainConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
AsyncSSLDelegate sslDelegate() {
|
||||
return sslDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -91,11 +88,6 @@ class AsyncSSLConnection extends HttpConnection
|
||||
return plainConnection.connected() && sslDelegate.connected();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isSecure() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isProxied() {
|
||||
return false;
|
||||
@ -172,6 +164,7 @@ class AsyncSSLConnection extends HttpConnection
|
||||
plainConnection.channel().shutdownOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
SSLEngine getEngine() {
|
||||
return sslDelegate.getEngine();
|
||||
}
|
||||
@ -184,18 +177,6 @@ class AsyncSSLConnection extends HttpConnection
|
||||
plainConnection.setAsyncCallbacks(sslDelegate::asyncReceive, errorReceiver, sslDelegate::getNetBuffer);
|
||||
}
|
||||
|
||||
// Blocking read functions not used here
|
||||
|
||||
@Override
|
||||
protected ByteBuffer readImpl() throws IOException {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
CompletableFuture<Void> whenReceivingResponse() {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startReading() {
|
||||
plainConnection.startReading();
|
||||
@ -206,4 +187,9 @@ class AsyncSSLConnection extends HttpConnection
|
||||
public void stopAsyncReading() {
|
||||
plainConnection.stopAsyncReading();
|
||||
}
|
||||
|
||||
@Override
|
||||
SSLConnection downgrade() {
|
||||
return new SSLConnection(this);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.incubator.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import jdk.incubator.http.internal.common.ByteBufferReference;
|
||||
import jdk.incubator.http.internal.common.Utils;
|
||||
|
||||
/**
|
||||
* An SSL tunnel built on a Plain (CONNECT) TCP tunnel.
|
||||
*/
|
||||
class AsyncSSLTunnelConnection extends AbstractAsyncSSLConnection {
|
||||
|
||||
final PlainTunnelingConnection plainConnection;
|
||||
final AsyncSSLDelegate sslDelegate;
|
||||
final String serverName;
|
||||
|
||||
@Override
|
||||
public void connect() throws IOException, InterruptedException {
|
||||
plainConnection.connect();
|
||||
configureMode(Mode.ASYNC);
|
||||
startReading();
|
||||
sslDelegate.connect();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean connected() {
|
||||
return plainConnection.connected() && sslDelegate.connected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> connectAsync() {
|
||||
throw new InternalError();
|
||||
}
|
||||
|
||||
AsyncSSLTunnelConnection(InetSocketAddress addr,
|
||||
HttpClientImpl client,
|
||||
String[] alpn,
|
||||
InetSocketAddress proxy)
|
||||
{
|
||||
super(addr, client);
|
||||
this.serverName = Utils.getServerName(addr);
|
||||
this.plainConnection = new PlainTunnelingConnection(addr, proxy, client);
|
||||
this.sslDelegate = new AsyncSSLDelegate(plainConnection, client, alpn, serverName);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void configureMode(Mode mode) throws IOException {
|
||||
super.configureMode(mode);
|
||||
plainConnection.configureMode(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
SSLParameters sslParameters() {
|
||||
return sslDelegate.getSSLParameters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AsyncSSLTunnelConnection: " + super.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
PlainTunnelingConnection plainConnection() {
|
||||
return plainConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
AsyncSSLDelegate sslDelegate() {
|
||||
return sslDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
ConnectionPool.CacheKey cacheKey() {
|
||||
return ConnectionPool.cacheKey(address, plainConnection.proxyAddr);
|
||||
}
|
||||
|
||||
@Override
|
||||
long write(ByteBuffer[] buffers, int start, int number) throws IOException {
|
||||
//debugPrint("Send", buffers, start, number);
|
||||
ByteBuffer[] bufs = Utils.reduce(buffers, start, number);
|
||||
long n = Utils.remaining(bufs);
|
||||
sslDelegate.writeAsync(ByteBufferReference.toReferences(bufs));
|
||||
sslDelegate.flushAsync();
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
long write(ByteBuffer buffer) throws IOException {
|
||||
//debugPrint("Send", buffer);
|
||||
long n = buffer.remaining();
|
||||
sslDelegate.writeAsync(ByteBufferReference.toReferences(buffer));
|
||||
sslDelegate.flushAsync();
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeAsync(ByteBufferReference[] buffers) throws IOException {
|
||||
sslDelegate.writeAsync(buffers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeAsyncUnordered(ByteBufferReference[] buffers) throws IOException {
|
||||
sslDelegate.writeAsyncUnordered(buffers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushAsync() throws IOException {
|
||||
sslDelegate.flushAsync();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Utils.close(sslDelegate, plainConnection.channel());
|
||||
}
|
||||
|
||||
@Override
|
||||
void shutdownInput() throws IOException {
|
||||
plainConnection.channel().shutdownInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
void shutdownOutput() throws IOException {
|
||||
plainConnection.channel().shutdownOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
SocketChannel channel() {
|
||||
return plainConnection.channel();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isProxied() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsyncCallbacks(Consumer<ByteBufferReference> asyncReceiver,
|
||||
Consumer<Throwable> errorReceiver,
|
||||
Supplier<ByteBufferReference> readBufferSupplier) {
|
||||
sslDelegate.setAsyncCallbacks(asyncReceiver, errorReceiver, readBufferSupplier);
|
||||
plainConnection.setAsyncCallbacks(sslDelegate::asyncReceive, errorReceiver, sslDelegate::getNetBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startReading() {
|
||||
plainConnection.startReading();
|
||||
sslDelegate.startReading();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopAsyncReading() {
|
||||
plainConnection.stopAsyncReading();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableCallback() {
|
||||
sslDelegate.enableCallback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeExceptionally(Throwable cause) throws IOException {
|
||||
Utils.close(cause, sslDelegate, plainConnection.channel());
|
||||
}
|
||||
|
||||
@Override
|
||||
SSLEngine getEngine() {
|
||||
return sslDelegate.getEngine();
|
||||
}
|
||||
|
||||
@Override
|
||||
SSLTunnelConnection downgrade() {
|
||||
return new SSLTunnelConnection(this);
|
||||
}
|
||||
}
|
@ -82,9 +82,9 @@ abstract class ExchangeImpl<T> {
|
||||
c = c2.getConnectionFor(request);
|
||||
} catch (Http2Connection.ALPNException e) {
|
||||
// failed to negotiate "h2"
|
||||
AsyncSSLConnection as = e.getConnection();
|
||||
AbstractAsyncSSLConnection as = e.getConnection();
|
||||
as.stopAsyncReading();
|
||||
SSLConnection sslc = new SSLConnection(as);
|
||||
HttpConnection sslc = as.downgrade();
|
||||
ExchangeImpl<U> ex = new Http1Exchange<>(exchange, sslc);
|
||||
return ex;
|
||||
}
|
||||
|
@ -211,12 +211,13 @@ class Http2Connection {
|
||||
this.hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE));
|
||||
this.windowUpdater = new ConnectionWindowUpdateSender(this, client.getReceiveBufferSize());
|
||||
}
|
||||
/**
|
||||
* Case 1) Create from upgraded HTTP/1.1 connection.
|
||||
* Is ready to use. Will not be SSL. exchange is the Exchange
|
||||
* that initiated the connection, whose response will be delivered
|
||||
* on a Stream.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Case 1) Create from upgraded HTTP/1.1 connection.
|
||||
* Is ready to use. Will not be SSL. exchange is the Exchange
|
||||
* that initiated the connection, whose response will be delivered
|
||||
* on a Stream.
|
||||
*/
|
||||
Http2Connection(HttpConnection connection,
|
||||
Http2ClientImpl client2,
|
||||
Exchange<?> exchange,
|
||||
@ -280,7 +281,7 @@ class Http2Connection {
|
||||
* Throws an IOException if h2 was not negotiated
|
||||
*/
|
||||
private void checkSSLConfig() throws IOException {
|
||||
AsyncSSLConnection aconn = (AsyncSSLConnection)connection;
|
||||
AbstractAsyncSSLConnection aconn = (AbstractAsyncSSLConnection)connection;
|
||||
SSLEngine engine = aconn.getEngine();
|
||||
String alpn = engine.getApplicationProtocol();
|
||||
if (alpn == null || !alpn.equals("h2")) {
|
||||
@ -906,14 +907,14 @@ class Http2Connection {
|
||||
*/
|
||||
static final class ALPNException extends IOException {
|
||||
private static final long serialVersionUID = 23138275393635783L;
|
||||
final AsyncSSLConnection connection;
|
||||
final AbstractAsyncSSLConnection connection;
|
||||
|
||||
ALPNException(String msg, AsyncSSLConnection connection) {
|
||||
ALPNException(String msg, AbstractAsyncSSLConnection connection) {
|
||||
super(msg);
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
AsyncSSLConnection getConnection() {
|
||||
AbstractAsyncSSLConnection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import jdk.incubator.http.internal.common.ByteBufferReference;
|
||||
import jdk.incubator.http.internal.common.Utils;
|
||||
|
||||
/**
|
||||
* Wraps socket channel layer and takes care of SSL also.
|
||||
@ -136,7 +135,11 @@ abstract class HttpConnection implements Closeable {
|
||||
String[] alpn, boolean isHttp2, HttpClientImpl client)
|
||||
{
|
||||
if (proxy != null) {
|
||||
return new SSLTunnelConnection(addr, client, proxy);
|
||||
if (!isHttp2) {
|
||||
return new SSLTunnelConnection(addr, client, proxy);
|
||||
} else {
|
||||
return new AsyncSSLTunnelConnection(addr, client, alpn, proxy);
|
||||
}
|
||||
} else if (!isHttp2) {
|
||||
return new SSLConnection(addr, client, alpn);
|
||||
} else {
|
||||
|
@ -34,12 +34,15 @@ import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A plain text socket tunnel through a proxy. Uses "CONNECT" but does not
|
||||
* encrypt. Used by WebSocket. Subclassed in SSLTunnelConnection for encryption.
|
||||
* encrypt. Used by WebSocket, as well as HTTP over SSL + Proxy.
|
||||
* Wrapped in SSLTunnelConnection or AsyncSSLTunnelConnection for encryption.
|
||||
*/
|
||||
class PlainTunnelingConnection extends HttpConnection {
|
||||
class PlainTunnelingConnection extends HttpConnection implements AsyncConnection {
|
||||
|
||||
final PlainHttpConnection delegate;
|
||||
protected final InetSocketAddress proxyAddr;
|
||||
@ -116,17 +119,17 @@ class PlainTunnelingConnection extends HttpConnection {
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeAsync(ByteBufferReference[] buffers) throws IOException {
|
||||
public void writeAsync(ByteBufferReference[] buffers) throws IOException {
|
||||
delegate.writeAsync(buffers);
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeAsyncUnordered(ByteBufferReference[] buffers) throws IOException {
|
||||
public void writeAsyncUnordered(ByteBufferReference[] buffers) throws IOException {
|
||||
delegate.writeAsyncUnordered(buffers);
|
||||
}
|
||||
|
||||
@Override
|
||||
void flushAsync() throws IOException {
|
||||
public void flushAsync() throws IOException {
|
||||
delegate.flushAsync();
|
||||
}
|
||||
|
||||
@ -165,4 +168,32 @@ class PlainTunnelingConnection extends HttpConnection {
|
||||
boolean isProxied() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsyncCallbacks(Consumer<ByteBufferReference> asyncReceiver,
|
||||
Consumer<Throwable> errorReceiver,
|
||||
Supplier<ByteBufferReference> readBufferSupplier) {
|
||||
delegate.setAsyncCallbacks(asyncReceiver, errorReceiver, readBufferSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startReading() {
|
||||
delegate.startReading();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopAsyncReading() {
|
||||
delegate.stopAsyncReading();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableCallback() {
|
||||
delegate.enableCallback();
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void configureMode(Mode mode) throws IOException {
|
||||
super.configureMode(mode);
|
||||
delegate.configureMode(mode);
|
||||
}
|
||||
}
|
||||
|
@ -77,8 +77,8 @@ class SSLConnection extends HttpConnection {
|
||||
*/
|
||||
SSLConnection(AsyncSSLConnection c) {
|
||||
super(c.address, c.client);
|
||||
this.delegate = c.plainConnection;
|
||||
AsyncSSLDelegate adel = c.sslDelegate;
|
||||
this.delegate = c.plainConnection();
|
||||
AsyncSSLDelegate adel = c.sslDelegate();
|
||||
this.sslDelegate = new SSLDelegate(adel.engine, delegate.channel(), client, adel.serverName);
|
||||
this.alpn = adel.alpn;
|
||||
this.serverName = adel.serverName;
|
||||
|
@ -85,6 +85,19 @@ class SSLTunnelConnection extends HttpConnection {
|
||||
delegate = new PlainTunnelingConnection(addr, proxy, client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an SSLTunnelConnection from an existing connected AsyncSSLTunnelConnection.
|
||||
* Used when downgrading from HTTP/2 to HTTP/1.1
|
||||
*/
|
||||
SSLTunnelConnection(AsyncSSLTunnelConnection c) {
|
||||
super(c.address, c.client);
|
||||
this.delegate = c.plainConnection();
|
||||
AsyncSSLDelegate adel = c.sslDelegate();
|
||||
this.sslDelegate = new SSLDelegate(adel.engine, delegate.channel(), client, adel.serverName);
|
||||
this.serverName = adel.serverName;
|
||||
connected = c.connected();
|
||||
}
|
||||
|
||||
@Override
|
||||
SSLParameters sslParameters() {
|
||||
return sslDelegate.getSSLParameters();
|
||||
|
@ -106,13 +106,24 @@ class ZipUtils {
|
||||
* Converts DOS time to Java time (number of milliseconds since epoch).
|
||||
*/
|
||||
public static long dosToJavaTime(long dtime) {
|
||||
LocalDateTime ldt = LocalDateTime.of(
|
||||
(int) (((dtime >> 25) & 0x7f) + 1980),
|
||||
(int) ((dtime >> 21) & 0x0f),
|
||||
(int) ((dtime >> 16) & 0x1f),
|
||||
(int) ((dtime >> 11) & 0x1f),
|
||||
(int) ((dtime >> 5) & 0x3f),
|
||||
(int) ((dtime << 1) & 0x3e));
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
int hour = (int) ((dtime >> 11) & 0x1f);
|
||||
int minute = (int) ((dtime >> 5) & 0x3f);
|
||||
int second = (int) ((dtime << 1) & 0x3e);
|
||||
if ((dtime >> 16) == 0) {
|
||||
// Interpret the 0 DOS date as 1979-11-30 for compatibility with
|
||||
// other implementations.
|
||||
year = 1979;
|
||||
month = 11;
|
||||
day = 30;
|
||||
} else {
|
||||
year = (int) (((dtime >> 25) & 0x7f) + 1980);
|
||||
month = (int) ((dtime >> 21) & 0x0f);
|
||||
day = (int) ((dtime >> 16) & 0x1f);
|
||||
}
|
||||
LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second);
|
||||
return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond(
|
||||
ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS);
|
||||
}
|
||||
|
@ -21,17 +21,6 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @key headful
|
||||
* @bug 6193279
|
||||
* @summary REGRESSION: AppletViewer throws IOException when path is encoded URL
|
||||
* @author Dmitry Cherepanov: area=appletviewer
|
||||
* @run compile IOExceptionIfEncodedURLTest.java
|
||||
* @run main IOExceptionIfEncodedURLTest
|
||||
* @run shell IOExceptionIfEncodedURLTest.sh
|
||||
*/
|
||||
|
||||
import java.applet.Applet;
|
||||
import sun.net.www.ParseUtil;
|
||||
import java.io.File;
|
||||
|
@ -25,7 +25,7 @@
|
||||
#
|
||||
# @test IOExceptionIfEncodedURLTest.sh
|
||||
# @key headful
|
||||
# @bug 6193279 6619458 8137087
|
||||
# @bug 6193279 6619458 8137087 8186259
|
||||
# @summary REGRESSION: AppletViewer throws IOException when path is encoded URL
|
||||
# @author Dmitry Cherepanov: area=appletviewer
|
||||
# @modules java.base/sun.net.www
|
||||
|
@ -56,9 +56,12 @@ import jdk.testlibrary.SimpleSSLContext;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8185852
|
||||
* @summary verifies that passing a proxy with an unresolved address does
|
||||
* not cause java.nio.channels.UnresolvedAddressException
|
||||
* @bug 8185852 8181422
|
||||
* @summary Verifies that passing a proxy with an unresolved address does
|
||||
* not cause java.nio.channels.UnresolvedAddressException.
|
||||
* Verifies that downgrading from HTTP/2 to HTTP/1.1 works through
|
||||
* an SSL Tunnel connection when the client is HTTP/2 and the server
|
||||
* and proxy are HTTP/1.1
|
||||
* @modules jdk.incubator.httpclient
|
||||
* @library /lib/testlibrary/
|
||||
* @build jdk.testlibrary.SimpleSSLContext ProxyTest
|
||||
@ -111,7 +114,7 @@ public class ProxyTest {
|
||||
server.start();
|
||||
try {
|
||||
test(server, HttpClient.Version.HTTP_1_1);
|
||||
// test(server, HttpClient.Version.HTTP_2);
|
||||
test(server, HttpClient.Version.HTTP_2);
|
||||
} finally {
|
||||
server.stop(0);
|
||||
System.out.println("Server stopped");
|
||||
|
323
jdk/test/java/net/httpclient/http2/ProxyTest2.java
Normal file
323
jdk/test/java/net/httpclient/http2/ProxyTest2.java
Normal file
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright (c) 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 com.sun.net.httpserver.HttpContext;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import com.sun.net.httpserver.HttpsConfigurator;
|
||||
import com.sun.net.httpserver.HttpsParameters;
|
||||
import com.sun.net.httpserver.HttpsServer;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import jdk.incubator.http.HttpClient;
|
||||
import jdk.incubator.http.HttpRequest;
|
||||
import jdk.incubator.http.HttpResponse;
|
||||
import jdk.testlibrary.SimpleSSLContext;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8181422
|
||||
* @summary Verifies that you can access an HTTP/2 server over HTTPS by
|
||||
* tunnelling through an HTTP/1.1 proxy.
|
||||
* @modules jdk.incubator.httpclient
|
||||
* @library /lib/testlibrary server
|
||||
* @modules jdk.incubator.httpclient/jdk.incubator.http.internal.common
|
||||
* jdk.incubator.httpclient/jdk.incubator.http.internal.frame
|
||||
* jdk.incubator.httpclient/jdk.incubator.http.internal.hpack
|
||||
* @build jdk.testlibrary.SimpleSSLContext ProxyTest2
|
||||
* @run main/othervm ProxyTest2
|
||||
* @author danielfuchs
|
||||
*/
|
||||
public class ProxyTest2 {
|
||||
|
||||
static {
|
||||
try {
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
SSLContext.setDefault(new SimpleSSLContext().get());
|
||||
} catch (IOException ex) {
|
||||
throw new ExceptionInInitializerError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static final String RESPONSE = "<html><body><p>Hello World!</body></html>";
|
||||
static final String PATH = "/foo/";
|
||||
|
||||
static Http2TestServer createHttpsServer(ExecutorService exec) throws Exception {
|
||||
Http2TestServer server = new Http2TestServer(true, 0, exec, SSLContext.getDefault());
|
||||
server.addHandler(new Http2Handler() {
|
||||
@Override
|
||||
public void handle(Http2TestExchange he) throws IOException {
|
||||
he.getResponseHeaders().addHeader("encoding", "UTF-8");
|
||||
he.sendResponseHeaders(200, RESPONSE.length());
|
||||
he.getResponseBody().write(RESPONSE.getBytes(StandardCharsets.UTF_8));
|
||||
he.close();
|
||||
}
|
||||
}, PATH);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
throws Exception
|
||||
{
|
||||
ExecutorService exec = Executors.newCachedThreadPool();
|
||||
Http2TestServer server = createHttpsServer(exec);
|
||||
server.start();
|
||||
try {
|
||||
// Http2TestServer over HTTPS does not support HTTP/1.1
|
||||
// => only test with a HTTP/2 client
|
||||
test(server, HttpClient.Version.HTTP_2);
|
||||
} finally {
|
||||
server.stop();
|
||||
exec.shutdown();
|
||||
System.out.println("Server stopped");
|
||||
}
|
||||
}
|
||||
|
||||
public static void test(Http2TestServer server, HttpClient.Version version)
|
||||
throws Exception
|
||||
{
|
||||
System.out.println("Server is: " + server.getAddress().toString());
|
||||
URI uri = new URI("https://localhost:" + server.getAddress().getPort() + PATH + "x");
|
||||
TunnelingProxy proxy = new TunnelingProxy(server);
|
||||
proxy.start();
|
||||
try {
|
||||
System.out.println("Proxy started");
|
||||
Proxy p = new Proxy(Proxy.Type.HTTP,
|
||||
InetSocketAddress.createUnresolved("localhost", proxy.getAddress().getPort()));
|
||||
System.out.println("Setting up request with HttpClient for version: "
|
||||
+ version.name() + "URI=" + uri);
|
||||
ProxySelector ps = ProxySelector.of(
|
||||
InetSocketAddress.createUnresolved("localhost", proxy.getAddress().getPort()));
|
||||
HttpClient client = HttpClient.newBuilder()
|
||||
.version(version)
|
||||
.proxy(ps)
|
||||
.build();
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(uri)
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
System.out.println("Sending request with HttpClient");
|
||||
HttpResponse<String> response
|
||||
= client.send(request, HttpResponse.BodyHandler.asString());
|
||||
System.out.println("Got response");
|
||||
String resp = response.body();
|
||||
System.out.println("Received: " + resp);
|
||||
if (!RESPONSE.equals(resp)) {
|
||||
throw new AssertionError("Unexpected response");
|
||||
}
|
||||
} finally {
|
||||
System.out.println("Stopping proxy");
|
||||
proxy.stop();
|
||||
System.out.println("Proxy stopped");
|
||||
}
|
||||
}
|
||||
|
||||
static class TunnelingProxy {
|
||||
final Thread accept;
|
||||
final ServerSocket ss;
|
||||
final boolean DEBUG = false;
|
||||
final Http2TestServer serverImpl;
|
||||
TunnelingProxy(Http2TestServer serverImpl) throws IOException {
|
||||
this.serverImpl = serverImpl;
|
||||
ss = new ServerSocket();
|
||||
accept = new Thread(this::accept);
|
||||
}
|
||||
|
||||
void start() throws IOException {
|
||||
ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
|
||||
accept.start();
|
||||
}
|
||||
|
||||
// Pipe the input stream to the output stream.
|
||||
private synchronized Thread pipe(InputStream is, OutputStream os, char tag) {
|
||||
return new Thread("TunnelPipe("+tag+")") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
try {
|
||||
int c;
|
||||
while ((c = is.read()) != -1) {
|
||||
os.write(c);
|
||||
os.flush();
|
||||
// if DEBUG prints a + or a - for each transferred
|
||||
// character.
|
||||
if (DEBUG) System.out.print(tag);
|
||||
}
|
||||
is.close();
|
||||
} finally {
|
||||
os.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
if (DEBUG) ex.printStackTrace(System.out);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public InetSocketAddress getAddress() {
|
||||
return new InetSocketAddress(ss.getInetAddress(), ss.getLocalPort());
|
||||
}
|
||||
|
||||
// This is a bit shaky. It doesn't handle continuation
|
||||
// lines, but our client shouldn't send any.
|
||||
// Read a line from the input stream, swallowing the final
|
||||
// \r\n sequence. Stops at the first \n, doesn't complain
|
||||
// if it wasn't preceded by '\r'.
|
||||
//
|
||||
String readLine(InputStream r) throws IOException {
|
||||
StringBuilder b = new StringBuilder();
|
||||
int c;
|
||||
while ((c = r.read()) != -1) {
|
||||
if (c == '\n') break;
|
||||
b.appendCodePoint(c);
|
||||
}
|
||||
if (b.codePointAt(b.length() -1) == '\r') {
|
||||
b.delete(b.length() -1, b.length());
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public void accept() {
|
||||
Socket clientConnection = null;
|
||||
try {
|
||||
while (true) {
|
||||
System.out.println("Tunnel: Waiting for client");
|
||||
Socket previous = clientConnection;
|
||||
try {
|
||||
clientConnection = ss.accept();
|
||||
} catch (IOException io) {
|
||||
if (DEBUG) io.printStackTrace(System.out);
|
||||
break;
|
||||
} finally {
|
||||
// we have only 1 client at a time, so it is safe
|
||||
// to close the previous connection here
|
||||
if (previous != null) previous.close();
|
||||
}
|
||||
System.out.println("Tunnel: Client accepted");
|
||||
Socket targetConnection = null;
|
||||
InputStream ccis = clientConnection.getInputStream();
|
||||
OutputStream ccos = clientConnection.getOutputStream();
|
||||
Writer w = new OutputStreamWriter(ccos, "UTF-8");
|
||||
PrintWriter pw = new PrintWriter(w);
|
||||
System.out.println("Tunnel: Reading request line");
|
||||
String requestLine = readLine(ccis);
|
||||
System.out.println("Tunnel: Request status line: " + requestLine);
|
||||
if (requestLine.startsWith("CONNECT ")) {
|
||||
// We should probably check that the next word following
|
||||
// CONNECT is the host:port of our HTTPS serverImpl.
|
||||
// Some improvement for a followup!
|
||||
|
||||
// Read all headers until we find the empty line that
|
||||
// signals the end of all headers.
|
||||
while(!requestLine.equals("")) {
|
||||
System.out.println("Tunnel: Reading header: "
|
||||
+ (requestLine = readLine(ccis)));
|
||||
}
|
||||
|
||||
// Open target connection
|
||||
targetConnection = new Socket(
|
||||
serverImpl.getAddress().getAddress(),
|
||||
serverImpl.getAddress().getPort());
|
||||
|
||||
// Then send the 200 OK response to the client
|
||||
System.out.println("Tunnel: Sending "
|
||||
+ "HTTP/1.1 200 OK\r\n\r\n");
|
||||
pw.print("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
|
||||
pw.flush();
|
||||
} else {
|
||||
// This should not happen.
|
||||
throw new IOException("Tunnel: Unexpected status line: "
|
||||
+ requestLine);
|
||||
}
|
||||
|
||||
// Pipe the input stream of the client connection to the
|
||||
// output stream of the target connection and conversely.
|
||||
// Now the client and target will just talk to each other.
|
||||
System.out.println("Tunnel: Starting tunnel pipes");
|
||||
Thread t1 = pipe(ccis, targetConnection.getOutputStream(), '+');
|
||||
Thread t2 = pipe(targetConnection.getInputStream(), ccos, '-');
|
||||
t1.start();
|
||||
t2.start();
|
||||
|
||||
// We have only 1 client... wait until it has finished before
|
||||
// accepting a new connection request.
|
||||
// System.out.println("Tunnel: Waiting for pipes to close");
|
||||
t1.join();
|
||||
t2.join();
|
||||
System.out.println("Tunnel: Done - waiting for next client");
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
try {
|
||||
ss.close();
|
||||
} catch (IOException ex1) {
|
||||
ex.addSuppressed(ex1);
|
||||
}
|
||||
ex.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
void stop() throws IOException {
|
||||
ss.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class Configurator extends HttpsConfigurator {
|
||||
public Configurator(SSLContext ctx) {
|
||||
super(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure (HttpsParameters params) {
|
||||
params.setSSLParameters (getSSLContext().getSupportedSSLParameters());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -201,7 +201,17 @@ public class Http2TestServer implements AutoCloseable {
|
||||
InetSocketAddress addr = (InetSocketAddress) socket.getRemoteSocketAddress();
|
||||
Http2TestServerConnection c = new Http2TestServerConnection(this, socket);
|
||||
connections.put(addr, c);
|
||||
c.run();
|
||||
try {
|
||||
c.run();
|
||||
} catch(Throwable e) {
|
||||
// we should not reach here, but if we do
|
||||
// the connection might not have been closed
|
||||
// and if so then the client might wait
|
||||
// forever.
|
||||
connections.remove(addr, c);
|
||||
c.close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
if (!stopping) {
|
||||
|
@ -133,10 +133,10 @@ public class Http2TestServerConnection {
|
||||
}
|
||||
|
||||
void close() {
|
||||
stopping = true;
|
||||
streams.forEach((i, q) -> {
|
||||
q.close();
|
||||
});
|
||||
stopping = true;
|
||||
try {
|
||||
socket.close();
|
||||
// TODO: put a reset on each stream
|
||||
@ -557,7 +557,14 @@ public class Http2TestServerConnection {
|
||||
void writeLoop() {
|
||||
try {
|
||||
while (!stopping) {
|
||||
Http2Frame frame = outputQ.take();
|
||||
Http2Frame frame;
|
||||
try {
|
||||
frame = outputQ.take();
|
||||
} catch(IOException x) {
|
||||
if (stopping && x.getCause() instanceof InterruptedException) {
|
||||
break;
|
||||
} else throw x;
|
||||
}
|
||||
if (frame instanceof ResponseHeaders) {
|
||||
ResponseHeaders rh = (ResponseHeaders)frame;
|
||||
HeadersFrame hf = new HeadersFrame(rh.streamid(), rh.getFlags(), encodeHeaders(rh.headers));
|
||||
|
112
jdk/test/java/util/zip/ZipFile/ZeroDate.java
Normal file
112
jdk/test/java/util/zip/ZipFile/ZeroDate.java
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 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 static java.util.zip.ZipFile.CENOFF;
|
||||
import static java.util.zip.ZipFile.CENTIM;
|
||||
import static java.util.zip.ZipFile.ENDHDR;
|
||||
import static java.util.zip.ZipFile.ENDOFF;
|
||||
import static java.util.zip.ZipFile.LOCTIM;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/* @test
|
||||
* @bug 8184940
|
||||
* @summary JDK 9 rejects zip files where the modified day or month is 0
|
||||
* @author Liam Miller-Cushon
|
||||
*/
|
||||
public class ZeroDate {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// create a zip file, and read it in as a byte array
|
||||
Path path = Files.createTempFile("bad", ".zip");
|
||||
try (OutputStream os = Files.newOutputStream(path);
|
||||
ZipOutputStream zos = new ZipOutputStream(os)) {
|
||||
ZipEntry e = new ZipEntry("x");
|
||||
zos.putNextEntry(e);
|
||||
zos.write((int) 'x');
|
||||
}
|
||||
int len = (int) Files.size(path);
|
||||
byte[] data = new byte[len];
|
||||
try (InputStream is = Files.newInputStream(path)) {
|
||||
is.read(data);
|
||||
}
|
||||
Files.delete(path);
|
||||
|
||||
// year, month, day are zero
|
||||
testDate(data.clone(), 0, LocalDate.of(1979, 11, 30));
|
||||
// only year is zero
|
||||
testDate(data.clone(), 0 << 25 | 4 << 21 | 5 << 16, LocalDate.of(1980, 4, 5));
|
||||
}
|
||||
|
||||
private static void testDate(byte[] data, int date, LocalDate expected) throws IOException {
|
||||
// set the datetime
|
||||
int endpos = data.length - ENDHDR;
|
||||
int cenpos = u16(data, endpos + ENDOFF);
|
||||
int locpos = u16(data, cenpos + CENOFF);
|
||||
writeU32(data, cenpos + CENTIM, date);
|
||||
writeU32(data, locpos + LOCTIM, date);
|
||||
|
||||
// ensure that the archive is still readable, and the date is 1979-11-30
|
||||
Path path = Files.createTempFile("out", ".zip");
|
||||
try (OutputStream os = Files.newOutputStream(path)) {
|
||||
os.write(data);
|
||||
}
|
||||
try (ZipFile zf = new ZipFile(path.toFile())) {
|
||||
ZipEntry ze = zf.entries().nextElement();
|
||||
Instant actualInstant = ze.getLastModifiedTime().toInstant();
|
||||
Instant expectedInstant =
|
||||
expected.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
|
||||
if (!actualInstant.equals(expectedInstant)) {
|
||||
throw new AssertionError(
|
||||
String.format("actual: %s, expected: %s", actualInstant, expectedInstant));
|
||||
}
|
||||
} finally {
|
||||
Files.delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
static int u8(byte[] data, int offset) {
|
||||
return data[offset] & 0xff;
|
||||
}
|
||||
|
||||
static int u16(byte[] data, int offset) {
|
||||
return u8(data, offset) + (u8(data, offset + 1) << 8);
|
||||
}
|
||||
|
||||
private static void writeU32(byte[] data, int pos, int value) {
|
||||
data[pos] = (byte) (value & 0xff);
|
||||
data[pos + 1] = (byte) ((value >> 8) & 0xff);
|
||||
data[pos + 2] = (byte) ((value >> 16) & 0xff);
|
||||
data[pos + 3] = (byte) ((value >> 24) & 0xff);
|
||||
}
|
||||
}
|
120
jdk/test/jdk/nio/zipfs/ZeroDate.java
Normal file
120
jdk/test/jdk/nio/zipfs/ZeroDate.java
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 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 static java.util.zip.ZipFile.CENOFF;
|
||||
import static java.util.zip.ZipFile.CENTIM;
|
||||
import static java.util.zip.ZipFile.ENDHDR;
|
||||
import static java.util.zip.ZipFile.ENDOFF;
|
||||
import static java.util.zip.ZipFile.LOCTIM;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Collections;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/* @test
|
||||
* @bug 8184940
|
||||
* @summary JDK 9 rejects zip files where the modified day or month is 0
|
||||
* @author Liam Miller-Cushon
|
||||
*/
|
||||
public class ZeroDate {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// create a zip file, and read it in as a byte array
|
||||
Path path = Files.createTempFile("bad", ".zip");
|
||||
try (OutputStream os = Files.newOutputStream(path);
|
||||
ZipOutputStream zos = new ZipOutputStream(os)) {
|
||||
ZipEntry e = new ZipEntry("x");
|
||||
zos.putNextEntry(e);
|
||||
zos.write((int) 'x');
|
||||
}
|
||||
int len = (int) Files.size(path);
|
||||
byte[] data = new byte[len];
|
||||
try (InputStream is = Files.newInputStream(path)) {
|
||||
is.read(data);
|
||||
}
|
||||
Files.delete(path);
|
||||
|
||||
// year, month, day are zero
|
||||
testDate(data.clone(), 0, LocalDate.of(1979, 11, 30));
|
||||
// only year is zero
|
||||
testDate(data.clone(), 0 << 25 | 4 << 21 | 5 << 16, LocalDate.of(1980, 4, 5));
|
||||
}
|
||||
|
||||
private static void testDate(byte[] data, int date, LocalDate expected) throws IOException {
|
||||
// set the datetime
|
||||
int endpos = data.length - ENDHDR;
|
||||
int cenpos = u16(data, endpos + ENDOFF);
|
||||
int locpos = u16(data, cenpos + CENOFF);
|
||||
writeU32(data, cenpos + CENTIM, date);
|
||||
writeU32(data, locpos + LOCTIM, date);
|
||||
|
||||
// ensure that the archive is still readable, and the date is 1979-11-30
|
||||
Path path = Files.createTempFile("out", ".zip");
|
||||
try (OutputStream os = Files.newOutputStream(path)) {
|
||||
os.write(data);
|
||||
}
|
||||
URI uri = URI.create("jar:file://" + path.toAbsolutePath());
|
||||
try (FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap())) {
|
||||
Path entry = fs.getPath("x");
|
||||
Instant actualInstant =
|
||||
Files.readAttributes(entry, BasicFileAttributes.class)
|
||||
.lastModifiedTime()
|
||||
.toInstant();
|
||||
Instant expectedInstant =
|
||||
expected.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
|
||||
if (!actualInstant.equals(expectedInstant)) {
|
||||
throw new AssertionError(
|
||||
String.format("actual: %s, expected: %s", actualInstant, expectedInstant));
|
||||
}
|
||||
} finally {
|
||||
Files.delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
static int u8(byte[] data, int offset) {
|
||||
return data[offset] & 0xff;
|
||||
}
|
||||
|
||||
static int u16(byte[] data, int offset) {
|
||||
return u8(data, offset) + (u8(data, offset + 1) << 8);
|
||||
}
|
||||
|
||||
private static void writeU32(byte[] data, int pos, int value) {
|
||||
data[pos] = (byte) (value & 0xff);
|
||||
data[pos + 1] = (byte) ((value >> 8) & 0xff);
|
||||
data[pos + 2] = (byte) ((value >> 16) & 0xff);
|
||||
data[pos + 3] = (byte) ((value >> 24) & 0xff);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -55,6 +55,9 @@ public class SmallPrimeExponentP {
|
||||
CertAndKeyGen ckg = new CertAndKeyGen("RSA", "SHA1withRSA");
|
||||
ckg.setRandom(new MySecureRandom(seed));
|
||||
|
||||
String alias = "anything";
|
||||
int count = 0;
|
||||
|
||||
boolean see63 = false;
|
||||
boolean see65 = false;
|
||||
while (!see63 || !see65) {
|
||||
@ -78,12 +81,19 @@ public class SmallPrimeExponentP {
|
||||
see65 = true;
|
||||
}
|
||||
}
|
||||
ks.setKeyEntry("anything", k, null, new X509Certificate[]{
|
||||
ks.setKeyEntry(alias, k, null, new X509Certificate[]{
|
||||
ckg.getSelfCertificate(new X500Name("CN=Me"), 1000)
|
||||
});
|
||||
count++;
|
||||
}
|
||||
}
|
||||
ks.store(null, null);
|
||||
|
||||
// Because of JDK-8185844, it has to reload the key store after
|
||||
// deleting an entry.
|
||||
for (int i = 0; i < count; i++) {
|
||||
ks.deleteEntry(alias);
|
||||
ks.load(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
static class MySecureRandom extends SecureRandom {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 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 java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
* A custom output stream that redirects the testing outputs to a file, called
|
||||
* details.out. It also calls another output stream to save some outputs to
|
||||
* other files.
|
||||
*/
|
||||
public class DetailsOutputStream extends FileOutputStream {
|
||||
|
||||
private PhaseOutputStream phaseOutputStream = new PhaseOutputStream();
|
||||
|
||||
public DetailsOutputStream() throws FileNotFoundException {
|
||||
super("details.out", true);
|
||||
}
|
||||
|
||||
public void transferPhase() throws IOException {
|
||||
if (phaseOutputStream.isCorePhase()) {
|
||||
phaseOutputStream.write(HtmlHelper.endHtml());
|
||||
phaseOutputStream.write(HtmlHelper.endPre());
|
||||
}
|
||||
|
||||
phaseOutputStream.transfer();
|
||||
|
||||
if (phaseOutputStream.isCorePhase()) {
|
||||
phaseOutputStream.write(HtmlHelper.startHtml());
|
||||
phaseOutputStream.write(HtmlHelper.startPre());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
super.write(b);
|
||||
phaseOutputStream.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
super.write(b);
|
||||
phaseOutputStream.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte b[], int off, int len) throws IOException {
|
||||
super.write(b, off, len);
|
||||
phaseOutputStream.write(b, off, len);
|
||||
}
|
||||
|
||||
public void writeAnchorName(String name, String text) throws IOException {
|
||||
super.write((text).getBytes());
|
||||
super.write('\n');
|
||||
phaseOutputStream.write(HtmlHelper.anchorName(name, text));
|
||||
phaseOutputStream.write('\n');
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A helper that is used for creating HTML elements.
|
||||
*/
|
||||
public class HtmlHelper {
|
||||
|
||||
private static final String STYLE
|
||||
= "style=\"font-family: Courier New; "
|
||||
+ "font-size: 12px; "
|
||||
+ "white-space: pre-wrap\"";
|
||||
|
||||
public static String htmlRow(String... values) {
|
||||
StringBuilder row = new StringBuilder();
|
||||
row.append(startTr());
|
||||
for (String value : values) {
|
||||
row.append(startTd());
|
||||
row.append(value);
|
||||
row.append(endTd());
|
||||
}
|
||||
row.append(endTr());
|
||||
return row.toString();
|
||||
}
|
||||
|
||||
public static String startHtml() {
|
||||
return startTag("html");
|
||||
}
|
||||
|
||||
public static String endHtml() {
|
||||
return endTag("html");
|
||||
}
|
||||
|
||||
public static String startPre() {
|
||||
return startTag("pre " + STYLE);
|
||||
}
|
||||
|
||||
public static String endPre() {
|
||||
return endTag("pre");
|
||||
}
|
||||
|
||||
public static String startTable() {
|
||||
return startTag("table " + STYLE);
|
||||
}
|
||||
|
||||
public static String endTable() {
|
||||
return endTag("table");
|
||||
}
|
||||
|
||||
public static String startTr() {
|
||||
return startTag("tr");
|
||||
}
|
||||
|
||||
public static String endTr() {
|
||||
return endTag("tr");
|
||||
}
|
||||
|
||||
public static String startTd() {
|
||||
return startTag("td");
|
||||
}
|
||||
|
||||
public static String endTd() {
|
||||
return endTag("td");
|
||||
}
|
||||
|
||||
public static String startTag(String tag) {
|
||||
return "<" + tag + ">";
|
||||
}
|
||||
|
||||
public static String endTag(String tag) {
|
||||
return "</" + tag + ">";
|
||||
}
|
||||
|
||||
public static String anchorName(String name, String text) {
|
||||
return "<a name=" + name + ">" + text + "</a>";
|
||||
}
|
||||
|
||||
public static String anchorLink(String file, String anchorName,
|
||||
String text) {
|
||||
return "<a href=" + file + "#" + anchorName + ">" + text + "</a>";
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 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 java.security.NoSuchAlgorithmException;
|
||||
import java.security.Signature;
|
||||
|
||||
/*
|
||||
* This class is used for returning some specific JDK information.
|
||||
*/
|
||||
public class JdkUtils {
|
||||
|
||||
static final String M_JAVA_RUNTIME_VERSION = "javaRuntimeVersion";
|
||||
static final String M_IS_SUPPORTED_SIGALG = "isSupportedSigalg";
|
||||
|
||||
// Returns the JDK build version.
|
||||
static String javaRuntimeVersion() {
|
||||
return System.getProperty("java.runtime.version");
|
||||
}
|
||||
|
||||
// Checks if the specified signature algorithm is supported by the JDK.
|
||||
static boolean isSupportedSigalg(String sigalg) {
|
||||
boolean isSupported = false;
|
||||
try {
|
||||
isSupported = Signature.getInstance(sigalg) != null;
|
||||
} catch (NoSuchAlgorithmException e) { }
|
||||
|
||||
if (!isSupported) {
|
||||
System.out.println(sigalg + " is not supported yet.");
|
||||
}
|
||||
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (M_JAVA_RUNTIME_VERSION.equals(args[0])) {
|
||||
System.out.print(javaRuntimeVersion());
|
||||
} else if (M_IS_SUPPORTED_SIGALG.equals(args[0])) {
|
||||
System.out.print(isSupportedSigalg(args[1]));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 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 java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/*
|
||||
* A custom output stream that saves the testing details to different files
|
||||
* according to the current testing phase.
|
||||
*/
|
||||
public class PhaseOutputStream extends OutputStream {
|
||||
|
||||
public enum Phase {
|
||||
PRE_SIGNING, // before jar signing
|
||||
SIGNING, // jar signing
|
||||
VERIFYING, // jar verifying
|
||||
DELAY_VERIFYING, // jar verifying after certificates expire
|
||||
POST_VERIFYING; // after jar verifying
|
||||
}
|
||||
|
||||
private OutputStream signingOut = null;
|
||||
private OutputStream verifyingOut = null;
|
||||
private OutputStream delayVerifyingOut = null;
|
||||
|
||||
private Phase currentPhase = Phase.PRE_SIGNING;
|
||||
|
||||
public void transfer() {
|
||||
switch (currentPhase) {
|
||||
case PRE_SIGNING:
|
||||
currentPhase = Phase.SIGNING;
|
||||
break;
|
||||
case SIGNING:
|
||||
currentPhase = Phase.VERIFYING;
|
||||
break;
|
||||
case VERIFYING:
|
||||
currentPhase = Compatibility.DELAY_VERIFY
|
||||
? Phase.DELAY_VERIFYING
|
||||
: Phase.POST_VERIFYING;
|
||||
break;
|
||||
case DELAY_VERIFYING:
|
||||
currentPhase = Phase.POST_VERIFYING;
|
||||
break;
|
||||
case POST_VERIFYING:
|
||||
currentPhase = Phase.POST_VERIFYING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The core phases are SIGNING, VERIFYING and DELAY_VERIFYING.
|
||||
public boolean isCorePhase() {
|
||||
return currentPhase != PhaseOutputStream.Phase.PRE_SIGNING
|
||||
&& currentPhase != PhaseOutputStream.Phase.POST_VERIFYING;
|
||||
}
|
||||
|
||||
public Phase currentPhase() {
|
||||
return currentPhase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
OutputStream output = phaseOut();
|
||||
if (output != null) {
|
||||
output.write(b);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
OutputStream output = phaseOut();
|
||||
if (output != null) {
|
||||
output.write(b);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
OutputStream output = phaseOut();
|
||||
if (output != null) {
|
||||
output.write(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
public void write(String str) throws IOException {
|
||||
write(str.getBytes());
|
||||
}
|
||||
|
||||
private OutputStream phaseOut() throws FileNotFoundException {
|
||||
switch (currentPhase) {
|
||||
case SIGNING:
|
||||
return signingOut == null
|
||||
? signingOut = createOutput(Phase.SIGNING)
|
||||
: signingOut;
|
||||
case VERIFYING:
|
||||
return verifyingOut == null
|
||||
? verifyingOut = createOutput(Phase.VERIFYING)
|
||||
: verifyingOut;
|
||||
case DELAY_VERIFYING:
|
||||
return delayVerifyingOut == null
|
||||
? delayVerifyingOut = createOutput(Phase.DELAY_VERIFYING)
|
||||
: delayVerifyingOut;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
flush(signingOut);
|
||||
flush(verifyingOut);
|
||||
flush(delayVerifyingOut);
|
||||
}
|
||||
|
||||
private void flush(OutputStream output) throws IOException {
|
||||
if (output != null) {
|
||||
output.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
close(signingOut);
|
||||
close(verifyingOut);
|
||||
close(delayVerifyingOut);
|
||||
}
|
||||
|
||||
private void close(OutputStream output) throws IOException {
|
||||
if (output != null) {
|
||||
output.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static OutputStream createOutput(Phase phase)
|
||||
throws FileNotFoundException {
|
||||
return new FileOutputStream(fileName(phase), true);
|
||||
}
|
||||
|
||||
public static String fileName(Phase phase) {
|
||||
return phase.name() + ".html";
|
||||
}
|
||||
}
|
215
jdk/test/sun/security/tools/jarsigner/compatibility/README
Normal file
215
jdk/test/sun/security/tools/jarsigner/compatibility/README
Normal file
@ -0,0 +1,215 @@
|
||||
# Copyright (c) 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.
|
||||
|
||||
##### Summary #####
|
||||
This test is used to verify the compatibility on jarsigner cross different JDK
|
||||
releases. It also can be used to check jar signing (w/ and w/o TSA) and verifying
|
||||
on some specific key algorithms and digest algorithms.
|
||||
|
||||
##### Output #####
|
||||
The test will generate a report, at JTwork/scratch/report.html, to display the
|
||||
key parameters for signing and the status of signing and verifying. And it will
|
||||
generate another report, at JTwork/scratch/failedReport.html, to collect all of
|
||||
failed cases.
|
||||
|
||||
Please note that, the test may output a great deal of logs if the jdk list and
|
||||
TSA list are big, and that would lead to jtreg output overflow. So, it redirects
|
||||
stdout and stderr to file JTwork/scratch/details.out.
|
||||
|
||||
##### Report Columns #####
|
||||
Certificate
|
||||
Certificate identifier. The identifier consists of specific attributes of
|
||||
the certificate. Generally, the naming convention is:
|
||||
KeyAlgorithm_DigestAlgorithm_[KeySize][_Expired]
|
||||
|
||||
Signer JDK
|
||||
The JDK version that signs jar.
|
||||
|
||||
Signature Algorithm
|
||||
The signature algorithm used by signing.
|
||||
|
||||
TSA Digest
|
||||
The timestamp digest algorithm used by signing.
|
||||
|
||||
TSA
|
||||
TSA URL index. All of TSA URLs and their indices can be found at the top
|
||||
of this report.
|
||||
|
||||
Signing Status
|
||||
Signing process result status. The status are the followings:
|
||||
[1]NONE, no action.
|
||||
[2]NORMAL, no any error and warning.
|
||||
[3]WARNING, no any error but some warnings raise.
|
||||
[4]ERROR, some errors raise.
|
||||
|
||||
Verifier JDK
|
||||
The JDK version that verifies signed jars.
|
||||
|
||||
Verifying Status
|
||||
Verifying process result status. The status are the same as those for
|
||||
"Status of Signing".
|
||||
|
||||
Delay Verifying Status
|
||||
Delay verifying process result status. The status are the same as those
|
||||
for "Status of Signing".
|
||||
|
||||
Failed
|
||||
It highlights which case fails. The failed cases (rows) are marked with
|
||||
letter X.
|
||||
|
||||
##### Usages #####
|
||||
jtreg [-options] \
|
||||
-jdk:<path/to/testing/JDK>
|
||||
[-DproxyHost=<host> \
|
||||
-DproxyPort=<port> \
|
||||
-DtsaListFile=</url/to/tsaListFile> \
|
||||
-DtsaList=</path/to/tsa1#/path/to/tsa2#/path/to/tsa3#...> \
|
||||
-DjdkListFile=</path/to/jdkListFile> \
|
||||
-DjdkList=</path/to/jdk1#/path/to/jdk2#/path/to/jdk3#...> \
|
||||
-DjavaSecurityFile=</path/to/java/security/properties/file> \
|
||||
-DdelayVerify=<true|false> \
|
||||
-DcertValidity=<[1, 1440]>] \
|
||||
<JDK_REPO>/jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java
|
||||
|
||||
Besides the common jtreg options, like -jdk, this test introduces a set of
|
||||
properties for receiving users' inputs and making the test more flexible. These
|
||||
properties are:
|
||||
proxyHost=<host>
|
||||
This property indicates proxy host.
|
||||
|
||||
proxyPort=<port>
|
||||
This property indicates proxy port. The default value is 80.
|
||||
|
||||
tsaListFile=</path/to/tsaListFile>
|
||||
This property indicates a local file, which contains a set of TSA URLs and
|
||||
the supported digest algorithms (by optional parameter digests). The format
|
||||
of the file content looks like the below,
|
||||
http://path/to/tsa1
|
||||
http://path/to/tsa2;digests=SHA-1,SHA-256
|
||||
https://path/to/tsa3
|
||||
...
|
||||
|
||||
If a TSA line does not list the supported digest algorithms, that means
|
||||
the TSA supports SHA-1, SHA-256 and SHA-512. Because the test only focus
|
||||
on SHA-1, SHA-256 and SHA-512. So, if other digest algorithms, like SHA-224
|
||||
and SHA-384, are listed, they just be ignored.
|
||||
|
||||
tsaList=</path/to/tsa1#/path/to/tsa2;digests=SHA-1,SHA-256#...>
|
||||
This property directly lists a set of TSAs in command. "#" is the delimiter.
|
||||
Note that, if both of tsaListFile and tsaList are specified, only property
|
||||
jdkListFile is selected. If neither of tsaListFile and tsaList is specified,
|
||||
the test will fails immediately.
|
||||
|
||||
jdkListFile=</path/to/jdkListFile>
|
||||
This property indicates a local file, which contains a set of local JDK
|
||||
paths. The style of the file content looks like the below,
|
||||
/path/to/jdk1
|
||||
/path/to/jdk2
|
||||
/path/to/jdk3
|
||||
...
|
||||
|
||||
jdkList=</path/to/jdk1#/path/to/jdk2#/path/to/jdk3#...>
|
||||
This property directly lists a set of local JDK paths in command. "#" is
|
||||
the delimiter.
|
||||
Note that, if both of jdkListFile and jdkList are specified, only property
|
||||
jdkListFile is selected. If neither of jdkListFile nor jdkList is specified,
|
||||
the testing JDK, which is specified by jtreg option -jdk will be used as
|
||||
the only one JDK in the JDK list.
|
||||
|
||||
javaSecurityFile=</path/to/java/security/properties/file>
|
||||
This property indicates an alternative java security properties file. The
|
||||
default file is the path of file java.scurity that is distributed with
|
||||
this test.
|
||||
|
||||
delayVerify=<true|false>
|
||||
This property indicates if doing an additional verifying after all of valid
|
||||
certificates expire. The default value is false.
|
||||
|
||||
certValidity=<[1, 1440]>
|
||||
This property indicates the remaining validity period in minutes for valid
|
||||
certificates. The value range is [1, 1440]. The default value is 1440.
|
||||
Note that, if delayVerify is false, this property doesn't take effect.
|
||||
|
||||
The testing JDK, which is specified by jtreg option "-jdk", should include the
|
||||
fix for JDK-8163304. Otherwise, the signature algorithm and timestamp digest
|
||||
algorithm cannot be extracted from verification output. And this JDK should
|
||||
support as many as possible signature algorithms. Anyway the latest JDK build
|
||||
is always recommended.
|
||||
|
||||
##### Examples #####
|
||||
$ cat /path/to/jdkList
|
||||
/path/to/jdk6u171-b05
|
||||
/path/to/jdk7u161-b05
|
||||
/path/to/jdk8u144-b01
|
||||
/path/to/jdk9-179
|
||||
|
||||
$ cat /path/to/tsaList
|
||||
http://timestamp.comodoca.com/rfc3161
|
||||
http://sha256timestamp.ws.symantec.com/sha256/timestamp
|
||||
http://tsa.starfieldtech.com
|
||||
http://timestamp.entrust.net/TSS/RFC3161sha1TS;digests=SHA-1,SHA-256
|
||||
http://timestamp.entrust.net/TSS/RFC3161sha2TS;digests=SHA-1,SHA-256
|
||||
http://rfc3161timestamp.globalsign.com/advanced;digests=SHA-256,SHA-512
|
||||
http://rfc3161timestamp.globalsign.com/standard
|
||||
http://timestamp.globalsign.com/scripts/timstamp.dll
|
||||
http://timestamp.globalsign.com/?signature=sha2;digests=SHA-256,SHA-512
|
||||
http://timestamp.digicert.com
|
||||
http://time.certum.pl
|
||||
http://tsa.swisssign.net
|
||||
http://zeitstempel.dfn.de
|
||||
https://tsp.iaik.tugraz.at/tsp/TspRequest
|
||||
|
||||
$ jtreg -va -nr -timeout:100 \
|
||||
-jdk:/path/to/latest/jdk \
|
||||
-DproxyHost=<proxy> -DproxyPort=<port> \
|
||||
-DjdkListFile=/path/to/jdkList \
|
||||
-DtsaListFile=/path/to/tsaList \
|
||||
-DdelayVerify=true -DcertValidity=60 \
|
||||
<JDK_REPO>/jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java
|
||||
|
||||
The above is a comprehensive usage example. File "jdkList" lists the paths of
|
||||
testing JDK builds, and file "tsaList" lists the URLs of TSA services. Some TSAs,
|
||||
like http://timestamp.entrust.net/TSS/RFC3161sha1TS, specify the supported digest
|
||||
algorithms. Other TSAs, which don't specify parameter digests, are regarded to
|
||||
support SHA-1, SHA-256 and SHA-512. The test uses a proxy to access TSA services.
|
||||
And it enables delay verifying and set the certificate validity period to 60
|
||||
minutes. So, after the first verification is done, the test will wait for all
|
||||
of valid certificates expire and then does verification again.
|
||||
|
||||
If don't want to provide such JDK list and TSA list files, the test allows to
|
||||
specify JDKs and TSAs (via properties jdkList and tsaList respectively) in the
|
||||
command directly, like the below style,
|
||||
$ jtreg -va -nr -timeout:100 \
|
||||
-jdk:/path/to/latest/jdk \
|
||||
-DproxyHost=<proxy> -DproxyPort=<port> \
|
||||
-DjdkList=/path/to/jdk6u171-b05#/path/to/jdk7u161-b05#/path/to/jdk8u144-b01#/path/to/jdk9-179 \
|
||||
-DtsaList=http://timestamp.comodoca.com/rfc3161#http://timestamp.entrust.net/TSS/RFC3161sha1TS;digests=SHA-1,SHA-256 \
|
||||
-DdelayVerify=true -DcertValidity=60 \
|
||||
<JDK_REPO>/jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java
|
||||
|
||||
Furthermore, here introduces one of the simplest usages. It doesn't specify any
|
||||
JDK list, so the testing JDK, which is specified by jtreg option "-jdk", will
|
||||
be tested. And it doesn't apply delay verifying, and no proxy is used, and use
|
||||
only one TSA. Now, the command is pretty simple and looks like the followings,
|
||||
$ jtreg -va -nr -timeout:100 \
|
||||
-jdk:/path/to/latest/jdk \
|
||||
-DtsaList=http://timestamp.comodoca.com/rfc3161 \
|
||||
<JDK_REPO>/jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java
|
@ -0,0 +1,2 @@
|
||||
jdk.certpath.disabledAlgorithms=MD2, MD5
|
||||
jdk.jar.disabledAlgorithms=MD2, MD5
|
Loading…
Reference in New Issue
Block a user