Merge
This commit is contained in:
commit
a6132067a5
@ -72,10 +72,13 @@ import sun.net.util.IPAddressUtil;
|
|||||||
*
|
*
|
||||||
* <h3> Address types </h3>
|
* <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>
|
* <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>
|
* <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
|
* <td>An identifier for a single interface. A packet sent to
|
||||||
* a unicast address is delivered to the interface identified by
|
* a unicast address is delivered to the interface identified by
|
||||||
* that address.
|
* that address.
|
||||||
@ -94,12 +97,12 @@ import sun.net.util.IPAddressUtil;
|
|||||||
* IP address loops around and becomes IP input on the local
|
* IP address loops around and becomes IP input on the local
|
||||||
* host. This address is often used when testing a
|
* host. This address is often used when testing a
|
||||||
* client.</td></tr>
|
* 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
|
* <td>An identifier for a set of interfaces (typically belonging
|
||||||
* to different nodes). A packet sent to a multicast address is
|
* to different nodes). A packet sent to a multicast address is
|
||||||
* delivered to all interfaces identified by that address.</td></tr>
|
* delivered to all interfaces identified by that address.</td></tr>
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table></blockquote>
|
* </table>
|
||||||
*
|
*
|
||||||
* <h4> IP address scope </h4>
|
* <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
|
* <p> Two Java security properties control the TTL values used for
|
||||||
* positive and negative host name resolution caching:
|
* positive and negative host name resolution caching:
|
||||||
*
|
*
|
||||||
* <blockquote>
|
* <dl style="margin-left:2em">
|
||||||
* <dl>
|
|
||||||
* <dt><b>networkaddress.cache.ttl</b></dt>
|
* <dt><b>networkaddress.cache.ttl</b></dt>
|
||||||
* <dd>Indicates the caching policy for successful name lookups from
|
* <dd>Indicates the caching policy for successful name lookups from
|
||||||
* the name service. The value is specified as an integer to indicate
|
* 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".
|
* A value of -1 indicates "cache forever".
|
||||||
* </dd>
|
* </dd>
|
||||||
* </dl>
|
* </dl>
|
||||||
* </blockquote>
|
|
||||||
*
|
*
|
||||||
* @author Chris Warth
|
* @author Chris Warth
|
||||||
* @see java.net.InetAddress#getByAddress(byte[])
|
* @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:
|
* <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>
|
* <caption style="display:none">Describes the components of a URI:scheme,scheme-specific-part,authority,user-info,host,port,path,query,fragment</caption>
|
||||||
* <thead>
|
* <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>
|
* </thead>
|
||||||
* <tbody>
|
* <tbody style="text-align:left">
|
||||||
* <tr><td>scheme</td><td>{@code String}</td></tr>
|
* <tr><th scope="row">scheme</th><td>{@code String}</td></tr>
|
||||||
* <tr><td>scheme-specific-part </td><td>{@code String}</td></tr>
|
* <tr><th scope="row">scheme-specific-part</th><td>{@code String}</td></tr>
|
||||||
* <tr><td>authority</td><td>{@code String}</td></tr>
|
* <tr><th scope="row">authority</th><td>{@code String}</td></tr>
|
||||||
* <tr><td>user-info</td><td>{@code String}</td></tr>
|
* <tr><th scope="row">user-info</th><td>{@code String}</td></tr>
|
||||||
* <tr><td>host</td><td>{@code String}</td></tr>
|
* <tr><th scope="row">host</th><td>{@code String}</td></tr>
|
||||||
* <tr><td>port</td><td>{@code int}</td></tr>
|
* <tr><th scope="row">port</th><td>{@code int}</td></tr>
|
||||||
* <tr><td>path</td><td>{@code String}</td></tr>
|
* <tr><th scope="row">path</th><td>{@code String}</td></tr>
|
||||||
* <tr><td>query</td><td>{@code String}</td></tr>
|
* <tr><th scope="row">query</th><td>{@code String}</td></tr>
|
||||||
* <tr><td>fragment</td><td>{@code String}</td></tr>
|
* <tr><th scope="row">fragment</th><td>{@code String}</td></tr>
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table></blockquote>
|
* </table>
|
||||||
*
|
*
|
||||||
* In a given instance any particular component is either <i>undefined</i> or
|
* In a given instance any particular component is either <i>undefined</i> or
|
||||||
* <i>defined</i> with a distinct value. Undefined string components are
|
* <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
|
* which are taken from that specification, are used below to describe these
|
||||||
* constraints:
|
* 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>
|
* <caption style="display:none">Describes categories alpha,digit,alphanum,unreserved,punct,reserved,escaped,and other</caption>
|
||||||
* <tbody>
|
* <thead>
|
||||||
* <tr><th style="vertical-align:top"><i>alpha</i></th>
|
* <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,
|
* <td>The US-ASCII alphabetic characters,
|
||||||
* {@code 'A'} through {@code 'Z'}
|
* {@code 'A'} through {@code 'Z'}
|
||||||
* and {@code 'a'} through {@code 'z'}</td></tr>
|
* 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,
|
* <td>The US-ASCII decimal digit characters,
|
||||||
* {@code '0'} through {@code '9'}</td></tr>
|
* {@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>
|
* <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
|
* <td>All <i>alphanum</i> characters together with those in the string
|
||||||
* {@code "_-!.~'()*"}</td></tr>
|
* {@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>
|
* <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
|
* <td>All <i>punct</i> characters together with those in the string
|
||||||
* {@code "?/[]@"}</td></tr>
|
* {@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
|
* <td>Escaped octets, that is, triplets consisting of the percent
|
||||||
* character ({@code '%'}) followed by two hexadecimal digits
|
* character ({@code '%'}) followed by two hexadecimal digits
|
||||||
* ({@code '0'}-{@code '9'}, {@code 'A'}-{@code 'F'}, and
|
* ({@code '0'}-{@code '9'}, {@code 'A'}-{@code 'F'}, and
|
||||||
* {@code 'a'}-{@code 'f'})</td></tr>
|
* {@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,
|
* <td>The Unicode characters that are not in the US-ASCII character set,
|
||||||
* are not control characters (according to the {@link
|
* are not control characters (according to the {@link
|
||||||
* java.lang.Character#isISOControl(char) Character.isISOControl}
|
* 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
|
* method) <i>(<b>Deviation from RFC 2396</b>, which is
|
||||||
* limited to US-ASCII)</i></td></tr>
|
* limited to US-ASCII)</i></td></tr>
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table></blockquote>
|
* </table>
|
||||||
*
|
*
|
||||||
* <p><a id="legal-chars"></a> The set of all legal URI characters consists of
|
* <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>
|
* 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
|
* The abstract class {@code URLConnection} is the superclass
|
||||||
* of all classes that represent a communications link between the
|
* of all classes that represent a communications link between the
|
||||||
* application and a URL. Instances of this class can be used both to
|
* 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
|
* read from and to write to the resource referenced by the URL.
|
||||||
* 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>
|
|
||||||
*
|
*
|
||||||
|
* <p>
|
||||||
|
* In general, creating a connection to a URL is a multistep process:
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>The connection object is created by invoking the
|
* <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 setup parameters and general request properties are manipulated.
|
||||||
* <li>The actual connection to the remote object is made, using the
|
* <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
|
* <li>The remote object becomes available. The header fields and the contents
|
||||||
* of the remote object can be accessed.
|
* of the remote object can be accessed.
|
||||||
* </ol>
|
* </ol>
|
||||||
|
@ -72,22 +72,22 @@ import java.security.Permission;
|
|||||||
* separated by '/' characters. <i>path</i> may also be empty. The path is specified
|
* 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
|
* in a similar way to the path in {@link java.io.FilePermission}. There are
|
||||||
* three different ways as the following examples show:
|
* three different ways as the following examples show:
|
||||||
* <table class="plain">
|
* <table class="striped">
|
||||||
* <caption>URL Examples</caption>
|
* <caption>URL Examples</caption>
|
||||||
* <thead>
|
* <thead>
|
||||||
* <tr><th>Example url</th><th>Description</th></tr>
|
* <tr><th scope="col">Example url</th><th scope="col">Description</th></tr>
|
||||||
* </thead>
|
* </thead>
|
||||||
* <tbody>
|
* <tbody style="text-align:left">
|
||||||
* <tr><td style="white-space:nowrap;">http://www.oracle.com/a/b/c.html</td>
|
* <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>
|
* <td>A url which identifies a specific (single) resource</td>
|
||||||
* </tr>
|
* </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
|
* <td>The '*' character refers to all resources in the same "directory" - in
|
||||||
* other words all resources with the same number of path components, and
|
* other words all resources with the same number of path components, and
|
||||||
* which only differ in the final path component, represented by the '*'.
|
* which only differ in the final path component, represented by the '*'.
|
||||||
* </td>
|
* </td>
|
||||||
* </tr>
|
* </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
|
* <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
|
* preceding path (eg. http://www.oracle.com/a/b/c/d/e.html matches this
|
||||||
* example).
|
* example).
|
||||||
@ -114,11 +114,12 @@ import java.security.Permission;
|
|||||||
* methods and permitted request headers of the permission (respectively). The two lists
|
* 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.
|
* are separated by a colon ':' character and elements of each list are comma separated.
|
||||||
* Some examples are:
|
* Some examples are:
|
||||||
* <pre>
|
* <ul>
|
||||||
* "POST,GET,DELETE"
|
* <li>"POST,GET,DELETE"
|
||||||
* "GET:X-Foo-Request,X-Bar-Request"
|
* <li>"GET:X-Foo-Request,X-Bar-Request"
|
||||||
* "POST,GET:Header1,Header2"
|
* <li>"POST,GET:Header1,Header2"
|
||||||
* </pre>
|
* </ul>
|
||||||
|
* <p>
|
||||||
* The first example specifies the methods: POST, GET and DELETE, but no request headers.
|
* 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
|
* The second example specifies one request method and two headers. The third
|
||||||
* example specifies two request methods, and two headers.
|
* example specifies two request methods, and two headers.
|
||||||
@ -253,16 +254,16 @@ public final class URLPermission extends Permission {
|
|||||||
* <table class="plain">
|
* <table class="plain">
|
||||||
* <caption>Examples of Path Matching</caption>
|
* <caption>Examples of Path Matching</caption>
|
||||||
* <thead>
|
* <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>
|
* </thead>
|
||||||
* <tbody>
|
* <tbody style="text-align:left">
|
||||||
* <tr><td>/a/b</td><td>/a/b</td><td>yes</td></tr>
|
* <tr><th scope="row">/a/b</th><th scope="row">/a/b</th><td>yes</td></tr>
|
||||||
* <tr><td>/a/b/*</td><td>/a/b/c</td><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><td>/a/b/*</td><td>/a/b/c/d</td><td>no</td></tr>
|
* <tr> <th scope="row">/a/b/c/d</th><td>no</td></tr>
|
||||||
* <tr><td>/a/b/-</td><td>/a/b/c/d</td><td>yes</td></tr>
|
* <tr> <th scope="row">/a/b/c/-</th><td>no</td></tr>
|
||||||
* <tr><td>/a/b/-</td><td>/a/b/c/d/e</td><td>yes</td></tr>
|
* <tr><th scope="row" rowspan="3">/a/b/-</th><th scope="row">/a/b/c/d</th><td>yes</td></tr>
|
||||||
* <tr><td>/a/b/-</td><td>/a/b/c/*</td><td>yes</td></tr>
|
* <tr> <th scope="row">/a/b/c/d/e</th><td>yes</td></tr>
|
||||||
* <tr><td>/a/b/*</td><td>/a/b/c/-</td><td>no</td></tr>
|
* <tr> <th scope="row">/a/b/c/*</th><td>yes</td></tr>
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table>
|
* </table>
|
||||||
*/
|
*/
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
or visit www.oracle.com if you need additional information or have any
|
or visit www.oracle.com if you need additional information or have any
|
||||||
questions.
|
questions.
|
||||||
-->
|
-->
|
||||||
<HTML>
|
<HTML lang="EN">
|
||||||
<HEAD>
|
<HEAD>
|
||||||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
||||||
<TITLE>Networking Properties</TITLE>
|
<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,
|
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,
|
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
|
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
|
The purpose of this document is to list
|
||||||
and detail all of these properties.</P>
|
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>
|
<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())
|
* Capability effective = ((DrbgParametes.Initiate) s.getParameters())
|
||||||
* .getCapability();</pre>
|
* .getCapability();</pre>
|
||||||
* </blockquote>
|
* </blockquote>
|
||||||
* <table class="plain">
|
* <table class="striped">
|
||||||
* <caption style="display:none">requested and effective capabilities</caption>
|
* <caption style="display:none">requested and effective capabilities</caption>
|
||||||
* <thead>
|
* <thead>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <th>Requested Value</th>
|
* <th scope="col">Requested Value</th>
|
||||||
* <th>Possible Effective Values</th>
|
* <th scope="col">Possible Effective Values</th>
|
||||||
* </tr>
|
* </tr>
|
||||||
* </thead>
|
* </thead>
|
||||||
* <tbody>
|
* <tbody style="text-align:left">
|
||||||
* <tr><td>NONE</td><td>NONE, RESEED_ONLY, PR_AND_RESEED</td></tr>
|
* <tr><th scope="row">NONE</th><td>NONE, RESEED_ONLY, PR_AND_RESEED</td></tr>
|
||||||
* <tr><td>RESEED_ONLY</td><td>RESEED_ONLY, PR_AND_RESEED</td></tr>
|
* <tr><th scope="row">RESEED_ONLY</th><td>RESEED_ONLY, PR_AND_RESEED</td></tr>
|
||||||
* <tr><td>PR_AND_RESEED</td><td>PR_AND_RESEED</td></tr>
|
* <tr><th scope="row">PR_AND_RESEED</th><td>PR_AND_RESEED</td></tr>
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table>
|
* </table>
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -61,19 +61,19 @@ import java.util.function.Function;
|
|||||||
* security framework. Services of this type cannot be added, removed,
|
* security framework. Services of this type cannot be added, removed,
|
||||||
* or modified by applications.
|
* or modified by applications.
|
||||||
* The following attributes are automatically placed in each Provider object:
|
* 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>
|
* <caption><b>Attributes Automatically Placed in a Provider Object</b></caption>
|
||||||
* <thead>
|
* <thead>
|
||||||
* <tr><th>Name</th><th>Value</th>
|
* <tr><th scope="col">Name</th><th scope="col">Value</th>
|
||||||
* </thead>
|
* </thead>
|
||||||
* <tbody>
|
* <tbody style="text-align:left">
|
||||||
* <tr><td>{@code Provider.id name}</td>
|
* <tr><th scope="row">{@code Provider.id name}</th>
|
||||||
* <td>{@code String.valueOf(provider.getName())}</td>
|
* <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>
|
* <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>
|
* <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>
|
* <td>{@code provider.getClass().getName()}</td>
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table>
|
* </table>
|
||||||
|
@ -153,33 +153,33 @@ public interface X509Extension {
|
|||||||
* by periods.
|
* by periods.
|
||||||
*
|
*
|
||||||
* <p>For example:<br>
|
* <p>For example:<br>
|
||||||
* <table class="plain">
|
* <table class="striped">
|
||||||
* <caption style="display:none">Examples of OIDs and extension names</caption>
|
* <caption style="display:none">Examples of OIDs and extension names</caption>
|
||||||
* <thead>
|
* <thead>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <th>OID <em>(Object Identifier)</em></th>
|
* <th scope="col">OID <em>(Object Identifier)</em></th>
|
||||||
* <th>Extension Name</th></tr>
|
* <th scope="col">Extension Name</th></tr>
|
||||||
* </thead>
|
* </thead>
|
||||||
* <tbody>
|
* <tbody style="text-align:left">
|
||||||
* <tr><td>2.5.29.14</td>
|
* <tr><th scope="row">2.5.29.14</th>
|
||||||
* <td>SubjectKeyIdentifier</td></tr>
|
* <td>SubjectKeyIdentifier</td></tr>
|
||||||
* <tr><td>2.5.29.15</td>
|
* <tr><th scope="row">2.5.29.15</th>
|
||||||
* <td>KeyUsage</td></tr>
|
* <td>KeyUsage</td></tr>
|
||||||
* <tr><td>2.5.29.16</td>
|
* <tr><th scope="row">2.5.29.16</th>
|
||||||
* <td>PrivateKeyUsage</td></tr>
|
* <td>PrivateKeyUsage</td></tr>
|
||||||
* <tr><td>2.5.29.17</td>
|
* <tr><th scope="row">2.5.29.17</th>
|
||||||
* <td>SubjectAlternativeName</td></tr>
|
* <td>SubjectAlternativeName</td></tr>
|
||||||
* <tr><td>2.5.29.18</td>
|
* <tr><th scope="row">2.5.29.18</th>
|
||||||
* <td>IssuerAlternativeName</td></tr>
|
* <td>IssuerAlternativeName</td></tr>
|
||||||
* <tr><td>2.5.29.19</td>
|
* <tr><th scope="row">2.5.29.19</th>
|
||||||
* <td>BasicConstraints</td></tr>
|
* <td>BasicConstraints</td></tr>
|
||||||
* <tr><td>2.5.29.30</td>
|
* <tr><th scope="row">2.5.29.30</th>
|
||||||
* <td>NameConstraints</td></tr>
|
* <td>NameConstraints</td></tr>
|
||||||
* <tr><td>2.5.29.33</td>
|
* <tr><th scope="row">2.5.29.33</th>
|
||||||
* <td>PolicyMappings</td></tr>
|
* <td>PolicyMappings</td></tr>
|
||||||
* <tr><td>2.5.29.35</td>
|
* <tr><th scope="row">2.5.29.35</th>
|
||||||
* <td>AuthorityKeyIdentifier</td></tr>
|
* <td>AuthorityKeyIdentifier</td></tr>
|
||||||
* <tr><td>2.5.29.36</td>
|
* <tr><th scope="row">2.5.29.36</th>
|
||||||
* <td>PolicyConstraints</td></tr>
|
* <td>PolicyConstraints</td></tr>
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table>
|
* </table>
|
||||||
|
@ -81,13 +81,24 @@ class ZipUtils {
|
|||||||
* Converts DOS time to Java time (number of milliseconds since epoch).
|
* Converts DOS time to Java time (number of milliseconds since epoch).
|
||||||
*/
|
*/
|
||||||
public static long dosToJavaTime(long dtime) {
|
public static long dosToJavaTime(long dtime) {
|
||||||
LocalDateTime ldt = LocalDateTime.of(
|
int year;
|
||||||
(int) (((dtime >> 25) & 0x7f) + 1980),
|
int month;
|
||||||
(int) ((dtime >> 21) & 0x0f),
|
int day;
|
||||||
(int) ((dtime >> 16) & 0x1f),
|
int hour = (int) ((dtime >> 11) & 0x1f);
|
||||||
(int) ((dtime >> 11) & 0x1f),
|
int minute = (int) ((dtime >> 5) & 0x3f);
|
||||||
(int) ((dtime >> 5) & 0x3f),
|
int second = (int) ((dtime << 1) & 0x3e);
|
||||||
(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(
|
return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond(
|
||||||
ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS);
|
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
|
* href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
|
||||||
* Application-Layer Protocol Negotiation (ALPN), can negotiate
|
* Application-Layer Protocol Negotiation (ALPN), can negotiate
|
||||||
* application-level values between peers.
|
* application-level values between peers.
|
||||||
* <p>
|
*
|
||||||
* @implSpec
|
* @implSpec
|
||||||
* The implementation in this class throws
|
* The implementation in this class throws
|
||||||
* {@code UnsupportedOperationException} and performs no other action.
|
* {@code UnsupportedOperationException} and performs no other action.
|
||||||
@ -1317,7 +1317,7 @@ public abstract class SSLEngine {
|
|||||||
* Like {@link #getHandshakeSession()},
|
* Like {@link #getHandshakeSession()},
|
||||||
* a connection may be in the middle of a handshake. The
|
* a connection may be in the middle of a handshake. The
|
||||||
* application protocol may or may not yet be available.
|
* application protocol may or may not yet be available.
|
||||||
* <p>
|
*
|
||||||
* @implSpec
|
* @implSpec
|
||||||
* The implementation in this class throws
|
* The implementation in this class throws
|
||||||
* {@code UnsupportedOperationException} and performs no other action.
|
* {@code UnsupportedOperationException} and performs no other action.
|
||||||
|
@ -646,7 +646,7 @@ public class SSLParameters {
|
|||||||
* requested by the peer, the underlying protocol will determine what
|
* requested by the peer, the underlying protocol will determine what
|
||||||
* action to take. (For example, ALPN will send a
|
* action to take. (For example, ALPN will send a
|
||||||
* {@code "no_application_protocol"} alert and terminate the connection.)
|
* {@code "no_application_protocol"} alert and terminate the connection.)
|
||||||
* <p>
|
*
|
||||||
* @implSpec
|
* @implSpec
|
||||||
* This method will make a copy of the {@code protocols} array.
|
* 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
|
* href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
|
||||||
* Application-Layer Protocol Negotiation (ALPN), can negotiate
|
* Application-Layer Protocol Negotiation (ALPN), can negotiate
|
||||||
* application-level values between peers.
|
* application-level values between peers.
|
||||||
* <p>
|
*
|
||||||
* @implSpec
|
* @implSpec
|
||||||
* The implementation in this class throws
|
* The implementation in this class throws
|
||||||
* {@code UnsupportedOperationException} and performs no other action.
|
* {@code UnsupportedOperationException} and performs no other action.
|
||||||
@ -727,7 +727,7 @@ public abstract class SSLSocket extends Socket
|
|||||||
* Like {@link #getHandshakeSession()},
|
* Like {@link #getHandshakeSession()},
|
||||||
* a connection may be in the middle of a handshake. The
|
* a connection may be in the middle of a handshake. The
|
||||||
* application protocol may or may not yet be available.
|
* application protocol may or may not yet be available.
|
||||||
* <p>
|
*
|
||||||
* @implSpec
|
* @implSpec
|
||||||
* The implementation in this class throws
|
* The implementation in this class throws
|
||||||
* {@code UnsupportedOperationException} and performs no other action.
|
* {@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 javax.net.ssl.SSLEngine;
|
||||||
|
|
||||||
import jdk.incubator.http.internal.common.ByteBufferReference;
|
import jdk.incubator.http.internal.common.ByteBufferReference;
|
||||||
import jdk.incubator.http.internal.common.ExceptionallyCloseable;
|
|
||||||
import jdk.incubator.http.internal.common.Utils;
|
import jdk.incubator.http.internal.common.Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronous version of SSLConnection.
|
* Asynchronous version of SSLConnection.
|
||||||
*/
|
*/
|
||||||
class AsyncSSLConnection extends HttpConnection
|
class AsyncSSLConnection extends AbstractAsyncSSLConnection {
|
||||||
implements AsyncConnection, ExceptionallyCloseable {
|
|
||||||
|
|
||||||
final AsyncSSLDelegate sslDelegate;
|
final AsyncSSLDelegate sslDelegate;
|
||||||
final PlainHttpConnection plainConnection;
|
final PlainHttpConnection plainConnection;
|
||||||
@ -61,15 +59,14 @@ class AsyncSSLConnection extends HttpConnection
|
|||||||
plainConnection.configureMode(mode);
|
plainConnection.configureMode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Void> configureModeAsync(Void ignore) {
|
@Override
|
||||||
CompletableFuture<Void> cf = new CompletableFuture<>();
|
PlainHttpConnection plainConnection() {
|
||||||
try {
|
return plainConnection;
|
||||||
configureMode(Mode.ASYNC);
|
}
|
||||||
cf.complete(null);
|
|
||||||
} catch (Throwable t) {
|
@Override
|
||||||
cf.completeExceptionally(t);
|
AsyncSSLDelegate sslDelegate() {
|
||||||
}
|
return sslDelegate;
|
||||||
return cf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -91,11 +88,6 @@ class AsyncSSLConnection extends HttpConnection
|
|||||||
return plainConnection.connected() && sslDelegate.connected();
|
return plainConnection.connected() && sslDelegate.connected();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean isSecure() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean isProxied() {
|
boolean isProxied() {
|
||||||
return false;
|
return false;
|
||||||
@ -172,6 +164,7 @@ class AsyncSSLConnection extends HttpConnection
|
|||||||
plainConnection.channel().shutdownOutput();
|
plainConnection.channel().shutdownOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
SSLEngine getEngine() {
|
SSLEngine getEngine() {
|
||||||
return sslDelegate.getEngine();
|
return sslDelegate.getEngine();
|
||||||
}
|
}
|
||||||
@ -184,18 +177,6 @@ class AsyncSSLConnection extends HttpConnection
|
|||||||
plainConnection.setAsyncCallbacks(sslDelegate::asyncReceive, errorReceiver, sslDelegate::getNetBuffer);
|
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
|
@Override
|
||||||
public void startReading() {
|
public void startReading() {
|
||||||
plainConnection.startReading();
|
plainConnection.startReading();
|
||||||
@ -206,4 +187,9 @@ class AsyncSSLConnection extends HttpConnection
|
|||||||
public void stopAsyncReading() {
|
public void stopAsyncReading() {
|
||||||
plainConnection.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);
|
c = c2.getConnectionFor(request);
|
||||||
} catch (Http2Connection.ALPNException e) {
|
} catch (Http2Connection.ALPNException e) {
|
||||||
// failed to negotiate "h2"
|
// failed to negotiate "h2"
|
||||||
AsyncSSLConnection as = e.getConnection();
|
AbstractAsyncSSLConnection as = e.getConnection();
|
||||||
as.stopAsyncReading();
|
as.stopAsyncReading();
|
||||||
SSLConnection sslc = new SSLConnection(as);
|
HttpConnection sslc = as.downgrade();
|
||||||
ExchangeImpl<U> ex = new Http1Exchange<>(exchange, sslc);
|
ExchangeImpl<U> ex = new Http1Exchange<>(exchange, sslc);
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
|
@ -211,12 +211,13 @@ class Http2Connection {
|
|||||||
this.hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE));
|
this.hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE));
|
||||||
this.windowUpdater = new ConnectionWindowUpdateSender(this, client.getReceiveBufferSize());
|
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
|
* Case 1) Create from upgraded HTTP/1.1 connection.
|
||||||
* that initiated the connection, whose response will be delivered
|
* Is ready to use. Will not be SSL. exchange is the Exchange
|
||||||
* on a Stream.
|
* that initiated the connection, whose response will be delivered
|
||||||
*/
|
* on a Stream.
|
||||||
|
*/
|
||||||
Http2Connection(HttpConnection connection,
|
Http2Connection(HttpConnection connection,
|
||||||
Http2ClientImpl client2,
|
Http2ClientImpl client2,
|
||||||
Exchange<?> exchange,
|
Exchange<?> exchange,
|
||||||
@ -280,7 +281,7 @@ class Http2Connection {
|
|||||||
* Throws an IOException if h2 was not negotiated
|
* Throws an IOException if h2 was not negotiated
|
||||||
*/
|
*/
|
||||||
private void checkSSLConfig() throws IOException {
|
private void checkSSLConfig() throws IOException {
|
||||||
AsyncSSLConnection aconn = (AsyncSSLConnection)connection;
|
AbstractAsyncSSLConnection aconn = (AbstractAsyncSSLConnection)connection;
|
||||||
SSLEngine engine = aconn.getEngine();
|
SSLEngine engine = aconn.getEngine();
|
||||||
String alpn = engine.getApplicationProtocol();
|
String alpn = engine.getApplicationProtocol();
|
||||||
if (alpn == null || !alpn.equals("h2")) {
|
if (alpn == null || !alpn.equals("h2")) {
|
||||||
@ -906,14 +907,14 @@ class Http2Connection {
|
|||||||
*/
|
*/
|
||||||
static final class ALPNException extends IOException {
|
static final class ALPNException extends IOException {
|
||||||
private static final long serialVersionUID = 23138275393635783L;
|
private static final long serialVersionUID = 23138275393635783L;
|
||||||
final AsyncSSLConnection connection;
|
final AbstractAsyncSSLConnection connection;
|
||||||
|
|
||||||
ALPNException(String msg, AsyncSSLConnection connection) {
|
ALPNException(String msg, AbstractAsyncSSLConnection connection) {
|
||||||
super(msg);
|
super(msg);
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncSSLConnection getConnection() {
|
AbstractAsyncSSLConnection getConnection() {
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ import java.nio.channels.SocketChannel;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import jdk.incubator.http.internal.common.ByteBufferReference;
|
import jdk.incubator.http.internal.common.ByteBufferReference;
|
||||||
import jdk.incubator.http.internal.common.Utils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps socket channel layer and takes care of SSL also.
|
* 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)
|
String[] alpn, boolean isHttp2, HttpClientImpl client)
|
||||||
{
|
{
|
||||||
if (proxy != null) {
|
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) {
|
} else if (!isHttp2) {
|
||||||
return new SSLConnection(addr, client, alpn);
|
return new SSLConnection(addr, client, alpn);
|
||||||
} else {
|
} else {
|
||||||
|
@ -34,12 +34,15 @@ import java.net.InetSocketAddress;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
import java.util.concurrent.CompletableFuture;
|
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
|
* 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;
|
final PlainHttpConnection delegate;
|
||||||
protected final InetSocketAddress proxyAddr;
|
protected final InetSocketAddress proxyAddr;
|
||||||
@ -116,17 +119,17 @@ class PlainTunnelingConnection extends HttpConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void writeAsync(ByteBufferReference[] buffers) throws IOException {
|
public void writeAsync(ByteBufferReference[] buffers) throws IOException {
|
||||||
delegate.writeAsync(buffers);
|
delegate.writeAsync(buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void writeAsyncUnordered(ByteBufferReference[] buffers) throws IOException {
|
public void writeAsyncUnordered(ByteBufferReference[] buffers) throws IOException {
|
||||||
delegate.writeAsyncUnordered(buffers);
|
delegate.writeAsyncUnordered(buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void flushAsync() throws IOException {
|
public void flushAsync() throws IOException {
|
||||||
delegate.flushAsync();
|
delegate.flushAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,4 +168,32 @@ class PlainTunnelingConnection extends HttpConnection {
|
|||||||
boolean isProxied() {
|
boolean isProxied() {
|
||||||
return true;
|
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) {
|
SSLConnection(AsyncSSLConnection c) {
|
||||||
super(c.address, c.client);
|
super(c.address, c.client);
|
||||||
this.delegate = c.plainConnection;
|
this.delegate = c.plainConnection();
|
||||||
AsyncSSLDelegate adel = c.sslDelegate;
|
AsyncSSLDelegate adel = c.sslDelegate();
|
||||||
this.sslDelegate = new SSLDelegate(adel.engine, delegate.channel(), client, adel.serverName);
|
this.sslDelegate = new SSLDelegate(adel.engine, delegate.channel(), client, adel.serverName);
|
||||||
this.alpn = adel.alpn;
|
this.alpn = adel.alpn;
|
||||||
this.serverName = adel.serverName;
|
this.serverName = adel.serverName;
|
||||||
|
@ -85,6 +85,19 @@ class SSLTunnelConnection extends HttpConnection {
|
|||||||
delegate = new PlainTunnelingConnection(addr, proxy, client);
|
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
|
@Override
|
||||||
SSLParameters sslParameters() {
|
SSLParameters sslParameters() {
|
||||||
return sslDelegate.getSSLParameters();
|
return sslDelegate.getSSLParameters();
|
||||||
|
@ -106,13 +106,24 @@ class ZipUtils {
|
|||||||
* Converts DOS time to Java time (number of milliseconds since epoch).
|
* Converts DOS time to Java time (number of milliseconds since epoch).
|
||||||
*/
|
*/
|
||||||
public static long dosToJavaTime(long dtime) {
|
public static long dosToJavaTime(long dtime) {
|
||||||
LocalDateTime ldt = LocalDateTime.of(
|
int year;
|
||||||
(int) (((dtime >> 25) & 0x7f) + 1980),
|
int month;
|
||||||
(int) ((dtime >> 21) & 0x0f),
|
int day;
|
||||||
(int) ((dtime >> 16) & 0x1f),
|
int hour = (int) ((dtime >> 11) & 0x1f);
|
||||||
(int) ((dtime >> 11) & 0x1f),
|
int minute = (int) ((dtime >> 5) & 0x3f);
|
||||||
(int) ((dtime >> 5) & 0x3f),
|
int second = (int) ((dtime << 1) & 0x3e);
|
||||||
(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(
|
return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond(
|
||||||
ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS);
|
ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
@ -21,17 +21,6 @@
|
|||||||
* questions.
|
* 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 java.applet.Applet;
|
||||||
import sun.net.www.ParseUtil;
|
import sun.net.www.ParseUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#
|
#
|
||||||
# @test IOExceptionIfEncodedURLTest.sh
|
# @test IOExceptionIfEncodedURLTest.sh
|
||||||
# @key headful
|
# @key headful
|
||||||
# @bug 6193279 6619458 8137087
|
# @bug 6193279 6619458 8137087 8186259
|
||||||
# @summary REGRESSION: AppletViewer throws IOException when path is encoded URL
|
# @summary REGRESSION: AppletViewer throws IOException when path is encoded URL
|
||||||
# @author Dmitry Cherepanov: area=appletviewer
|
# @author Dmitry Cherepanov: area=appletviewer
|
||||||
# @modules java.base/sun.net.www
|
# @modules java.base/sun.net.www
|
||||||
|
@ -56,9 +56,12 @@ import jdk.testlibrary.SimpleSSLContext;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @bug 8185852
|
* @bug 8185852 8181422
|
||||||
* @summary verifies that passing a proxy with an unresolved address does
|
* @summary Verifies that passing a proxy with an unresolved address does
|
||||||
* not cause java.nio.channels.UnresolvedAddressException
|
* 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
|
* @modules jdk.incubator.httpclient
|
||||||
* @library /lib/testlibrary/
|
* @library /lib/testlibrary/
|
||||||
* @build jdk.testlibrary.SimpleSSLContext ProxyTest
|
* @build jdk.testlibrary.SimpleSSLContext ProxyTest
|
||||||
@ -111,7 +114,7 @@ public class ProxyTest {
|
|||||||
server.start();
|
server.start();
|
||||||
try {
|
try {
|
||||||
test(server, HttpClient.Version.HTTP_1_1);
|
test(server, HttpClient.Version.HTTP_1_1);
|
||||||
// test(server, HttpClient.Version.HTTP_2);
|
test(server, HttpClient.Version.HTTP_2);
|
||||||
} finally {
|
} finally {
|
||||||
server.stop(0);
|
server.stop(0);
|
||||||
System.out.println("Server stopped");
|
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();
|
InetSocketAddress addr = (InetSocketAddress) socket.getRemoteSocketAddress();
|
||||||
Http2TestServerConnection c = new Http2TestServerConnection(this, socket);
|
Http2TestServerConnection c = new Http2TestServerConnection(this, socket);
|
||||||
connections.put(addr, c);
|
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) {
|
} catch (Throwable e) {
|
||||||
if (!stopping) {
|
if (!stopping) {
|
||||||
|
@ -133,10 +133,10 @@ public class Http2TestServerConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void close() {
|
||||||
|
stopping = true;
|
||||||
streams.forEach((i, q) -> {
|
streams.forEach((i, q) -> {
|
||||||
q.close();
|
q.close();
|
||||||
});
|
});
|
||||||
stopping = true;
|
|
||||||
try {
|
try {
|
||||||
socket.close();
|
socket.close();
|
||||||
// TODO: put a reset on each stream
|
// TODO: put a reset on each stream
|
||||||
@ -557,7 +557,14 @@ public class Http2TestServerConnection {
|
|||||||
void writeLoop() {
|
void writeLoop() {
|
||||||
try {
|
try {
|
||||||
while (!stopping) {
|
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) {
|
if (frame instanceof ResponseHeaders) {
|
||||||
ResponseHeaders rh = (ResponseHeaders)frame;
|
ResponseHeaders rh = (ResponseHeaders)frame;
|
||||||
HeadersFrame hf = new HeadersFrame(rh.streamid(), rh.getFlags(), encodeHeaders(rh.headers));
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -55,6 +55,9 @@ public class SmallPrimeExponentP {
|
|||||||
CertAndKeyGen ckg = new CertAndKeyGen("RSA", "SHA1withRSA");
|
CertAndKeyGen ckg = new CertAndKeyGen("RSA", "SHA1withRSA");
|
||||||
ckg.setRandom(new MySecureRandom(seed));
|
ckg.setRandom(new MySecureRandom(seed));
|
||||||
|
|
||||||
|
String alias = "anything";
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
boolean see63 = false;
|
boolean see63 = false;
|
||||||
boolean see65 = false;
|
boolean see65 = false;
|
||||||
while (!see63 || !see65) {
|
while (!see63 || !see65) {
|
||||||
@ -78,12 +81,19 @@ public class SmallPrimeExponentP {
|
|||||||
see65 = true;
|
see65 = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ks.setKeyEntry("anything", k, null, new X509Certificate[]{
|
ks.setKeyEntry(alias, k, null, new X509Certificate[]{
|
||||||
ckg.getSelfCertificate(new X500Name("CN=Me"), 1000)
|
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 {
|
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