Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
b80ffe55
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
b80ffe55
编写于
10月 18, 2012
作者:
X
xuelei
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
7068321: Support TLS Server Name Indication (SNI) Extension in JSSE Server
Reviewed-by: mullan, weijun, wetmore
上级
b1886967
变更
46
隐藏空白更改
内联
并排
Showing
46 changed file
with
8171 addition
and
290 deletion
+8171
-290
src/share/classes/javax/net/ssl/ExtendedSSLSession.java
src/share/classes/javax/net/ssl/ExtendedSSLSession.java
+32
-0
src/share/classes/javax/net/ssl/HandshakeCompletedEvent.java
src/share/classes/javax/net/ssl/HandshakeCompletedEvent.java
+3
-4
src/share/classes/javax/net/ssl/SNIHostName.java
src/share/classes/javax/net/ssl/SNIHostName.java
+394
-0
src/share/classes/javax/net/ssl/SNIMatcher.java
src/share/classes/javax/net/ssl/SNIMatcher.java
+105
-0
src/share/classes/javax/net/ssl/SNIServerName.java
src/share/classes/javax/net/ssl/SNIServerName.java
+213
-0
src/share/classes/javax/net/ssl/SSLEngine.java
src/share/classes/javax/net/ssl/SSLEngine.java
+14
-10
src/share/classes/javax/net/ssl/SSLParameters.java
src/share/classes/javax/net/ssl/SSLParameters.java
+187
-4
src/share/classes/javax/net/ssl/SSLServerSocket.java
src/share/classes/javax/net/ssl/SSLServerSocket.java
+14
-10
src/share/classes/javax/net/ssl/SSLSocket.java
src/share/classes/javax/net/ssl/SSLSocket.java
+14
-10
src/share/classes/javax/net/ssl/SSLSocketFactory.java
src/share/classes/javax/net/ssl/SSLSocketFactory.java
+51
-3
src/share/classes/javax/net/ssl/StandardConstants.java
src/share/classes/javax/net/ssl/StandardConstants.java
+56
-0
src/share/classes/sun/security/ssl/BaseSSLSocketImpl.java
src/share/classes/sun/security/ssl/BaseSSLSocketImpl.java
+64
-3
src/share/classes/sun/security/ssl/ClientHandshaker.java
src/share/classes/sun/security/ssl/ClientHandshaker.java
+12
-13
src/share/classes/sun/security/ssl/HandshakeInStream.java
src/share/classes/sun/security/ssl/HandshakeInStream.java
+3
-2
src/share/classes/sun/security/ssl/HandshakeMessage.java
src/share/classes/sun/security/ssl/HandshakeMessage.java
+2
-6
src/share/classes/sun/security/ssl/Handshaker.java
src/share/classes/sun/security/ssl/Handshaker.java
+25
-9
src/share/classes/sun/security/ssl/HelloExtensions.java
src/share/classes/sun/security/ssl/HelloExtensions.java
+157
-76
src/share/classes/sun/security/ssl/ProtocolList.java
src/share/classes/sun/security/ssl/ProtocolList.java
+2
-2
src/share/classes/sun/security/ssl/SSLEngineImpl.java
src/share/classes/sun/security/ssl/SSLEngineImpl.java
+49
-21
src/share/classes/sun/security/ssl/SSLServerSocketImpl.java
src/share/classes/sun/security/ssl/SSLServerSocketImpl.java
+12
-1
src/share/classes/sun/security/ssl/SSLSessionImpl.java
src/share/classes/sun/security/ssl/SSLSessionImpl.java
+27
-1
src/share/classes/sun/security/ssl/SSLSocketFactoryImpl.java
src/share/classes/sun/security/ssl/SSLSocketFactoryImpl.java
+10
-0
src/share/classes/sun/security/ssl/SSLSocketImpl.java
src/share/classes/sun/security/ssl/SSLSocketImpl.java
+100
-74
src/share/classes/sun/security/ssl/ServerHandshaker.java
src/share/classes/sun/security/ssl/ServerHandshaker.java
+49
-0
src/share/classes/sun/security/ssl/SunJSSE.java
src/share/classes/sun/security/ssl/SunJSSE.java
+2
-2
src/share/classes/sun/security/ssl/Utilities.java
src/share/classes/sun/security/ssl/Utilities.java
+115
-0
src/share/classes/sun/security/ssl/X509KeyManagerImpl.java
src/share/classes/sun/security/ssl/X509KeyManagerImpl.java
+96
-16
src/share/classes/sun/security/ssl/X509TrustManagerImpl.java
src/share/classes/sun/security/ssl/X509TrustManagerImpl.java
+117
-7
test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/LargePacket.java
...rity/ssl/javax/net/ssl/NewAPIs/SSLEngine/LargePacket.java
+12
-5
test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/SSLEngineService.java
...ssl/javax/net/ssl/NewAPIs/SSLEngine/SSLEngineService.java
+56
-11
test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorer.java
...urity/ssl/javax/net/ssl/ServerName/SSLEngineExplorer.java
+335
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java
...javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java
+393
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java
...vax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java
+406
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java
...sl/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java
+365
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java
...sl/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java
+351
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketConsistentSNI.java
.../ssl/javax/net/ssl/ServerName/SSLSocketConsistentSNI.java
+357
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorer.java
...urity/ssl/javax/net/ssl/ServerName/SSLSocketExplorer.java
+375
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java
...sl/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java
+383
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java
...javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java
+435
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java
...vax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java
+392
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java
...javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java
+407
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java
...javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java
+390
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketInconsistentSNI.java
...sl/javax/net/ssl/ServerName/SSLSocketInconsistentSNI.java
+340
-0
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketSNISensitive.java
...y/ssl/javax/net/ssl/ServerName/SSLSocketSNISensitive.java
+564
-0
test/sun/security/ssl/templates/SSLCapabilities.java
test/sun/security/ssl/templates/SSLCapabilities.java
+70
-0
test/sun/security/ssl/templates/SSLExplorer.java
test/sun/security/ssl/templates/SSLExplorer.java
+615
-0
未找到文件。
src/share/classes/javax/net/ssl/ExtendedSSLSession.java
浏览文件 @
b80ffe55
...
...
@@ -25,6 +25,8 @@
package
javax.net.ssl
;
import
java.util.List
;
/**
* Extends the <code>SSLSession</code> interface to support additional
* session attributes.
...
...
@@ -83,4 +85,34 @@ public abstract class ExtendedSSLSession implements SSLSession {
* @see X509ExtendedKeyManager
*/
public
abstract
String
[]
getPeerSupportedSignatureAlgorithms
();
/**
* Obtains a {@link List} containing all {@link SNIServerName}s
* of the requested Server Name Indication (SNI) extension.
* <P>
* In server mode, unless the return {@link List} is empty,
* the server should use the requested server names to guide its
* selection of an appropriate authentication certificate, and/or
* other aspects of security policy.
* <P>
* In client mode, unless the return {@link List} is empty,
* the client should use the requested server names to guide its
* endpoint identification of the peer's identity, and/or
* other aspects of security policy.
*
* @return a non-null immutable list of {@link SNIServerName}s of the
* requested server name indications. The returned list may be
* empty if no server name indications were requested.
* @throws UnsupportedOperationException if the underlying provider
* does not implement the operation
*
* @see SNIServerName
* @see X509ExtendedTrustManager
* @see X509ExtendedKeyManager
*
* @since 1.8
*/
public
List
<
SNIServerName
>
getRequestedServerNames
()
{
throw
new
UnsupportedOperationException
();
}
}
src/share/classes/javax/net/ssl/HandshakeCompletedEvent.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 1997, 20
03
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 20
12
, 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
...
...
@@ -186,8 +186,7 @@ public class HandshakeCompletedEvent extends EventObject
// if the provider does not support it, fallback to peer certs.
// return the X500Principal of the end-entity cert.
Certificate
[]
certs
=
getPeerCertificates
();
principal
=
(
X500Principal
)
((
X509Certificate
)
certs
[
0
]).
getSubjectX500Principal
();
principal
=
((
X509Certificate
)
certs
[
0
]).
getSubjectX500Principal
();
}
return
principal
;
}
...
...
@@ -216,7 +215,7 @@ public class HandshakeCompletedEvent extends EventObject
// return the X500Principal of the end-entity cert.
Certificate
[]
certs
=
getLocalCertificates
();
if
(
certs
!=
null
)
{
principal
=
(
X500Principal
)
principal
=
((
X509Certificate
)
certs
[
0
]).
getSubjectX500Principal
();
}
}
...
...
src/share/classes/javax/net/ssl/SNIHostName.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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
javax.net.ssl
;
import
java.net.IDN
;
import
java.nio.ByteBuffer
;
import
java.nio.charset.CodingErrorAction
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.charset.CharsetDecoder
;
import
java.nio.charset.CharacterCodingException
;
import
java.util.Locale
;
import
java.util.Objects
;
import
java.util.regex.Pattern
;
/**
* Instances of this class represent a server name of type
* {@link StandardConstants#SNI_HOST_NAME host_name} in a Server Name
* Indication (SNI) extension.
* <P>
* As described in section 3, "Server Name Indication", of
* <A HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions (RFC 6066)</A>,
* "HostName" contains the fully qualified DNS hostname of the server, as
* understood by the client. The encoded server name value of a hostname is
* represented as a byte string using ASCII encoding without a trailing dot.
* This allows the support of Internationalized Domain Names (IDN) through
* the use of A-labels (the ASCII-Compatible Encoding (ACE) form of a valid
* string of Internationalized Domain Names for Applications (IDNA)) defined
* in <A HREF="http://www.ietf.org/rfc/rfc5890.txt">RFC 5890</A>.
* <P>
* Note that {@code SNIHostName} objects are immutable.
*
* @see SNIServerName
* @see StandardConstants#SNI_HOST_NAME
*
* @since 1.8
*/
public
final
class
SNIHostName
extends
SNIServerName
{
// the decoded string value of the server name
private
final
String
hostname
;
/**
* Creates an {@code SNIHostName} using the specified hostname.
* <P>
* Note that per <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>,
* the encoded server name value of a hostname is
* {@link StandardCharsets#US_ASCII}-compliant. In this method,
* {@code hostname} can be a user-friendly Internationalized Domain Name
* (IDN). {@link IDN#toASCII(String, int)} is used to enforce the
* restrictions on ASCII characters in hostnames (see
* <A HREF="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</A>,
* <A HREF="http://www.ietf.org/rfc/rfc1122.txt">RFC 1122</A>,
* <A HREF="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</A>) and
* translate the {@code hostname} into ASCII Compatible Encoding (ACE), as:
* <pre>
* IDN.toASCII(hostname, IDN.USE_STD3_ASCII_RULES);
* </pre>
* <P>
* The {@code hostname} argument is illegal if it:
* <ul>
* <li> {@code hostname} is empty,</li>
* <li> {@code hostname} ends with a trailing dot,</li>
* <li> {@code hostname} is not a valid Internationalized
* Domain Name (IDN) compliant with the RFC 3490 specification.</li>
* </ul>
* @param hostname
* the hostname of this server name
*
* @throws NullPointerException if {@code hostname} is {@code null}
* @throws IllegalArgumentException if {@code hostname} is illegal
*/
public
SNIHostName
(
String
hostname
)
{
// IllegalArgumentException will be thrown if {@code hostname} is
// not a valid IDN.
super
(
StandardConstants
.
SNI_HOST_NAME
,
(
hostname
=
IDN
.
toASCII
(
Objects
.
requireNonNull
(
hostname
,
"Server name value of host_name cannot be null"
),
IDN
.
USE_STD3_ASCII_RULES
))
.
getBytes
(
StandardCharsets
.
US_ASCII
));
this
.
hostname
=
hostname
;
// check the validity of the string hostname
checkHostName
();
}
/**
* Creates an {@code SNIHostName} using the specified encoded value.
* <P>
* This method is normally used to parse the encoded name value in a
* requested SNI extension.
* <P>
* Per <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>,
* the encoded name value of a hostname is
* {@link StandardCharsets#US_ASCII}-compliant. However, in the previous
* version of the SNI extension (
* <A HREF="http://www.ietf.org/rfc/rfc4366.txt">RFC 4366</A>),
* the encoded hostname is represented as a byte string using UTF-8
* encoding. For the purpose of version tolerance, this method allows
* that the charset of {@code encoded} argument can be
* {@link StandardCharsets#UTF_8}, as well as
* {@link StandardCharsets#US_ASCII}. {@link IDN#toASCII(String)} is used
* to translate the {@code encoded} argument into ASCII Compatible
* Encoding (ACE) hostname.
* <P>
* It is strongly recommended that this constructor is only used to parse
* the encoded name value in a requested SNI extension. Otherwise, to
* comply with <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>,
* please always use {@link StandardCharsets#US_ASCII}-compliant charset
* and enforce the restrictions on ASCII characters in hostnames (see
* <A HREF="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</A>,
* <A HREF="http://www.ietf.org/rfc/rfc1122.txt">RFC 1122</A>,
* <A HREF="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</A>)
* for {@code encoded} argument, or use {@link SNIHostName(String)} instead.
* <P>
* The {@code encoded} argument is illegal if it:
* <ul>
* <li> {@code encoded} is empty,</li>
* <li> {@code encoded} ends with a trailing dot,</li>
* <li> {@code encoded} is not encoded in
* {@link StandardCharsets#US_ASCII} or
* {@link StandardCharsets#UTF_8}-compliant charset,</li>
* <li> {@code encoded} is not a valid Internationalized
* Domain Name (IDN) compliant with the RFC 3490 specification.</li>
* </ul>
*
* <P>
* Note that the {@code encoded} byte array is cloned
* to protect against subsequent modification.
*
* @param encoded
* the encoded hostname of this server name
*
* @throws NullPointerException if {@code encoded} is {@code null}
* @throws IllegalArgumentException if {@code encoded} is illegal
*/
public
SNIHostName
(
byte
[]
encoded
)
{
// NullPointerException will be thrown if {@code encoded} is null
super
(
StandardConstants
.
SNI_HOST_NAME
,
encoded
);
// Compliance: RFC 4366 requires that the hostname is represented
// as a byte string using UTF_8 encoding [UTF8]
try
{
// Please don't use {@link String} constructors because they
// do not report coding errors.
CharsetDecoder
decoder
=
StandardCharsets
.
UTF_8
.
newDecoder
()
.
onMalformedInput
(
CodingErrorAction
.
REPORT
)
.
onUnmappableCharacter
(
CodingErrorAction
.
REPORT
);
this
.
hostname
=
IDN
.
toASCII
(
decoder
.
decode
(
ByteBuffer
.
wrap
(
encoded
)).
toString
());
}
catch
(
RuntimeException
|
CharacterCodingException
e
)
{
throw
new
IllegalArgumentException
(
"The encoded server name value is invalid"
,
e
);
}
// check the validity of the string hostname
checkHostName
();
}
/**
* Returns the {@link StandardCharsets#US_ASCII}-compliant hostname of
* this {@code SNIHostName} object.
* <P>
* Note that, per
* <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>, the
* returned hostname may be an internationalized domain name that
* contains A-labels. See
* <A HREF="http://www.ietf.org/rfc/rfc5890.txt">RFC 5890</A>
* for more information about the detailed A-label specification.
*
* @return the {@link StandardCharsets#US_ASCII}-compliant hostname
* of this {@code SNIHostName} object
*/
public
String
getAsciiName
()
{
return
hostname
;
}
/**
* Compares this server name to the specified object.
* <P>
* Per <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>, DNS
* hostnames are case-insensitive. Two server hostnames are equal if,
* and only if, they have the same name type, and the hostnames are
* equal in a case-independent comparison.
*
* @param other
* the other server name object to compare with.
* @return true if, and only if, the {@code other} is considered
* equal to this instance
*/
@Override
public
boolean
equals
(
Object
other
)
{
if
(
this
==
other
)
{
return
true
;
}
if
(
other
instanceof
SNIHostName
)
{
return
hostname
.
equalsIgnoreCase
(((
SNIHostName
)
other
).
hostname
);
}
return
false
;
}
/**
* Returns a hash code value for this {@code SNIHostName}.
* <P>
* The hash code value is generated using the case-insensitive hostname
* of this {@code SNIHostName}.
*
* @return a hash code value for this {@code SNIHostName}.
*/
@Override
public
int
hashCode
()
{
int
result
=
17
;
// 17/31: prime number to decrease collisions
result
=
31
*
result
+
hostname
.
toUpperCase
(
Locale
.
ENGLISH
).
hashCode
();
return
result
;
}
/**
* Returns a string representation of the object, including the DNS
* hostname in this {@code SNIHostName} object.
* <P>
* The exact details of the representation are unspecified and subject
* to change, but the following may be regarded as typical:
* <pre>
* "type=host_name (0), value={@literal <hostname>}"
* </pre>
* The "{@literal <hostname>}" is an ASCII representation of the hostname,
* which may contains A-labels. For example, a returned value of an pseudo
* hostname may look like:
* <pre>
* "type=host_name (0), value=www.example.com"
* </pre>
* or
* <pre>
* "type=host_name (0), value=xn--fsqu00a.xn--0zwm56d"
* </pre>
* <P>
* Please NOTE that the exact details of the representation are unspecified
* and subject to change.
*
* @return a string representation of the object.
*/
@Override
public
String
toString
()
{
return
"type=host_name (0), value="
+
hostname
;
}
/**
* Creates an {@link SNIMatcher} object for {@code SNIHostName}s.
* <P>
* This method can be used by a server to verify the acceptable
* {@code SNIHostName}s. For example,
* <pre>
* SNIMatcher matcher =
* SNIHostName.createSNIMatcher("www\\.example\\.com");
* </pre>
* will accept the hostname "www.example.com".
* <pre>
* SNIMatcher matcher =
* SNIHostName.createSNIMatcher("www\\.example\\.(com|org)");
* </pre>
* will accept hostnames "www.example.com" and "www.example.org".
*
* @param regex
* the <a href="{@docRoot}/java/util/regex/Pattern.html#sum">
* regular expression pattern</a>
* representing the hostname(s) to match
* @throws NullPointerException if {@code regex} is
* {@code null}
* @throws PatternSyntaxException if the regular expression's syntax
* is invalid
*/
public
static
SNIMatcher
createSNIMatcher
(
String
regex
)
{
if
(
regex
==
null
)
{
throw
new
NullPointerException
(
"The regular expression cannot be null"
);
}
return
new
SNIHostNameMatcher
(
regex
);
}
// check the validity of the string hostname
private
void
checkHostName
()
{
if
(
hostname
.
isEmpty
())
{
throw
new
IllegalArgumentException
(
"Server name value of host_name cannot be empty"
);
}
if
(
hostname
.
endsWith
(
"."
))
{
throw
new
IllegalArgumentException
(
"Server name value of host_name cannot have the trailing dot"
);
}
}
private
final
static
class
SNIHostNameMatcher
extends
SNIMatcher
{
// the compiled representation of a regular expression.
private
final
Pattern
pattern
;
/**
* Creates an SNIHostNameMatcher object.
*
* @param regex
* the <a href="{@docRoot}/java/util/regex/Pattern.html#sum">
* regular expression pattern</a>
* representing the hostname(s) to match
* @throws NullPointerException if {@code regex} is
* {@code null}
* @throws PatternSyntaxException if the regular expression's syntax
* is invalid
*/
SNIHostNameMatcher
(
String
regex
)
{
super
(
StandardConstants
.
SNI_HOST_NAME
);
pattern
=
Pattern
.
compile
(
regex
,
Pattern
.
CASE_INSENSITIVE
);
}
/**
* Attempts to match the given {@link SNIServerName}.
*
* @param serverName
* the {@link SNIServerName} instance on which this matcher
* performs match operations
*
* @return {@code true} if, and only if, the matcher matches the
* given {@code serverName}
*
* @throws NullPointerException if {@code serverName} is {@code null}
* @throws IllegalArgumentException if {@code serverName} is
* not of {@code StandardConstants#SNI_HOST_NAME} type
*
* @see SNIServerName
*/
@Override
public
boolean
matches
(
SNIServerName
serverName
)
{
if
(
serverName
==
null
)
{
throw
new
NullPointerException
(
"The SNIServerName argument cannot be null"
);
}
SNIHostName
hostname
;
if
(!(
serverName
instanceof
SNIHostName
))
{
if
(
serverName
.
getType
()
!=
StandardConstants
.
SNI_HOST_NAME
)
{
throw
new
IllegalArgumentException
(
"The server name type is not host_name"
);
}
try
{
hostname
=
new
SNIHostName
(
serverName
.
getEncoded
());
}
catch
(
NullPointerException
|
IllegalArgumentException
e
)
{
return
false
;
}
}
else
{
hostname
=
(
SNIHostName
)
serverName
;
}
// Let's first try the ascii name matching
String
asciiName
=
hostname
.
getAsciiName
();
if
(
pattern
.
matcher
(
asciiName
).
matches
())
{
return
true
;
}
// May be an internationalized domain name, check the Unicode
// representations.
return
pattern
.
matcher
(
IDN
.
toUnicode
(
asciiName
)).
matches
();
}
}
}
src/share/classes/javax/net/ssl/SNIMatcher.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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
javax.net.ssl
;
/**
* Instances of this class represent a matcher that performs match
* operations on an {@link SNIServerName} instance.
* <P>
* Servers can use Server Name Indication (SNI) information to decide if
* specific {@link SSLSocket} or {@link SSLEngine} instances should accept
* a connection. For example, when multiple "virtual" or "name-based"
* servers are hosted on a single underlying network address, the server
* application can use SNI information to determine whether this server is
* the exact server that the client wants to access. Instances of this
* class can be used by a server to verify the acceptable server names of
* a particular type, such as host names.
* <P>
* {@code SNIMatcher} objects are immutable. Subclasses should not provide
* methods that can change the state of an instance once it has been created.
*
* @see SNIServerName
* @see SNIHostName
* @see SSLParameters#getSNIMatchers()
* @see SSLParameters#setSNIMatchers(Collection<SNIMatcher>)
*
* @since 1.8
*/
public
abstract
class
SNIMatcher
{
// the type of the server name that this matcher performs on
private
final
int
type
;
/**
* Creates an {@code SNIMatcher} using the specified server name type.
*
* @param type
* the type of the server name that this matcher performs on
*
* @throws IllegalArgumentException if {@code type} is not in the range
* of 0 to 255, inclusive.
*/
protected
SNIMatcher
(
int
type
)
{
if
(
type
<
0
)
{
throw
new
IllegalArgumentException
(
"Server name type cannot be less than zero"
);
}
else
if
(
type
>
255
)
{
throw
new
IllegalArgumentException
(
"Server name type cannot be greater than 255"
);
}
this
.
type
=
type
;
}
/**
* Returns the server name type of this {@code SNIMatcher} object.
*
* @return the server name type of this {@code SNIMatcher} object.
*
* @see SNIServerName
*/
public
final
int
getType
()
{
return
type
;
}
/**
* Attempts to match the given {@link SNIServerName}.
*
* @param serverName
* the {@link SNIServerName} instance on which this matcher
* performs match operations
*
* @return {@code true} if, and only if, the matcher matches the
* given {@code serverName}
*
* @throws NullPointerException if {@code serverName} is {@code null}
* @throws IllegalArgumentException if {@code serverName} is
* not of the given server name type of this matcher
*
* @see SNIServerName
*/
public
abstract
boolean
matches
(
SNIServerName
serverName
);
}
src/share/classes/javax/net/ssl/SNIServerName.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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
javax.net.ssl
;
import
java.util.Arrays
;
/**
* Instances of this class represent a server name in a Server Name
* Indication (SNI) extension.
* <P>
* The SNI extension is a feature that extends the SSL/TLS protocols to
* indicate what server name the client is attempting to connect to during
* handshaking. See section 3, "Server Name Indication", of <A
* HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions (RFC 6066)</A>.
* <P>
* {@code SNIServerName} objects are immutable. Subclasses should not provide
* methods that can change the state of an instance once it has been created.
*
* @see SSLParameters#getServerNames()
* @see SSLParameters#setServerNames(List<SNIServerName>)
*
* @since 1.8
*/
public
abstract
class
SNIServerName
{
// the type of the server name
private
final
int
type
;
// the encoded value of the server name
private
final
byte
[]
encoded
;
// the hex digitals
private
static
final
char
[]
HEXES
=
"0123456789ABCDEF"
.
toCharArray
();
/**
* Creates an {@code SNIServerName} using the specified name type and
* encoded value.
* <P>
* Note that the {@code encoded} byte array is cloned to protect against
* subsequent modification.
*
* @param type
* the type of the server name
* @param encoded
* the encoded value of the server name
*
* @throws IllegalArgumentException if {@code type} is not in the range
* of 0 to 255, inclusive.
* @throws NullPointerException if {@code encoded} is null
*/
protected
SNIServerName
(
int
type
,
byte
[]
encoded
)
{
if
(
type
<
0
)
{
throw
new
IllegalArgumentException
(
"Server name type cannot be less than zero"
);
}
else
if
(
type
>
255
)
{
throw
new
IllegalArgumentException
(
"Server name type cannot be greater than 255"
);
}
this
.
type
=
type
;
if
(
encoded
==
null
)
{
throw
new
NullPointerException
(
"Server name encoded value cannot be null"
);
}
this
.
encoded
=
encoded
.
clone
();
}
/**
* Returns the name type of this server name.
*
* @return the name type of this server name
*/
public
final
int
getType
()
{
return
type
;
}
/**
* Returns a copy of the encoded server name value of this server name.
*
* @return a copy of the encoded server name value of this server name
*/
public
final
byte
[]
getEncoded
()
{
return
encoded
.
clone
();
}
/**
* Indicates whether some other object is "equal to" this server name.
*
* @return true if, and only if, {@code other} is of the same class
* of this object, and has the same name type and
* encoded value as this server name.
*/
@Override
public
boolean
equals
(
Object
other
)
{
if
(
this
==
other
)
{
return
true
;
}
if
(
this
.
getClass
()
!=
other
.
getClass
())
{
return
false
;
}
SNIServerName
that
=
(
SNIServerName
)
other
;
return
(
this
.
type
==
that
.
type
)
&&
Arrays
.
equals
(
this
.
encoded
,
that
.
encoded
);
}
/**
* Returns a hash code value for this server name.
* <P>
* The hash code value is generated using the name type and encoded
* value of this server name.
*
* @return a hash code value for this server name.
*/
@Override
public
int
hashCode
()
{
int
result
=
17
;
// 17/31: prime number to decrease collisions
result
=
31
*
result
+
type
;
result
=
31
*
result
+
Arrays
.
hashCode
(
encoded
);
return
result
;
}
/**
* Returns a string representation of this server name, including the server
* name type and the encoded server name value in this
* {@code SNIServerName} object.
* <P>
* The exact details of the representation are unspecified and subject
* to change, but the following may be regarded as typical:
* <pre>
* "type={@literal <name type>}, value={@literal <name value>}"
* </pre>
* <P>
* In this class, the format of "{@literal <name type>}" is
* "[LITERAL] (INTEGER)", where the optional "LITERAL" is the literal
* name, and INTEGER is the integer value of the name type. The format
* of "{@literal <name value>}" is "XX:...:XX", where "XX" is the
* hexadecimal digit representation of a byte value. For example, a
* returned value of an pseudo server name may look like:
* <pre>
* "type=(31), value=77:77:77:2E:65:78:61:6D:70:6C:65:2E:63:6E"
* </pre>
* or
* <pre>
* "type=host_name (0), value=77:77:77:2E:65:78:61:6D:70:6C:65:2E:63:6E"
* </pre>
*
* <P>
* Please NOTE that the exact details of the representation are unspecified
* and subject to change, and subclasses may override the method with
* their own formats.
*
* @return a string representation of this server name
*/
@Override
public
String
toString
()
{
if
(
type
==
StandardConstants
.
SNI_HOST_NAME
)
{
return
"type=host_name (0), value="
+
toHexString
(
encoded
);
}
else
{
return
"type=("
+
type
+
"), value="
+
toHexString
(
encoded
);
}
}
// convert byte array to hex string
private
static
String
toHexString
(
byte
[]
bytes
)
{
if
(
bytes
.
length
==
0
)
{
return
"(empty)"
;
}
StringBuilder
sb
=
new
StringBuilder
(
bytes
.
length
*
3
-
1
);
boolean
isInitial
=
true
;
for
(
byte
b
:
bytes
)
{
if
(
isInitial
)
{
isInitial
=
false
;
}
else
{
sb
.
append
(
':'
);
}
int
k
=
b
&
0xFF
;
sb
.
append
(
HEXES
[
k
>>>
4
]);
sb
.
append
(
HEXES
[
k
&
0xF
]);
}
return
sb
.
toString
();
}
}
src/share/classes/javax/net/ssl/SSLEngine.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 2003, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 201
2
, 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
...
...
@@ -1214,15 +1214,19 @@ public abstract class SSLEngine {
*
* <p>This means:
* <ul>
* <li>if <code>params.getCipherSuites()</code> is non-null,
* <code>setEnabledCipherSuites()</code> is called with that value
* <li>if <code>params.getProtocols()</code> is non-null,
* <code>setEnabledProtocols()</code> is called with that value
* <li>if <code>params.getNeedClientAuth()</code> or
* <code>params.getWantClientAuth()</code> return <code>true</code>,
* <code>setNeedClientAuth(true)</code> and
* <code>setWantClientAuth(true)</code> are called, respectively;
* otherwise <code>setWantClientAuth(false)</code> is called.
* <li>If {@code params.getCipherSuites()} is non-null,
* {@code setEnabledCipherSuites()} is called with that value.</li>
* <li>If {@code params.getProtocols()} is non-null,
* {@code setEnabledProtocols()} is called with that value.</li>
* <li>If {@code params.getNeedClientAuth()} or
* {@code params.getWantClientAuth()} return {@code true},
* {@code setNeedClientAuth(true)} and
* {@code setWantClientAuth(true)} are called, respectively;
* otherwise {@code setWantClientAuth(false)} is called.</li>
* <li>If {@code params.getServerNames()} is non-null, the engine will
* configure its server names with that value.</li>
* <li>If {@code params.getSNIMatchers()} is non-null, the engine will
* configure its SNI matchers with that value.</li>
* </ul>
*
* @param params the parameters
...
...
src/share/classes/javax/net/ssl/SSLParameters.java
浏览文件 @
b80ffe55
...
...
@@ -26,13 +26,23 @@
package
javax.net.ssl
;
import
java.security.AlgorithmConstraints
;
import
java.util.Map
;
import
java.util.List
;
import
java.util.HashSet
;
import
java.util.HashMap
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.LinkedHashMap
;
import
java.util.regex.Pattern
;
/**
* Encapsulates parameters for an SSL/TLS connection. The parameters
* are the list of ciphersuites to be accepted in an SSL/TLS handshake,
* the list of protocols to be allowed, the endpoint identification
* algorithm during SSL/TLS handshaking, the algorithm constraints and
* whether SSL/TLS servers should request or require client authentication.
* algorithm during SSL/TLS handshaking, the Server Name Indication (SNI),
* the algorithm constraints and whether SSL/TLS servers should request
* or require client authentication.
* <p>
* SSLParameters can be created via the constructors in this class.
* Objects can also be obtained using the <code>getSSLParameters()</code>
...
...
@@ -47,7 +57,7 @@ import java.security.AlgorithmConstraints;
* SSLParameters can be applied to a connection via the methods
* {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and
* {@link SSLServerSocket#setSSLParameters SSLServerSocket.setSSLParameters()}
* and {@link SSLEngine#setSSLParameters SSLEngine.
g
etSSLParameters()}.
* and {@link SSLEngine#setSSLParameters SSLEngine.
s
etSSLParameters()}.
*
* @see SSLSocket
* @see SSLEngine
...
...
@@ -63,11 +73,15 @@ public class SSLParameters {
private
boolean
needClientAuth
;
private
String
identificationAlgorithm
;
private
AlgorithmConstraints
algorithmConstraints
;
private
Map
<
Integer
,
SNIServerName
>
sniNames
=
null
;
private
Map
<
Integer
,
SNIMatcher
>
sniMatchers
=
null
;
/**
* Constructs SSLParameters.
* <p>
* The cipherSuites and protocols values are set to <code>null</code>,
* The values of cipherSuites, protocols, cryptographic algorithm
* constraints, endpoint identification algorithm, server names and
* server name matchers are set to <code>null</code>,
* wantClientAuth and needClientAuth are set to <code>false</code>.
*/
public
SSLParameters
()
{
...
...
@@ -254,4 +268,173 @@ public class SSLParameters {
this
.
identificationAlgorithm
=
algorithm
;
}
/**
* Sets the desired {@link SNIServerName}s of the Server Name
* Indication (SNI) parameter.
* <P>
* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
* operating in client mode.
* <P>
* Note that the {@code serverNames} list is cloned
* to protect against subsequent modification.
*
* @param serverNames
* the list of desired {@link SNIServerName}s (or null)
*
* @throws NullPointerException if the {@code serverNames}
* contains {@code null} element
* @throws IllegalArgumentException if the {@code serverNames}
* contains more than one name of the same name type
*
* @see SNIServerName
* @see #getServerNames()
*
* @since 1.8
*/
public
void
setServerNames
(
List
<
SNIServerName
>
serverNames
)
{
if
(
serverNames
!=
null
)
{
if
(!
serverNames
.
isEmpty
())
{
sniNames
=
new
LinkedHashMap
<>(
serverNames
.
size
());
for
(
SNIServerName
serverName
:
serverNames
)
{
if
(
sniNames
.
put
(
serverName
.
getType
(),
serverName
)
!=
null
)
{
throw
new
IllegalArgumentException
(
"Duplicated server name of type "
+
serverName
.
getType
());
}
}
}
else
{
sniNames
=
Collections
.<
Integer
,
SNIServerName
>
emptyMap
();
}
}
else
{
sniNames
=
null
;
}
}
/**
* Returns a {@link List} containing all {@link SNIServerName}s of the
* Server Name Indication (SNI) parameter, or null if none has been set.
* <P>
* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
* operating in client mode.
* <P>
* For SSL/TLS connections, the underlying SSL/TLS provider
* may specify a default value for a certain server name type. In
* client mode, it is recommended that, by default, providers should
* include the server name indication whenever the server can be located
* by a supported server name type.
* <P>
* It is recommended that providers initialize default Server Name
* Indications when creating {@code SSLSocket}/{@code SSLEngine}s.
* In the following examples, the server name could be represented by an
* instance of {@link SNIHostName} which has been initialized with the
* hostname "www.example.com" and type
* {@link StandardConstants#SNI_HOST_NAME}.
*
* <pre>
* Socket socket =
* sslSocketFactory.createSocket("www.example.com", 443);
* </pre>
* or
* <pre>
* SSLEngine engine =
* sslContext.createSSLEngine("www.example.com", 443);
* </pre>
* <P>
*
* @return null or an immutable list of non-null {@link SNIServerName}s
*
* @see List
* @see #setServerNames(List<SNIServerName>)
*
* @since 1.8
*/
public
List
<
SNIServerName
>
getServerNames
()
{
if
(
sniNames
!=
null
)
{
if
(!
sniNames
.
isEmpty
())
{
return
Collections
.<
SNIServerName
>
unmodifiableList
(
new
ArrayList
<>(
sniNames
.
values
()));
}
else
{
return
Collections
.<
SNIServerName
>
emptyList
();
}
}
return
null
;
}
/**
* Sets the {@link SNIMatcher}s of the Server Name Indication (SNI)
* parameter.
* <P>
* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
* operating in server mode.
* <P>
* Note that the {@code matchers} collection is cloned to protect
* against subsequent modification.
*
* @param matchers
* the collection of {@link SNIMatcher}s (or null)
*
* @throws NullPointerException if the {@code matchers}
* contains {@code null} element
* @throws IllegalArgumentException if the {@code matchers}
* contains more than one name of the same name type
*
* @see Collection
* @see SNIMatcher
* @see #getSNIMatchers()
*
* @since 1.8
*/
public
void
setSNIMatchers
(
Collection
<
SNIMatcher
>
matchers
)
{
if
(
matchers
!=
null
)
{
if
(!
matchers
.
isEmpty
())
{
sniMatchers
=
new
HashMap
<>(
matchers
.
size
());
for
(
SNIMatcher
matcher
:
matchers
)
{
if
(
sniMatchers
.
put
(
matcher
.
getType
(),
matcher
)
!=
null
)
{
throw
new
IllegalArgumentException
(
"Duplicated server name of type "
+
matcher
.
getType
());
}
}
}
else
{
sniMatchers
=
Collections
.<
Integer
,
SNIMatcher
>
emptyMap
();
}
}
else
{
sniMatchers
=
null
;
}
}
/**
* Returns a {@link Collection} containing all {@link SNIMatcher}s of the
* Server Name Indication (SNI) parameter, or null if none has been set.
* <P>
* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
* operating in server mode.
* <P>
* For better interoperability, providers generally will not define
* default matchers so that by default servers will ignore the SNI
* extension and continue the handshake.
*
* @return null or an immutable collection of non-null {@link SNIMatcher}s
*
* @see SNIMatcher
* @see #setSNIMatchers(Collection<SNIMatcher>)
*
* @since 1.8
*/
public
Collection
<
SNIMatcher
>
getSNIMatchers
()
{
if
(
sniMatchers
!=
null
)
{
if
(!
sniMatchers
.
isEmpty
())
{
return
Collections
.<
SNIMatcher
>
unmodifiableList
(
new
ArrayList
<>(
sniMatchers
.
values
()));
}
else
{
return
Collections
.<
SNIMatcher
>
emptyList
();
}
}
return
null
;
}
}
src/share/classes/javax/net/ssl/SSLServerSocket.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 1997, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
2
, 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
...
...
@@ -484,15 +484,19 @@ public abstract class SSLServerSocket extends ServerSocket {
*
* <p>This means:
* <ul>
* <li>if <code>params.getCipherSuites()</code> is non-null,
* <code>setEnabledCipherSuites()</code> is called with that value
* <li>if <code>params.getProtocols()</code> is non-null,
* <code>setEnabledProtocols()</code> is called with that value
* <li>if <code>params.getNeedClientAuth()</code> or
* <code>params.getWantClientAuth()</code> return <code>true</code>,
* <code>setNeedClientAuth(true)</code> and
* <code>setWantClientAuth(true)</code> are called, respectively;
* otherwise <code>setWantClientAuth(false)</code> is called.
* <li>If {@code params.getCipherSuites()} is non-null,
* {@code setEnabledCipherSuites()} is called with that value.</li>
* <li>If {@code params.getProtocols()} is non-null,
* {@code setEnabledProtocols()} is called with that value.</li>
* <li>If {@code params.getNeedClientAuth()} or
* {@code params.getWantClientAuth()} return {@code true},
* {@code setNeedClientAuth(true)} and
* {@code setWantClientAuth(true)} are called, respectively;
* otherwise {@code setWantClientAuth(false)} is called.</li>
* <li>If {@code params.getServerNames()} is non-null, the socket will
* configure its server names with that value.</li>
* <li>If {@code params.getSNIMatchers()} is non-null, the socket will
* configure its SNI matchers with that value.</li>
* </ul>
*
* @param params the parameters
...
...
src/share/classes/javax/net/ssl/SSLSocket.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 1997, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
2
, 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
...
...
@@ -626,15 +626,19 @@ public abstract class SSLSocket extends Socket
*
* <p>This means:
* <ul>
* <li>if <code>params.getCipherSuites()</code> is non-null,
* <code>setEnabledCipherSuites()</code> is called with that value
* <li>if <code>params.getProtocols()</code> is non-null,
* <code>setEnabledProtocols()</code> is called with that value
* <li>if <code>params.getNeedClientAuth()</code> or
* <code>params.getWantClientAuth()</code> return <code>true</code>,
* <code>setNeedClientAuth(true)</code> and
* <code>setWantClientAuth(true)</code> are called, respectively;
* otherwise <code>setWantClientAuth(false)</code> is called.
* <li>If {@code params.getCipherSuites()} is non-null,
* {@code setEnabledCipherSuites()} is called with that value.</li>
* <li>If {@code params.getProtocols()} is non-null,
* {@code setEnabledProtocols()} is called with that value.</li>
* <li>If {@code params.getNeedClientAuth()} or
* {@code params.getWantClientAuth()} return {@code true},
* {@code setNeedClientAuth(true)} and
* {@code setWantClientAuth(true)} are called, respectively;
* otherwise {@code setWantClientAuth(false)} is called.</li>
* <li>If {@code params.getServerNames()} is non-null, the socket will
* configure its server names with that value.</li>
* <li>If {@code params.getSNIMatchers()} is non-null, the socket will
* configure its SNI matchers with that value.</li>
* </ul>
*
* @param params the parameters
...
...
src/share/classes/javax/net/ssl/SSLSocketFactory.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 1997, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
2
, 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
...
...
@@ -29,6 +29,7 @@ package javax.net.ssl;
import
java.net.*
;
import
javax.net.SocketFactory
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.security.*
;
import
java.util.Locale
;
...
...
@@ -180,8 +181,55 @@ public abstract class SSLSocketFactory extends SocketFactory
* @throws NullPointerException if the parameter s is null
*/
public
abstract
Socket
createSocket
(
Socket
s
,
String
host
,
int
port
,
boolean
autoClose
)
throws
IOException
;
int
port
,
boolean
autoClose
)
throws
IOException
;
/**
* Creates a server mode {@link Socket} layered over an
* existing connected socket, and is able to read data which has
* already been consumed/removed from the {@link Socket}'s
* underlying {@link InputStream}.
* <p>
* This method can be used by a server application that needs to
* observe the inbound data but still create valid SSL/TLS
* connections: for example, inspection of Server Name Indication
* (SNI) extensions (See section 3 of <A
* HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions
* (RFC6066)</A>). Data that has been already removed from the
* underlying {@link InputStream} should be loaded into the
* {@code consumed} stream before this method is called, perhaps
* using a {@link ByteArrayInputStream}. When this {@link Socket}
* begins handshaking, it will read all of the data in
* {@code consumed} until it reaches {@code EOF}, then all further
* data is read from the underlying {@link InputStream} as
* usual.
* <p>
* The returned socket is configured using the socket options
* established for this factory, and is set to use server mode when
* handshaking (see {@link SSLSocket#setUseClientMode(boolean)}).
*
* @param s
* the existing socket
* @param consumed
* the consumed inbound network data that has already been
* removed from the existing {@link Socket}
* {@link InputStream}. This parameter may be
* {@code null} if no data has been removed.
* @param autoClose close the underlying socket when this socket is closed.
*
* @return the {@link Socket} compliant with the socket options
* established for this factory
*
* @throws IOException if an I/O error occurs when creating the socket
* @throws UnsupportedOperationException if the underlying provider
* does not implement the operation
* @throws NullPointerException if {@code s} is {@code null}
*
* @since 1.8
*/
public
Socket
createSocket
(
Socket
s
,
InputStream
consumed
,
boolean
autoClose
)
throws
IOException
{
throw
new
UnsupportedOperationException
();
}
}
...
...
src/share/classes/javax/net/ssl/StandardConstants.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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
javax.net.ssl
;
/**
* Standard constants definitions
*
* @since 1.8
*/
public
final
class
StandardConstants
{
// Suppress default constructor for noninstantiability
private
StandardConstants
()
{
throw
new
AssertionError
(
"No javax.net.ssl.StandardConstants instances for you!"
);
}
/**
* The "host_name" type representing of a DNS hostname
* (see {@link SNIHostName}) in a Server Name Indication (SNI) extension.
* <P>
* The SNI extension is a feature that extends the SSL/TLS protocols to
* indicate what server name the client is attempting to connect to during
* handshaking. See section 3, "Server Name Indication", of <A
* HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions (RFC 6066)</A>.
* <P>
* The value of this constant is {@value}.
*
* @see SNIServerName
* @see SNIHostName
*/
public
static
final
int
SNI_HOST_NAME
=
0x00
;
}
src/share/classes/sun/security/ssl/BaseSSLSocketImpl.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 2002, 20
08
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 20
12
, 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
...
...
@@ -23,7 +23,6 @@
* questions.
*/
package
sun.security.ssl
;
import
java.io.*
;
...
...
@@ -55,16 +54,25 @@ abstract class BaseSSLSocketImpl extends SSLSocket {
* recurse infinitely ... e.g. close() calling itself, or doing
* I/O in terms of our own streams.
*/
final
Socket
self
;
final
private
Socket
self
;
final
private
InputStream
consumedInput
;
BaseSSLSocketImpl
()
{
super
();
this
.
self
=
this
;
this
.
consumedInput
=
null
;
}
BaseSSLSocketImpl
(
Socket
socket
)
{
super
();
this
.
self
=
socket
;
this
.
consumedInput
=
null
;
}
BaseSSLSocketImpl
(
Socket
socket
,
InputStream
consumed
)
{
super
();
this
.
self
=
socket
;
this
.
consumedInput
=
consumed
;
}
//
...
...
@@ -541,4 +549,57 @@ abstract class BaseSSLSocketImpl extends SSLSocket {
}
}
@Override
public
String
toString
()
{
if
(
self
==
this
)
{
return
super
.
toString
();
}
return
self
.
toString
();
}
@Override
public
InputStream
getInputStream
()
throws
IOException
{
if
(
self
==
this
)
{
return
super
.
getInputStream
();
}
if
(
consumedInput
!=
null
)
{
return
new
SequenceInputStream
(
consumedInput
,
self
.
getInputStream
());
}
return
self
.
getInputStream
();
}
@Override
public
OutputStream
getOutputStream
()
throws
IOException
{
if
(
self
==
this
)
{
return
super
.
getOutputStream
();
}
return
self
.
getOutputStream
();
}
@Override
public
synchronized
void
close
()
throws
IOException
{
if
(
self
==
this
)
{
super
.
close
();
}
else
{
self
.
close
();
}
}
@Override
public
synchronized
void
setSoTimeout
(
int
timeout
)
throws
SocketException
{
if
(
self
==
this
)
{
super
.
setSoTimeout
(
timeout
);
}
else
{
self
.
setSoTimeout
(
timeout
);
}
}
boolean
isLayered
()
{
return
(
self
!=
this
);
}
}
src/share/classes/sun/security/ssl/ClientHandshaker.java
浏览文件 @
b80ffe55
...
...
@@ -48,8 +48,6 @@ import sun.security.ssl.HandshakeMessage.*;
import
sun.security.ssl.CipherSuite.*
;
import
static
sun
.
security
.
ssl
.
CipherSuite
.
KeyExchange
.*;
import
sun.net.util.IPAddressUtil
;
/**
* ClientHandshaker does the protocol handshaking from the point
* of view of a client. It is driven asychronously by handshake messages
...
...
@@ -92,6 +90,9 @@ final class ClientHandshaker extends Handshaker {
private
final
static
boolean
enableSNIExtension
=
Debug
.
getBooleanProperty
(
"jsse.enableSNIExtension"
,
true
);
private
List
<
SNIServerName
>
requestedServerNames
=
Collections
.<
SNIServerName
>
emptyList
();
/*
* Constructors
*/
...
...
@@ -579,6 +580,7 @@ final class ClientHandshaker extends Handshaker {
session
=
new
SSLSessionImpl
(
protocolVersion
,
cipherSuite
,
getLocalSupportedSignAlgs
(),
mesg
.
sessionId
,
getHostSE
(),
getPortSE
());
session
.
setRequestedServerNames
(
requestedServerNames
);
setHandshakeSessionSE
(
session
);
if
(
debug
!=
null
&&
Debug
.
isOn
(
"handshake"
))
{
System
.
out
.
println
(
"** "
+
cipherSuite
);
...
...
@@ -1246,17 +1248,14 @@ final class ClientHandshaker extends Handshaker {
// add server_name extension
if
(
enableSNIExtension
)
{
// We cannot use the hostname resolved from name services. For
// virtual hosting, multiple hostnames may be bound to the same IP
// address, so the hostname resolved from name services is not
// reliable.
String
hostname
=
getRawHostnameSE
();
// we only allow FQDN
if
(
hostname
!=
null
&&
hostname
.
indexOf
(
'.'
)
>
0
&&
!
IPAddressUtil
.
isIPv4LiteralAddress
(
hostname
)
&&
!
IPAddressUtil
.
isIPv6LiteralAddress
(
hostname
))
{
clientHelloMessage
.
addServerNameIndicationExtension
(
hostname
);
if
(
session
!=
null
)
{
requestedServerNames
=
session
.
getRequestedServerNames
();
}
else
{
requestedServerNames
=
serverNames
;
}
if
(!
requestedServerNames
.
isEmpty
())
{
clientHelloMessage
.
addSNIExtension
(
requestedServerNames
);
}
}
...
...
src/share/classes/sun/security/ssl/HandshakeInStream.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 1996, 20
09
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 20
12
, 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
...
...
@@ -121,7 +121,8 @@ public class HandshakeInStream extends InputStream {
r
.
mark
(
readlimit
);
}
public
void
reset
()
{
@Override
public
void
reset
()
throws
IOException
{
r
.
reset
();
}
...
...
src/share/classes/sun/security/ssl/HandshakeMessage.java
浏览文件 @
b80ffe55
...
...
@@ -256,13 +256,9 @@ static final class ClientHello extends HandshakeMessage {
}
// add server_name extension
void
addServerNameIndicationExtension
(
String
hostname
)
{
// We would have checked that the hostname ia a FQDN.
ArrayList
<
String
>
hostnames
=
new
ArrayList
<>(
1
);
hostnames
.
add
(
hostname
);
void
addSNIExtension
(
List
<
SNIServerName
>
serverNames
)
{
try
{
extensions
.
add
(
new
ServerNameExtension
(
hostn
ames
));
extensions
.
add
(
new
ServerNameExtension
(
serverN
ames
));
}
catch
(
IOException
ioe
)
{
// ignore the exception and return
}
...
...
src/share/classes/sun/security/ssl/Handshaker.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 1996, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 201
2
, 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
...
...
@@ -112,6 +112,12 @@ abstract class Handshaker {
*/
private
CipherSuiteList
activeCipherSuites
;
// The server name indication and matchers
List
<
SNIServerName
>
serverNames
=
Collections
.<
SNIServerName
>
emptyList
();
Collection
<
SNIMatcher
>
sniMatchers
=
Collections
.<
SNIMatcher
>
emptyList
();
private
boolean
isClient
;
private
boolean
needCertVerify
;
...
...
@@ -287,14 +293,7 @@ abstract class Handshaker {
}
}
String
getRawHostnameSE
()
{
if
(
conn
!=
null
)
{
return
conn
.
getRawHostname
();
}
else
{
return
engine
.
getPeerHost
();
}
}
// ONLY used by ClientHandshaker to setup the peer host in SSLSession.
String
getHostSE
()
{
if
(
conn
!=
null
)
{
return
conn
.
getHost
();
...
...
@@ -303,6 +302,7 @@ abstract class Handshaker {
}
}
// ONLY used by ServerHandshaker to setup the peer host in SSLSession.
String
getHostAddressSE
()
{
if
(
conn
!=
null
)
{
return
conn
.
getInetAddress
().
getHostAddress
();
...
...
@@ -435,6 +435,22 @@ abstract class Handshaker {
this
.
identificationProtocol
=
protocol
;
}
/**
* Sets the server name indication of the handshake.
*/
void
setSNIServerNames
(
List
<
SNIServerName
>
serverNames
)
{
// The serverNames parameter is unmodifiable.
this
.
serverNames
=
serverNames
;
}
/**
* Sets the server name matchers of the handshaking.
*/
void
setSNIMatchers
(
Collection
<
SNIMatcher
>
sniMatchers
)
{
// The sniMatchers parameter is unmodifiable.
this
.
sniMatchers
=
sniMatchers
;
}
/**
* Prior to handshaking, activate the handshake and initialize the version,
* input stream and output stream.
...
...
src/share/classes/sun/security/ssl/HelloExtensions.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 2006, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 201
2
, 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
...
...
@@ -28,11 +28,10 @@ package sun.security.ssl;
import
java.io.IOException
;
import
java.io.PrintStream
;
import
java.util.*
;
import
javax.net.ssl.*
;
import
java.nio.charset.StandardCharsets
;
import
java.security.spec.ECParameterSpec
;
import
javax.net.ssl.SSLProtocolException
;
/**
* This file contains all the classes relevant to TLS Extensions for the
* ClientHello and ServerHello messages. The extension mechanism and
...
...
@@ -274,11 +273,11 @@ final class UnknownExtension extends HelloExtension {
}
/*
* [RFC
4366] To facilitate secure connections to servers that host multiple
*
'virtual' servers at a single underlying network address, clients MAY
*
include an extension of type "server_name" in the (extended) client hello.
*
The "extension_data" field of this extension SHALL contain "ServerNameList"
* where:
* [RFC
4366/6066] To facilitate secure connections to servers that host
*
multiple 'virtual' servers at a single underlying network address, clients
*
MAY include an extension of type "server_name" in the (extended) client
*
hello. The "extension_data" field of this extension SHALL contain
*
"ServerNameList"
where:
*
* struct {
* NameType name_type;
...
...
@@ -299,44 +298,47 @@ final class UnknownExtension extends HelloExtension {
*/
final
class
ServerNameExtension
extends
HelloExtension
{
final
static
int
NAME_HOST_NAME
=
0
;
private
List
<
ServerName
>
names
;
// For backward compatibility, all future data structures associated with
// new NameTypes MUST begin with a 16-bit length field.
final
static
int
NAME_HEADER_LENGTH
=
3
;
// NameType: 1 byte
// Name length: 2 bytes
private
Map
<
Integer
,
SNIServerName
>
sniMap
;
private
int
listLength
;
// ServerNameList length
ServerNameExtension
(
List
<
String
>
hostnames
)
throws
IOException
{
// constructor for ServerHello
ServerNameExtension
()
throws
IOException
{
super
(
ExtensionType
.
EXT_SERVER_NAME
);
listLength
=
0
;
sniMap
=
Collections
.<
Integer
,
SNIServerName
>
emptyMap
();
}
// constructor for ClientHello
ServerNameExtension
(
List
<
SNIServerName
>
serverNames
)
throws
IOException
{
super
(
ExtensionType
.
EXT_SERVER_NAME
);
listLength
=
0
;
names
=
new
ArrayList
<
ServerName
>(
hostnames
.
size
());
for
(
String
hostname
:
hostnames
)
{
if
(
hostname
!=
null
&&
hostname
.
length
()
!=
0
)
{
// we only support DNS hostname now.
ServerName
serverName
=
new
ServerName
(
NAME_HOST_NAME
,
hostname
);
names
.
add
(
serverName
);
listLength
+=
serverName
.
length
;
sniMap
=
new
LinkedHashMap
<>();
for
(
SNIServerName
serverName
:
serverNames
)
{
// check for duplicated server name type
if
(
sniMap
.
put
(
serverName
.
getType
(),
serverName
)
!=
null
)
{
// unlikely to happen, but in case ...
throw
new
RuntimeException
(
"Duplicated server name of type "
+
serverName
.
getType
());
}
}
// As we only support DNS hostname now, the hostname list must
// not contain more than one hostname
if
(
names
.
size
()
>
1
)
{
throw
new
SSLProtocolException
(
"The ServerNameList MUST NOT contain more than "
+
"one name of the same name_type"
);
listLength
+=
serverName
.
getEncoded
().
length
+
NAME_HEADER_LENGTH
;
}
// We only need to add "server_name" extension in ClientHello unless
// we support SNI in server side in the future. It is possible that
// the SNI is empty in ServerHello. As we don't support SNI in
// ServerHello now, we will throw exception for empty list for now.
// This constructor is used for ClientHello only. Empty list is
// not allowed in client mode.
if
(
listLength
==
0
)
{
throw
new
SSLProtocolException
(
"The ServerNameList cannot be empty"
);
throw
new
RuntimeException
(
"The ServerNameList cannot be empty"
);
}
}
// constructor for ServerHello for parsing SNI extension
ServerNameExtension
(
HandshakeInStream
s
,
int
len
)
throws
IOException
{
super
(
ExtensionType
.
EXT_SERVER_NAME
);
...
...
@@ -350,17 +352,54 @@ final class ServerNameExtension extends HelloExtension {
}
remains
-=
2
;
names
=
new
ArrayList
<
ServerName
>();
sniMap
=
new
LinkedHashMap
<
>();
while
(
remains
>
0
)
{
ServerName
name
=
new
ServerName
(
s
);
names
.
add
(
name
);
remains
-=
name
.
length
;
int
code
=
s
.
getInt8
();
// NameType
// HostName (length read in getBytes16);
byte
[]
encoded
=
s
.
getBytes16
();
SNIServerName
serverName
;
switch
(
code
)
{
case
StandardConstants
.
SNI_HOST_NAME
:
if
(
encoded
.
length
==
0
)
{
throw
new
SSLProtocolException
(
"Empty HostName in server name indication"
);
}
try
{
serverName
=
new
SNIHostName
(
encoded
);
}
catch
(
IllegalArgumentException
iae
)
{
SSLProtocolException
spe
=
new
SSLProtocolException
(
"Illegal server name, type=host_name("
+
code
+
"), name="
+
(
new
String
(
encoded
,
StandardCharsets
.
UTF_8
))
+
", value="
+
Debug
.
toString
(
encoded
));
spe
.
initCause
(
iae
);
throw
spe
;
}
break
;
default
:
try
{
serverName
=
new
UnknownServerName
(
code
,
encoded
);
}
catch
(
IllegalArgumentException
iae
)
{
SSLProtocolException
spe
=
new
SSLProtocolException
(
"Illegal server name, type=("
+
code
+
"), value="
+
Debug
.
toString
(
encoded
));
spe
.
initCause
(
iae
);
throw
spe
;
}
}
// check for duplicated server name type
if
(
sniMap
.
put
(
serverName
.
getType
(),
serverName
)
!=
null
)
{
throw
new
SSLProtocolException
(
"Duplicated server name of type "
+
serverName
.
getType
());
}
// we may need to check the duplicated ServerName type
remains
-=
encoded
.
length
+
NAME_HEADER_LENGTH
;
}
}
else
if
(
len
==
0
)
{
// "server_name" extension in ServerHello
listLength
=
0
;
names
=
Collections
.<
ServerName
>
emptyList
();
sniMap
=
Collections
.<
Integer
,
SNIServerName
>
emptyMap
();
}
if
(
remains
!=
0
)
{
...
...
@@ -368,39 +407,72 @@ final class ServerNameExtension extends HelloExtension {
}
}
static
class
ServerName
{
final
int
length
;
final
int
type
;
final
byte
[]
data
;
final
String
hostname
;
ServerName
(
int
type
,
String
hostname
)
throws
IOException
{
this
.
type
=
type
;
// NameType
this
.
hostname
=
hostname
;
this
.
data
=
hostname
.
getBytes
(
"UTF8"
);
// HostName
this
.
length
=
data
.
length
+
3
;
// NameType: 1 byte
// HostName length: 2 bytes
}
ServerName
(
HandshakeInStream
s
)
throws
IOException
{
type
=
s
.
getInt8
();
// NameType
data
=
s
.
getBytes16
();
// HostName (length read in getBytes16)
length
=
data
.
length
+
3
;
// NameType: 1 byte
// HostName length: 2 bytes
if
(
type
==
NAME_HOST_NAME
)
{
hostname
=
new
String
(
data
,
"UTF8"
);
}
else
{
hostname
=
null
;
List
<
SNIServerName
>
getServerNames
()
{
if
(
sniMap
!=
null
&&
!
sniMap
.
isEmpty
())
{
return
Collections
.<
SNIServerName
>
unmodifiableList
(
new
ArrayList
<>(
sniMap
.
values
()));
}
return
Collections
.<
SNIServerName
>
emptyList
();
}
/*
* Is the extension recognized by the corresponding matcher?
*
* This method is used to check whether the server name indication can
* be recognized by the server name matchers.
*
* Per RFC 6066, if the server understood the ClientHello extension but
* does not recognize the server name, the server SHOULD take one of two
* actions: either abort the handshake by sending a fatal-level
* unrecognized_name(112) alert or continue the handshake.
*
* If there is an instance of SNIMatcher defined for a particular name
* type, it must be used to perform match operations on the server name.
*/
boolean
isMatched
(
Collection
<
SNIMatcher
>
matchers
)
{
if
(
sniMap
!=
null
&&
!
sniMap
.
isEmpty
())
{
for
(
SNIMatcher
matcher
:
matchers
)
{
SNIServerName
sniName
=
sniMap
.
get
(
matcher
.
getType
());
if
(
sniName
!=
null
&&
(!
matcher
.
matches
(
sniName
)))
{
return
false
;
}
}
}
public
String
toString
()
{
if
(
type
==
NAME_HOST_NAME
)
{
return
"host_name: "
+
hostname
;
}
else
{
return
"unknown-"
+
type
+
": "
+
Debug
.
toString
(
data
);
return
true
;
}
/*
* Is the extension is identical to a server name list?
*
* This method is used to check the server name indication during session
* resumption.
*
* Per RFC 6066, when the server is deciding whether or not to accept a
* request to resume a session, the contents of a server_name extension
* MAY be used in the lookup of the session in the session cache. The
* client SHOULD include the same server_name extension in the session
* resumption request as it did in the full handshake that established
* the session. A server that implements this extension MUST NOT accept
* the request to resume the session if the server_name extension contains
* a different name. Instead, it proceeds with a full handshake to
* establish a new session. When resuming a session, the server MUST NOT
* include a server_name extension in the server hello.
*/
boolean
isIdentical
(
List
<
SNIServerName
>
other
)
{
if
(
other
.
size
()
==
sniMap
.
size
())
{
for
(
SNIServerName
sniInOther
:
other
)
{
SNIServerName
sniName
=
sniMap
.
get
(
sniInOther
.
getType
());
if
(
sniName
==
null
||
!
sniInOther
.
equals
(
sniName
))
{
return
false
;
}
}
return
true
;
}
return
false
;
}
int
length
()
{
...
...
@@ -409,25 +481,34 @@ final class ServerNameExtension extends HelloExtension {
void
send
(
HandshakeOutStream
s
)
throws
IOException
{
s
.
putInt16
(
type
.
id
);
s
.
putInt16
(
listLength
+
2
);
if
(
listLength
!=
0
)
{
s
.
putInt16
(
listLength
);
if
(
listLength
==
0
)
{
s
.
putInt16
(
listLength
);
// in ServerHello, empty extension_data
}
else
{
s
.
putInt16
(
listLength
+
2
);
// length of extension_data
s
.
putInt16
(
listLength
);
// length of ServerNameList
for
(
S
erverName
name
:
names
)
{
s
.
putInt8
(
name
.
type
);
// NameT
ype
s
.
putBytes16
(
name
.
data
);
// HostNam
e
for
(
S
NIServerName
sniName
:
sniMap
.
values
()
)
{
s
.
putInt8
(
sniName
.
getType
());
// server name t
ype
s
.
putBytes16
(
sniName
.
getEncoded
());
// server name valu
e
}
}
}
public
String
toString
()
{
StringBuffer
buffer
=
new
StringBuffer
();
for
(
S
erverName
name
:
names
)
{
buffer
.
append
(
"["
+
n
ame
+
"]"
);
for
(
S
NIServerName
sniName
:
sniMap
.
values
()
)
{
buffer
.
append
(
"["
+
sniN
ame
+
"]"
);
}
return
"Extension "
+
type
+
", server_name: "
+
buffer
;
}
private
static
class
UnknownServerName
extends
SNIServerName
{
UnknownServerName
(
int
code
,
byte
[]
encoded
)
{
super
(
code
,
encoded
);
}
}
}
final
class
SupportedEllipticCurvesExtension
extends
HelloExtension
{
...
...
src/share/classes/sun/security/ssl/ProtocolList.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 2002, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 201
2
, 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
...
...
@@ -79,7 +79,7 @@ final class ProtocolList {
throw
new
IllegalArgumentException
(
"Protocols may not be null"
);
}
ArrayList
<
ProtocolVersion
>
versions
=
new
ArrayList
<>(
3
);
ArrayList
<
ProtocolVersion
>
versions
=
new
ArrayList
<>(
names
.
length
);
for
(
int
i
=
0
;
i
<
names
.
length
;
i
++
)
{
ProtocolVersion
version
=
ProtocolVersion
.
valueOf
(
names
[
i
]);
if
(
versions
.
contains
(
version
)
==
false
)
{
...
...
src/share/classes/sun/security/ssl/SSLEngineImpl.java
浏览文件 @
b80ffe55
...
...
@@ -27,6 +27,7 @@ package sun.security.ssl;
import
java.io.*
;
import
java.nio.*
;
import
java.util.*
;
import
java.security.*
;
import
javax.crypto.BadPaddingException
;
...
...
@@ -34,7 +35,6 @@ import javax.crypto.BadPaddingException;
import
javax.net.ssl.*
;
import
javax.net.ssl.SSLEngineResult.*
;
/**
* Implementation of an non-blocking SSLEngine.
*
...
...
@@ -253,6 +253,12 @@ final public class SSLEngineImpl extends SSLEngine {
// The cryptographic algorithm constraints
private
AlgorithmConstraints
algorithmConstraints
=
null
;
// The server name indication and matchers
List
<
SNIServerName
>
serverNames
=
Collections
.<
SNIServerName
>
emptyList
();
Collection
<
SNIMatcher
>
sniMatchers
=
Collections
.<
SNIMatcher
>
emptyList
();
// Have we been told whether we're client or server?
private
boolean
serverModeSet
=
false
;
private
boolean
roleIsServer
;
...
...
@@ -361,6 +367,10 @@ final public class SSLEngineImpl extends SSLEngine {
roleIsServer
=
true
;
connectionState
=
cs_START
;
// default server name indication
serverNames
=
Utilities
.
addToSNIServerNameList
(
serverNames
,
getPeerHost
());
/*
* default read and write side cipher and MAC support
*
...
...
@@ -459,11 +469,13 @@ final public class SSLEngineImpl extends SSLEngine {
enabledProtocols
,
doClientAuth
,
protocolVersion
,
connectionState
==
cs_HANDSHAKE
,
secureRenegotiation
,
clientVerifyData
,
serverVerifyData
);
handshaker
.
setSNIMatchers
(
sniMatchers
);
}
else
{
handshaker
=
new
ClientHandshaker
(
this
,
sslContext
,
enabledProtocols
,
protocolVersion
,
connectionState
==
cs_HANDSHAKE
,
secureRenegotiation
,
clientVerifyData
,
serverVerifyData
);
handshaker
.
setSNIServerNames
(
serverNames
);
}
handshaker
.
setEnabledCipherSuites
(
enabledCipherSuites
);
handshaker
.
setEnableSessionCreation
(
enableSessionCreation
);
...
...
@@ -1100,7 +1112,7 @@ final public class SSLEngineImpl extends SSLEngine {
// TLS requires that unrecognized records be ignored.
//
if
(
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", Received record type: "
+
inputRecord
.
contentType
());
}
...
...
@@ -1384,7 +1396,7 @@ final public class SSLEngineImpl extends SSLEngine {
* for handshaking and bad_record_mac for other records.
*/
if
(
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", sequence number extremely close to overflow "
+
"(2^64-1 packets). Closing connection."
);
}
...
...
@@ -1402,7 +1414,8 @@ final public class SSLEngineImpl extends SSLEngine {
*/
if
((
type
!=
Record
.
ct_handshake
)
&&
mac
.
seqNumIsHuge
())
{
if
(
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
threadName
()
+
", request renegotiation "
+
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", request renegotiation "
+
"to avoid sequence number overflow"
);
}
...
...
@@ -1420,7 +1433,8 @@ final public class SSLEngineImpl extends SSLEngine {
private
void
closeOutboundInternal
()
{
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
threadName
()
+
", closeOutboundInternal()"
);
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", closeOutboundInternal()"
);
}
/*
...
...
@@ -1467,7 +1481,8 @@ final public class SSLEngineImpl extends SSLEngine {
* Dump out a close_notify to the remote side
*/
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
threadName
()
+
", called closeOutbound()"
);
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", called closeOutbound()"
);
}
closeOutboundInternal
();
...
...
@@ -1487,7 +1502,8 @@ final public class SSLEngineImpl extends SSLEngine {
private
void
closeInboundInternal
()
{
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
threadName
()
+
", closeInboundInternal()"
);
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", closeInboundInternal()"
);
}
/*
...
...
@@ -1519,7 +1535,8 @@ final public class SSLEngineImpl extends SSLEngine {
* someday in the future.
*/
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
threadName
()
+
", called closeInbound()"
);
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", called closeInbound()"
);
}
/*
...
...
@@ -1642,7 +1659,7 @@ final public class SSLEngineImpl extends SSLEngine {
*/
if
(
closeReason
!=
null
)
{
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", fatal: engine already closed. Rethrowing "
+
cause
.
toString
());
}
...
...
@@ -1656,7 +1673,7 @@ final public class SSLEngineImpl extends SSLEngine {
}
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", fatal error: "
+
description
+
": "
+
diagnostic
+
"\n"
+
cause
.
toString
());
}
...
...
@@ -1723,7 +1740,7 @@ final public class SSLEngineImpl extends SSLEngine {
if
(
debug
!=
null
&&
(
Debug
.
isOn
(
"record"
)
||
Debug
.
isOn
(
"handshake"
)))
{
synchronized
(
System
.
out
)
{
System
.
out
.
print
(
thread
Name
());
System
.
out
.
print
(
Thread
.
currentThread
().
get
Name
());
System
.
out
.
print
(
", RECV "
+
protocolVersion
+
" ALERT: "
);
if
(
level
==
Alerts
.
alert_fatal
)
{
System
.
out
.
print
(
"fatal, "
);
...
...
@@ -1790,7 +1807,7 @@ final public class SSLEngineImpl extends SSLEngine {
boolean
useDebug
=
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
);
if
(
useDebug
)
{
synchronized
(
System
.
out
)
{
System
.
out
.
print
(
thread
Name
());
System
.
out
.
print
(
Thread
.
currentThread
().
get
Name
());
System
.
out
.
print
(
", SEND "
+
protocolVersion
+
" ALERT: "
);
if
(
level
==
Alerts
.
alert_fatal
)
{
System
.
out
.
print
(
"fatal, "
);
...
...
@@ -1810,7 +1827,7 @@ final public class SSLEngineImpl extends SSLEngine {
writeRecord
(
r
);
}
catch
(
IOException
e
)
{
if
(
useDebug
)
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", Exception sending alert: "
+
e
);
}
}
...
...
@@ -1948,7 +1965,7 @@ final public class SSLEngineImpl extends SSLEngine {
default
:
if
(
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", setUseClientMode() invoked in state = "
+
connectionState
);
}
...
...
@@ -2050,6 +2067,8 @@ final public class SSLEngineImpl extends SSLEngine {
// the super implementation does not handle the following parameters
params
.
setEndpointIdentificationAlgorithm
(
identificationProtocol
);
params
.
setAlgorithmConstraints
(
algorithmConstraints
);
params
.
setSNIMatchers
(
sniMatchers
);
params
.
setServerNames
(
serverNames
);
return
params
;
}
...
...
@@ -2063,19 +2082,28 @@ final public class SSLEngineImpl extends SSLEngine {
// the super implementation does not handle the following parameters
identificationProtocol
=
params
.
getEndpointIdentificationAlgorithm
();
algorithmConstraints
=
params
.
getAlgorithmConstraints
();
List
<
SNIServerName
>
sniNames
=
params
.
getServerNames
();
if
(
sniNames
!=
null
)
{
serverNames
=
sniNames
;
}
Collection
<
SNIMatcher
>
matchers
=
params
.
getSNIMatchers
();
if
(
matchers
!=
null
)
{
sniMatchers
=
matchers
;
}
if
((
handshaker
!=
null
)
&&
!
handshaker
.
started
())
{
handshaker
.
setIdentificationProtocol
(
identificationProtocol
);
handshaker
.
setAlgorithmConstraints
(
algorithmConstraints
);
if
(
roleIsServer
)
{
handshaker
.
setSNIMatchers
(
sniMatchers
);
}
else
{
handshaker
.
setSNIServerNames
(
serverNames
);
}
}
}
/**
* Return the name of the current thread. Utility method.
*/
private
static
String
threadName
()
{
return
Thread
.
currentThread
().
getName
();
}
/**
* Returns a printable representation of this end of the connection.
*/
...
...
src/share/classes/sun/security/ssl/SSLServerSocketImpl.java
浏览文件 @
b80ffe55
...
...
@@ -39,6 +39,7 @@ import javax.net.ServerSocketFactory;
import
javax.net.ssl.SSLException
;
import
javax.net.ssl.SSLServerSocket
;
import
javax.net.ssl.SSLParameters
;
import
javax.net.ssl.SNIMatcher
;
/**
...
...
@@ -92,6 +93,10 @@ class SSLServerSocketImpl extends SSLServerSocket
// The cryptographic algorithm constraints
private
AlgorithmConstraints
algorithmConstraints
=
null
;
// The server name indication
Collection
<
SNIMatcher
>
sniMatchers
=
Collections
.<
SNIMatcher
>
emptyList
();
/**
* Create an SSL server socket on a port, using a non-default
* authentication context and a specified connection backlog.
...
...
@@ -289,6 +294,7 @@ class SSLServerSocketImpl extends SSLServerSocket
// the super implementation does not handle the following parameters
params
.
setEndpointIdentificationAlgorithm
(
identificationProtocol
);
params
.
setAlgorithmConstraints
(
algorithmConstraints
);
params
.
setSNIMatchers
(
sniMatchers
);
return
params
;
}
...
...
@@ -302,6 +308,10 @@ class SSLServerSocketImpl extends SSLServerSocket
// the super implementation does not handle the following parameters
identificationProtocol
=
params
.
getEndpointIdentificationAlgorithm
();
algorithmConstraints
=
params
.
getAlgorithmConstraints
();
Collection
<
SNIMatcher
>
matchers
=
params
.
getSNIMatchers
();
if
(
matchers
!=
null
)
{
sniMatchers
=
params
.
getSNIMatchers
();
}
}
/**
...
...
@@ -312,7 +322,8 @@ class SSLServerSocketImpl extends SSLServerSocket
public
Socket
accept
()
throws
IOException
{
SSLSocketImpl
s
=
new
SSLSocketImpl
(
sslContext
,
useServerMode
,
enabledCipherSuites
,
doClientAuth
,
enableSessionCreation
,
enabledProtocols
,
identificationProtocol
,
algorithmConstraints
);
enabledProtocols
,
identificationProtocol
,
algorithmConstraints
,
sniMatchers
);
implAccept
(
s
);
s
.
doneConnect
();
...
...
src/share/classes/sun/security/ssl/SSLSessionImpl.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 1996, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 201
2
, 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
...
...
@@ -33,6 +33,9 @@ import java.util.Hashtable;
import
java.util.Vector
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.ArrayList
;
import
java.security.Principal
;
import
java.security.PrivateKey
;
...
...
@@ -51,6 +54,7 @@ import javax.net.ssl.SSLSession;
import
javax.net.ssl.SSLPermission
;
import
javax.net.ssl.SSLException
;
import
javax.net.ssl.ExtendedSSLSession
;
import
javax.net.ssl.SNIServerName
;
import
javax.security.auth.x500.X500Principal
;
...
...
@@ -111,6 +115,8 @@ final class SSLSessionImpl extends ExtendedSSLSession {
private
PrivateKey
localPrivateKey
;
private
String
[]
localSupportedSignAlgs
;
private
String
[]
peerSupportedSignAlgs
;
private
List
<
SNIServerName
>
requestedServerNames
;
// Principals for non-certificate based cipher suites
private
Principal
peerPrincipal
;
...
...
@@ -212,6 +218,10 @@ final class SSLSessionImpl extends ExtendedSSLSession {
SignatureAndHashAlgorithm
.
getAlgorithmNames
(
algorithms
);
}
void
setRequestedServerNames
(
List
<
SNIServerName
>
requestedServerNames
)
{
this
.
requestedServerNames
=
new
ArrayList
<>(
requestedServerNames
);
}
/**
* Set the peer principal.
*/
...
...
@@ -748,6 +758,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
* Gets an array of supported signature algorithms that the local side is
* willing to verify.
*/
@Override
public
String
[]
getLocalSupportedSignatureAlgorithms
()
{
if
(
localSupportedSignAlgs
!=
null
)
{
return
localSupportedSignAlgs
.
clone
();
...
...
@@ -760,6 +771,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
* Gets an array of supported signature algorithms that the peer is
* able to verify.
*/
@Override
public
String
[]
getPeerSupportedSignatureAlgorithms
()
{
if
(
peerSupportedSignAlgs
!=
null
)
{
return
peerSupportedSignAlgs
.
clone
();
...
...
@@ -768,6 +780,20 @@ final class SSLSessionImpl extends ExtendedSSLSession {
return
new
String
[
0
];
}
/**
* Obtains a <code>List</code> containing all {@link SNIServerName}s
* of the requested Server Name Indication (SNI) extension.
*/
@Override
public
List
<
SNIServerName
>
getRequestedServerNames
()
{
if
(
requestedServerNames
!=
null
&&
!
requestedServerNames
.
isEmpty
())
{
return
Collections
.<
SNIServerName
>
unmodifiableList
(
requestedServerNames
);
}
return
Collections
.<
SNIServerName
>
emptyList
();
}
/** Returns a string representation of this SSL session */
public
String
toString
()
{
return
"[Session-"
+
sessionCount
...
...
src/share/classes/sun/security/ssl/SSLSocketFactoryImpl.java
浏览文件 @
b80ffe55
...
...
@@ -109,6 +109,16 @@ final public class SSLSocketFactoryImpl extends SSLSocketFactory {
return
new
SSLSocketImpl
(
context
,
s
,
host
,
port
,
autoClose
);
}
@Override
public
Socket
createSocket
(
Socket
s
,
InputStream
consumed
,
boolean
autoClose
)
throws
IOException
{
if
(
s
==
null
)
{
throw
new
NullPointerException
(
"the existing socket cannot be null"
);
}
return
new
SSLSocketImpl
(
context
,
s
,
consumed
,
autoClose
);
}
/**
* Constructs an SSL connection to a server at a specified address
...
...
src/share/classes/sun/security/ssl/SSLSocketImpl.java
浏览文件 @
b80ffe55
...
...
@@ -36,9 +36,9 @@ import java.security.AlgorithmConstraints;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.locks.ReentrantLock
;
import
java.nio.charset.StandardCharsets
;
import
javax.crypto.BadPaddingException
;
import
javax.net.ssl.*
;
/**
...
...
@@ -198,14 +198,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
private
boolean
autoClose
=
true
;
private
AccessControlContext
acc
;
/*
* We cannot use the hostname resolved from name services. For
* virtual hosting, multiple hostnames may be bound to the same IP
* address, so the hostname resolved from name services is not
* reliable.
*/
private
String
rawHostname
;
// The cipher suites enabled for use on this connection.
private
CipherSuiteList
enabledCipherSuites
;
...
...
@@ -215,6 +207,12 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
// The cryptographic algorithm constraints
private
AlgorithmConstraints
algorithmConstraints
=
null
;
// The server name indication and matchers
List
<
SNIServerName
>
serverNames
=
Collections
.<
SNIServerName
>
emptyList
();
Collection
<
SNIMatcher
>
sniMatchers
=
Collections
.<
SNIMatcher
>
emptyList
();
/*
* READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
* IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
...
...
@@ -397,7 +395,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
throws
IOException
,
UnknownHostException
{
super
();
this
.
host
=
host
;
this
.
rawHostname
=
host
;
this
.
serverNames
=
Utilities
.
addToSNIServerNameList
(
this
.
serverNames
,
this
.
host
);
init
(
context
,
false
);
SocketAddress
socketAddress
=
host
!=
null
?
new
InetSocketAddress
(
host
,
port
)
:
...
...
@@ -440,7 +439,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
throws
IOException
,
UnknownHostException
{
super
();
this
.
host
=
host
;
this
.
rawHostname
=
host
;
this
.
serverNames
=
Utilities
.
addToSNIServerNameList
(
this
.
serverNames
,
this
.
host
);
init
(
context
,
false
);
bind
(
new
InetSocketAddress
(
localAddr
,
localPort
));
SocketAddress
socketAddress
=
...
...
@@ -482,13 +482,15 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
CipherSuiteList
suites
,
byte
clientAuth
,
boolean
sessionCreation
,
ProtocolList
protocols
,
String
identificationProtocol
,
AlgorithmConstraints
algorithmConstraints
)
throws
IOException
{
AlgorithmConstraints
algorithmConstraints
,
Collection
<
SNIMatcher
>
sniMatchers
)
throws
IOException
{
super
();
doClientAuth
=
clientAuth
;
enableSessionCreation
=
sessionCreation
;
this
.
identificationProtocol
=
identificationProtocol
;
this
.
algorithmConstraints
=
algorithmConstraints
;
this
.
sniMatchers
=
sniMatchers
;
init
(
context
,
serverMode
);
/*
...
...
@@ -535,12 +537,35 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
throw
new
SocketException
(
"Underlying socket is not connected"
);
}
this
.
host
=
host
;
this
.
rawHostname
=
host
;
this
.
serverNames
=
Utilities
.
addToSNIServerNameList
(
this
.
serverNames
,
this
.
host
);
init
(
context
,
false
);
this
.
autoClose
=
autoClose
;
doneConnect
();
}
/**
* Creates a server mode {@link Socket} layered over an
* existing connected socket, and is able to read data which has
* already been consumed/removed from the {@link Socket}'s
* underlying {@link InputStream}.
*/
SSLSocketImpl
(
SSLContextImpl
context
,
Socket
sock
,
InputStream
consumed
,
boolean
autoClose
)
throws
IOException
{
super
(
sock
,
consumed
);
// We always layer over a connected socket
if
(!
sock
.
isConnected
())
{
throw
new
SocketException
(
"Underlying socket is not connected"
);
}
// In server mode, it is not necessary to set host and serverNames.
// Otherwise, would require a reverse DNS lookup to get the hostname.
init
(
context
,
true
);
this
.
autoClose
=
autoClose
;
doneConnect
();
}
/**
* Initializes the client socket.
*/
...
...
@@ -604,7 +629,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
public
void
connect
(
SocketAddress
endpoint
,
int
timeout
)
throws
IOException
{
if
(
self
!=
this
)
{
if
(
isLayered
()
)
{
throw
new
SocketException
(
"Already connected"
);
}
...
...
@@ -628,13 +653,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* java.net actually connects using the socket "self", else
* we get some pretty bizarre failure modes.
*/
if
(
self
==
this
)
{
sockInput
=
super
.
getInputStream
();
sockOutput
=
super
.
getOutputStream
();
}
else
{
sockInput
=
self
.
getInputStream
();
sockOutput
=
self
.
getOutputStream
();
}
sockInput
=
super
.
getInputStream
();
sockOutput
=
super
.
getOutputStream
();
/*
* Move to handshaking state, with pending session initialized
...
...
@@ -761,13 +781,14 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
// For layered, non-autoclose sockets, we are not
// able to bring them into a usable state, so we
// treat it as fatal error.
if
(
self
!=
this
&&
!
autoClose
)
{
if
(
isLayered
()
&&
!
autoClose
)
{
// Note that the alert description is
// specified as -1, so no message will be send
// to peer anymore.
fatal
((
byte
)(-
1
),
ssle
);
}
else
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
threadName
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", received Exception: "
+
ssle
);
}
...
...
@@ -935,7 +956,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
boolean
handshaking
=
(
getConnectionState
()
<=
cs_HANDSHAKE
);
boolean
rethrow
=
requireCloseNotify
||
handshaking
;
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", received EOFException: "
+
(
rethrow
?
"error"
:
"ignored"
));
}
...
...
@@ -1119,7 +1140,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
// TLS requires that unrecognized records be ignored.
//
if
(
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", Received record type: "
+
r
.
contentType
());
}
...
...
@@ -1183,7 +1204,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
* for handshaking and bad_record_mac for other records.
*/
if
(
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", sequence number extremely close to overflow "
+
"(2^64-1 packets). Closing connection."
);
...
...
@@ -1200,7 +1221,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/
if
((
type
!=
Record
.
ct_handshake
)
&&
mac
.
seqNumIsHuge
())
{
if
(
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
threadName
()
+
", request renegotiation "
+
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", request renegotiation "
+
"to avoid sequence number overflow"
);
}
...
...
@@ -1278,11 +1300,13 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
enabledProtocols
,
doClientAuth
,
protocolVersion
,
connectionState
==
cs_HANDSHAKE
,
secureRenegotiation
,
clientVerifyData
,
serverVerifyData
);
handshaker
.
setSNIMatchers
(
sniMatchers
);
}
else
{
handshaker
=
new
ClientHandshaker
(
this
,
sslContext
,
enabledProtocols
,
protocolVersion
,
connectionState
==
cs_HANDSHAKE
,
secureRenegotiation
,
clientVerifyData
,
serverVerifyData
);
handshaker
.
setSNIServerNames
(
serverNames
);
}
handshaker
.
setEnabledCipherSuites
(
enabledCipherSuites
);
handshaker
.
setEnableSessionCreation
(
enableSessionCreation
);
...
...
@@ -1509,24 +1533,20 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
protected
void
closeSocket
()
throws
IOException
{
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
threadName
()
+
", called closeSocket()"
);
}
if
(
self
==
this
)
{
super
.
close
();
}
else
{
self
.
close
();
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", called closeSocket()"
);
}
super
.
close
();
}
private
void
closeSocket
(
boolean
selfInitiated
)
throws
IOException
{
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", called closeSocket("
+
selfInitiated
+
")"
);
}
if
(
self
==
this
)
{
if
(
!
isLayered
()
||
autoClose
)
{
super
.
close
();
}
else
if
(
autoClose
)
{
self
.
close
();
}
else
if
(
selfInitiated
)
{
// layered && non-autoclose
// read close_notify alert to clear input stream
...
...
@@ -1549,7 +1569,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/
public
void
close
()
throws
IOException
{
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
threadName
()
+
", called close()"
);
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", called close()"
);
}
closeInternal
(
true
);
// caller is initiating close
setConnectionState
(
cs_APP_CLOSED
);
...
...
@@ -1567,8 +1588,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/
private
void
closeInternal
(
boolean
selfInitiated
)
throws
IOException
{
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
threadName
()
+
", called closeInternal("
+
selfInitiated
+
")"
);
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", called closeInternal("
+
selfInitiated
+
")"
);
}
int
state
=
getConnectionState
();
...
...
@@ -1630,7 +1651,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
// closing since it is already in progress.
if
(
state
==
cs_SENT_CLOSE
)
{
if
(
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", close invoked again; state = "
+
getConnectionState
());
}
...
...
@@ -1653,7 +1674,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
}
}
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", after primary close; state = "
+
getConnectionState
());
}
...
...
@@ -1701,7 +1722,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/
void
waitForClose
(
boolean
rethrow
)
throws
IOException
{
if
(
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", waiting for close_notify or alert: state "
+
getConnectionState
());
}
...
...
@@ -1726,7 +1747,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
inrec
=
null
;
}
catch
(
IOException
e
)
{
if
(
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", Exception while waiting for close "
+
e
);
}
if
(
rethrow
)
{
...
...
@@ -1788,8 +1809,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
synchronized
private
void
handleException
(
Exception
e
,
boolean
resumable
)
throws
IOException
{
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
threadName
()
+
", handling exception: "
+
e
.
toString
());
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", handling exception: "
+
e
.
toString
());
}
// don't close the Socket in case of timeouts or interrupts if
...
...
@@ -1935,7 +1956,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
if
(
debug
!=
null
&&
(
Debug
.
isOn
(
"record"
)
||
Debug
.
isOn
(
"handshake"
)))
{
synchronized
(
System
.
out
)
{
System
.
out
.
print
(
thread
Name
());
System
.
out
.
print
(
Thread
.
currentThread
().
get
Name
());
System
.
out
.
print
(
", RECV "
+
protocolVersion
+
" ALERT: "
);
if
(
level
==
Alerts
.
alert_fatal
)
{
System
.
out
.
print
(
"fatal, "
);
...
...
@@ -2001,7 +2022,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
boolean
useDebug
=
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
);
if
(
useDebug
)
{
synchronized
(
System
.
out
)
{
System
.
out
.
print
(
thread
Name
());
System
.
out
.
print
(
Thread
.
currentThread
().
get
Name
());
System
.
out
.
print
(
", SEND "
+
protocolVersion
+
" ALERT: "
);
if
(
level
==
Alerts
.
alert_fatal
)
{
System
.
out
.
print
(
"fatal, "
);
...
...
@@ -2021,7 +2042,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
writeRecord
(
r
);
}
catch
(
IOException
e
)
{
if
(
useDebug
)
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", Exception sending alert: "
+
e
);
}
}
...
...
@@ -2118,14 +2139,15 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
return
host
;
}
synchronized
String
getRawHostname
()
{
return
rawHostname
;
}
// ONLY used by HttpsClient to setup the URI specified hostname
//
// Please NOTE that this method MUST be called before calling to
// SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter
// may override SNIHostName in the customized server name indication.
synchronized
public
void
setHost
(
String
host
)
{
this
.
host
=
host
;
this
.
rawHostname
=
host
;
this
.
serverNames
=
Utilities
.
addToSNIServerNameList
(
this
.
serverNames
,
this
.
host
);
}
/**
...
...
@@ -2186,7 +2208,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
}
catch
(
IOException
e
)
{
// handshake failed. log and return a nullSession
if
(
debug
!=
null
&&
Debug
.
isOn
(
"handshake"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", IOException in getSession(): "
+
e
);
}
}
...
...
@@ -2328,7 +2350,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
default
:
if
(
debug
!=
null
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", setUseClientMode() invoked in state = "
+
connectionState
);
}
...
...
@@ -2422,14 +2444,11 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/
public
void
setSoTimeout
(
int
timeout
)
throws
SocketException
{
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
thread
Name
()
+
System
.
out
.
println
(
Thread
.
currentThread
().
get
Name
()
+
", setSoTimeout("
+
timeout
+
") called"
);
}
if
(
self
==
this
)
{
super
.
setSoTimeout
(
timeout
);
}
else
{
self
.
setSoTimeout
(
timeout
);
}
super
.
setSoTimeout
(
timeout
);
}
/**
...
...
@@ -2474,6 +2493,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
// the super implementation does not handle the following parameters
params
.
setEndpointIdentificationAlgorithm
(
identificationProtocol
);
params
.
setAlgorithmConstraints
(
algorithmConstraints
);
params
.
setSNIMatchers
(
sniMatchers
);
params
.
setServerNames
(
serverNames
);
return
params
;
}
...
...
@@ -2487,9 +2508,25 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
// the super implementation does not handle the following parameters
identificationProtocol
=
params
.
getEndpointIdentificationAlgorithm
();
algorithmConstraints
=
params
.
getAlgorithmConstraints
();
List
<
SNIServerName
>
sniNames
=
params
.
getServerNames
();
if
(
sniNames
!=
null
)
{
serverNames
=
sniNames
;
}
Collection
<
SNIMatcher
>
matchers
=
params
.
getSNIMatchers
();
if
(
matchers
!=
null
)
{
sniMatchers
=
matchers
;
}
if
((
handshaker
!=
null
)
&&
!
handshaker
.
started
())
{
handshaker
.
setIdentificationProtocol
(
identificationProtocol
);
handshaker
.
setAlgorithmConstraints
(
algorithmConstraints
);
if
(
roleIsServer
)
{
handshaker
.
setSNIMatchers
(
sniMatchers
);
}
else
{
handshaker
.
setSNIServerNames
(
serverNames
);
}
}
}
...
...
@@ -2530,13 +2567,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
}
}
/**
* Return the name of the current thread. Utility method.
*/
private
static
String
threadName
()
{
return
Thread
.
currentThread
().
getName
();
}
/**
* Returns a printable representation of this end of the connection.
*/
...
...
@@ -2548,11 +2578,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
retval
.
append
(
sess
.
getCipherSuite
());
retval
.
append
(
": "
);
if
(
self
==
this
)
{
retval
.
append
(
super
.
toString
());
}
else
{
retval
.
append
(
self
.
toString
());
}
retval
.
append
(
super
.
toString
());
retval
.
append
(
"]"
);
return
retval
.
toString
();
...
...
src/share/classes/sun/security/ssl/ServerHandshaker.java
浏览文件 @
b80ffe55
...
...
@@ -276,6 +276,18 @@ final class ServerHandshaker extends Handshaker {
mesg
.
print
(
System
.
out
);
}
// check the server name indication if required
ServerNameExtension
clientHelloSNIExt
=
(
ServerNameExtension
)
mesg
.
extensions
.
get
(
ExtensionType
.
EXT_SERVER_NAME
);
if
(!
sniMatchers
.
isEmpty
())
{
// we do not reject client without SNI extension
if
(
clientHelloSNIExt
!=
null
&&
!
clientHelloSNIExt
.
isMatched
(
sniMatchers
))
{
fatalSE
(
Alerts
.
alert_unrecognized_name
,
"Unrecognized server name indication"
);
}
}
// Does the message include security renegotiation indication?
boolean
renegotiationIndicated
=
false
;
...
...
@@ -474,6 +486,26 @@ final class ServerHandshaker extends Handshaker {
}
}
// cannot resume session with different server name indication
if
(
resumingSession
)
{
List
<
SNIServerName
>
oldServerNames
=
previous
.
getRequestedServerNames
();
if
(
clientHelloSNIExt
!=
null
)
{
if
(!
clientHelloSNIExt
.
isIdentical
(
oldServerNames
))
{
resumingSession
=
false
;
}
}
else
if
(!
oldServerNames
.
isEmpty
())
{
resumingSession
=
false
;
}
if
(!
resumingSession
&&
debug
!=
null
&&
Debug
.
isOn
(
"handshake"
))
{
System
.
out
.
println
(
"The requested server name indication "
+
"is not identical to the previous one"
);
}
}
if
(
resumingSession
&&
(
doClientAuth
==
SSLEngineImpl
.
clauth_required
))
{
try
{
...
...
@@ -613,6 +645,14 @@ final class ServerHandshaker extends Handshaker {
// algorithms in chooseCipherSuite()
}
// set the server name indication in the session
List
<
SNIServerName
>
clientHelloSNI
=
Collections
.<
SNIServerName
>
emptyList
();
if
(
clientHelloSNIExt
!=
null
)
{
clientHelloSNI
=
clientHelloSNIExt
.
getServerNames
();
}
session
.
setRequestedServerNames
(
clientHelloSNI
);
// set the handshake session
setHandshakeSessionSE
(
session
);
...
...
@@ -654,6 +694,15 @@ final class ServerHandshaker extends Handshaker {
m1
.
extensions
.
add
(
serverHelloRI
);
}
if
(!
sniMatchers
.
isEmpty
()
&&
clientHelloSNIExt
!=
null
)
{
// When resuming a session, the server MUST NOT include a
// server_name extension in the server hello.
if
(!
resumingSession
)
{
ServerNameExtension
serverHelloSNI
=
new
ServerNameExtension
();
m1
.
extensions
.
add
(
serverHelloSNI
);
}
}
if
(
debug
!=
null
&&
Debug
.
isOn
(
"handshake"
))
{
m1
.
print
(
System
.
out
);
System
.
out
.
println
(
"Cipher suite: "
+
session
.
getSuite
());
...
...
src/share/classes/sun/security/ssl/SunJSSE.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 1999, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 201
2
, 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
...
...
@@ -103,7 +103,7 @@ public abstract class SunJSSE extends java.security.Provider {
// standard constructor
protected
SunJSSE
()
{
super
(
"SunJSSE"
,
1.
7
d
,
info
);
super
(
"SunJSSE"
,
1.
8
d
,
info
);
subclassCheck
();
if
(
Boolean
.
TRUE
.
equals
(
fips
))
{
throw
new
ProviderException
...
...
src/share/classes/sun/security/ssl/Utilities.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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
sun.security.ssl
;
import
javax.net.ssl.*
;
import
java.util.*
;
import
sun.net.util.IPAddressUtil
;
/**
* A utility class to share the static methods.
*/
final
class
Utilities
{
/**
* Puts {@code hostname} into the {@code serverNames} list.
* <P>
* If the {@code serverNames} does not look like a legal FQDN, it will
* not be put into the returned list.
* <P>
* Note that the returned list does not allow duplicated name type.
*
* @return a list of {@link SNIServerName}
*/
static
List
<
SNIServerName
>
addToSNIServerNameList
(
List
<
SNIServerName
>
serverNames
,
String
hostname
)
{
SNIHostName
sniHostName
=
rawToSNIHostName
(
hostname
);
if
(
sniHostName
==
null
)
{
return
serverNames
;
}
int
size
=
serverNames
.
size
();
List
<
SNIServerName
>
sniList
=
(
size
!=
0
)
?
new
ArrayList
<
SNIServerName
>(
serverNames
)
:
new
ArrayList
<
SNIServerName
>(
1
);
boolean
reset
=
false
;
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
SNIServerName
serverName
=
sniList
.
get
(
i
);
if
(
serverName
.
getType
()
==
StandardConstants
.
SNI_HOST_NAME
)
{
sniList
.
set
(
i
,
sniHostName
);
if
(
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", the previous server name in SNI ("
+
serverName
+
") was replaced with ("
+
sniHostName
+
")"
);
}
reset
=
true
;
break
;
}
}
if
(!
reset
)
{
sniList
.
add
(
sniHostName
);
}
return
Collections
.<
SNIServerName
>
unmodifiableList
(
sniList
);
}
/**
* Converts string hostname to {@code SNIHostName}.
* <P>
* Note that to check whether a hostname is a valid domain name, we cannot
* use the hostname resolved from name services. For virtual hosting,
* multiple hostnames may be bound to the same IP address, so the hostname
* resolved from name services is not always reliable.
*
* @param hostname
* the raw hostname
* @return an instance of {@link SNIHostName}, or null if the hostname does
* not look like a FQDN
*/
private
static
SNIHostName
rawToSNIHostName
(
String
hostname
)
{
SNIHostName
sniHostName
=
null
;
if
(
hostname
!=
null
&&
hostname
.
indexOf
(
'.'
)
>
0
&&
!
hostname
.
endsWith
(
"."
)
&&
!
IPAddressUtil
.
isIPv4LiteralAddress
(
hostname
)
&&
!
IPAddressUtil
.
isIPv6LiteralAddress
(
hostname
))
{
try
{
sniHostName
=
new
SNIHostName
(
hostname
);
}
catch
(
IllegalArgumentException
iae
)
{
// don't bother to handle illegal host_name
if
(
Debug
.
isOn
(
"ssl"
))
{
System
.
out
.
println
(
Thread
.
currentThread
().
getName
()
+
", \""
+
hostname
+
"\" "
+
"is not a legal HostName for server name indication"
);
}
}
}
return
sniHostName
;
}
}
src/share/classes/sun/security/ssl/X509KeyManagerImpl.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 2004, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 201
2
, 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
...
...
@@ -128,13 +128,35 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
public
String
chooseServerAlias
(
String
keyType
,
Principal
[]
issuers
,
Socket
socket
)
{
return
chooseAlias
(
getKeyTypes
(
keyType
),
issuers
,
CheckType
.
SERVER
,
getAlgorithmConstraints
(
socket
));
getAlgorithmConstraints
(
socket
),
X509TrustManagerImpl
.
getRequestedServerNames
(
socket
),
"HTTPS"
);
// The SNI HostName is a fully qualified domain name.
// The certificate selection scheme for SNI HostName
// is similar to HTTPS endpoint identification scheme
// implemented in this provider.
//
// Using HTTPS endpoint identification scheme to guide
// the selection of an appropriate authentication
// certificate according to requested SNI extension.
//
// It is not a really HTTPS endpoint identification.
}
public
String
chooseEngineServerAlias
(
String
keyType
,
Principal
[]
issuers
,
SSLEngine
engine
)
{
return
chooseAlias
(
getKeyTypes
(
keyType
),
issuers
,
CheckType
.
SERVER
,
getAlgorithmConstraints
(
engine
));
getAlgorithmConstraints
(
engine
),
X509TrustManagerImpl
.
getRequestedServerNames
(
engine
),
"HTTPS"
);
// The SNI HostName is a fully qualified domain name.
// The certificate selection scheme for SNI HostName
// is similar to HTTPS endpoint identification scheme
// implemented in this provider.
//
// Using HTTPS endpoint identification scheme to guide
// the selection of an appropriate authentication
// certificate according to requested SNI extension.
//
// It is not a really HTTPS endpoint identification.
}
public
String
[]
getClientAliases
(
String
keyType
,
Principal
[]
issuers
)
{
...
...
@@ -321,8 +343,8 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
* The algorithm we use is:
* . scan through all the aliases in all builders in order
* . as soon as we find a perfect match, return
* (i.e. a match with a cert that has appropriate key usage
* and is not expired).
* (i.e. a match with a cert that has appropriate key usage
,
*
qualified endpoint identity,
and is not expired).
* . if we do not find a perfect match, keep looping and remember
* the imperfect matches
* . at the end, sort the imperfect matches. we prefer expired certs
...
...
@@ -331,6 +353,15 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
*/
private
String
chooseAlias
(
List
<
KeyType
>
keyTypeList
,
Principal
[]
issuers
,
CheckType
checkType
,
AlgorithmConstraints
constraints
)
{
return
chooseAlias
(
keyTypeList
,
issuers
,
checkType
,
constraints
,
null
,
null
);
}
private
String
chooseAlias
(
List
<
KeyType
>
keyTypeList
,
Principal
[]
issuers
,
CheckType
checkType
,
AlgorithmConstraints
constraints
,
List
<
SNIServerName
>
requestedServerNames
,
String
idAlgorithm
)
{
if
(
keyTypeList
==
null
||
keyTypeList
.
isEmpty
())
{
return
null
;
}
...
...
@@ -340,7 +371,8 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
for
(
int
i
=
0
,
n
=
builders
.
size
();
i
<
n
;
i
++)
{
try
{
List
<
EntryStatus
>
results
=
getAliases
(
i
,
keyTypeList
,
issuerSet
,
false
,
checkType
,
constraints
);
issuerSet
,
false
,
checkType
,
constraints
,
requestedServerNames
,
idAlgorithm
);
if
(
results
!=
null
)
{
// the results will either be a single perfect match
// or 1 or more imperfect matches
...
...
@@ -394,7 +426,8 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
for
(
int
i
=
0
,
n
=
builders
.
size
();
i
<
n
;
i
++)
{
try
{
List
<
EntryStatus
>
results
=
getAliases
(
i
,
keyTypeList
,
issuerSet
,
true
,
checkType
,
constraints
);
issuerSet
,
true
,
checkType
,
constraints
,
null
,
null
);
if
(
results
!=
null
)
{
if
(
allResults
==
null
)
{
allResults
=
new
ArrayList
<
EntryStatus
>();
...
...
@@ -504,7 +537,9 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
// first check extensions, if they match, check expiration
// note: we may want to move this code into the sun.security.validator
// package
CheckResult
check
(
X509Certificate
cert
,
Date
date
)
{
CheckResult
check
(
X509Certificate
cert
,
Date
date
,
List
<
SNIServerName
>
serverNames
,
String
idAlgorithm
)
{
if
(
this
==
NONE
)
{
return
CheckResult
.
OK
;
}
...
...
@@ -553,11 +588,11 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
return
CheckResult
.
EXTENSION_MISMATCH
;
}
// For servers, also require key agreement.
// This is not totally accurate as the keyAgreement
bit
//
is only necessary for static ECDH key exchange and
//
not ephemeral ECDH. We leave it in for now until
//
there are signs that this check causes problems
// for real world EC certificates.
// This is not totally accurate as the keyAgreement
//
bit is only necessary for static ECDH key
//
exchange and not ephemeral ECDH. We leave it in
//
for now until there are signs that this check
//
causes problems
for real world EC certificates.
if
((
this
==
SERVER
)
&&
(
getBit
(
ku
,
4
)
==
false
))
{
return
CheckResult
.
EXTENSION_MISMATCH
;
}
...
...
@@ -571,10 +606,50 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
try
{
cert
.
checkValidity
(
date
);
return
CheckResult
.
OK
;
}
catch
(
CertificateException
e
)
{
return
CheckResult
.
EXPIRED
;
}
if
(
serverNames
!=
null
&&
!
serverNames
.
isEmpty
())
{
for
(
SNIServerName
serverName
:
serverNames
)
{
if
(
serverName
.
getType
()
==
StandardConstants
.
SNI_HOST_NAME
)
{
if
(!(
serverName
instanceof
SNIHostName
))
{
try
{
serverName
=
new
SNIHostName
(
serverName
.
getEncoded
());
}
catch
(
IllegalArgumentException
iae
)
{
// unlikely to happen, just in case ...
if
(
useDebug
)
{
debug
.
println
(
"Illegal server name: "
+
serverName
);
}
return
CheckResult
.
INSENSITIVE
;
}
}
String
hostname
=
((
SNIHostName
)
serverName
).
getAsciiName
();
try
{
X509TrustManagerImpl
.
checkIdentity
(
hostname
,
cert
,
idAlgorithm
);
}
catch
(
CertificateException
e
)
{
if
(
useDebug
)
{
debug
.
println
(
"Certificate identity does not match "
+
"Server Name Inidication (SNI): "
+
hostname
);
}
return
CheckResult
.
INSENSITIVE
;
}
break
;
}
}
}
return
CheckResult
.
OK
;
}
}
...
...
@@ -583,6 +658,7 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
// for sorting, i.e. OK is best, followed by EXPIRED and EXTENSION_MISMATCH
private
static
enum
CheckResult
{
OK
,
// ok or not checked
INSENSITIVE
,
// server name indication insensitive
EXPIRED
,
// extensions valid but cert expired
EXTENSION_MISMATCH
,
// extensions invalid (expiration not checked)
}
...
...
@@ -616,7 +692,10 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
private
List
<
EntryStatus
>
getAliases
(
int
builderIndex
,
List
<
KeyType
>
keyTypes
,
Set
<
Principal
>
issuerSet
,
boolean
findAll
,
CheckType
checkType
,
AlgorithmConstraints
constraints
)
throws
Exception
{
AlgorithmConstraints
constraints
,
List
<
SNIServerName
>
requestedServerNames
,
String
idAlgorithm
)
throws
Exception
{
Builder
builder
=
builders
.
get
(
builderIndex
);
KeyStore
ks
=
builder
.
getKeyStore
();
List
<
EntryStatus
>
results
=
null
;
...
...
@@ -699,7 +778,8 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
date
=
new
Date
();
}
CheckResult
checkResult
=
checkType
.
check
((
X509Certificate
)
chain
[
0
],
date
);
checkType
.
check
((
X509Certificate
)
chain
[
0
],
date
,
requestedServerNames
,
idAlgorithm
);
EntryStatus
status
=
new
EntryStatus
(
builderIndex
,
keyIndex
,
alias
,
chain
,
checkResult
);
...
...
src/share/classes/sun/security/ssl/X509TrustManagerImpl.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 1997, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
2
, 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
...
...
@@ -28,15 +28,14 @@ package sun.security.ssl;
import
java.net.Socket
;
import
javax.net.ssl.SSLSession
;
import
java.nio.charset.StandardCharsets
;
import
java.util.*
;
import
java.security.*
;
import
java.security.cert.*
;
import
javax.net.ssl.*
;
import
sun.security.validator.*
;
import
sun.security.util.HostnameChecker
;
/**
...
...
@@ -199,8 +198,8 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
String
identityAlg
=
sslSocket
.
getSSLParameters
().
getEndpointIdentificationAlgorithm
();
if
(
identityAlg
!=
null
&&
identityAlg
.
length
()
!=
0
)
{
String
hostname
=
session
.
getPeerHost
();
checkIdentity
(
hostname
,
chain
[
0
],
identityAlg
);
checkIdentity
(
session
,
chain
[
0
],
identityAlg
,
isClient
,
getRequestedServerNames
(
socket
)
);
}
// create the algorithm constraints
...
...
@@ -251,8 +250,8 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
String
identityAlg
=
engine
.
getSSLParameters
().
getEndpointIdentificationAlgorithm
();
if
(
identityAlg
!=
null
&&
identityAlg
.
length
()
!=
0
)
{
String
hostname
=
session
.
getPeerHost
();
checkIdentity
(
hostname
,
chain
[
0
],
identityAlg
);
checkIdentity
(
session
,
chain
[
0
],
identityAlg
,
isClient
,
getRequestedServerNames
(
engine
)
);
}
// create the algorithm constraints
...
...
@@ -329,6 +328,117 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
}
// Get string representation of HostName from a list of server names.
//
// We are only accepting host_name name type in the list.
private
static
String
getHostNameInSNI
(
List
<
SNIServerName
>
sniNames
)
{
SNIHostName
hostname
=
null
;
for
(
SNIServerName
sniName
:
sniNames
)
{
if
(
sniName
.
getType
()
!=
StandardConstants
.
SNI_HOST_NAME
)
{
continue
;
}
if
(
sniName
instanceof
SNIHostName
)
{
hostname
=
(
SNIHostName
)
sniName
;
}
else
{
try
{
hostname
=
new
SNIHostName
(
sniName
.
getEncoded
());
}
catch
(
IllegalArgumentException
iae
)
{
// unlikely to happen, just in case ...
if
((
debug
!=
null
)
&&
Debug
.
isOn
(
"trustmanager"
))
{
byte
[]
encoded
=
hostname
.
getEncoded
();
System
.
out
.
println
(
"Illegal server name: "
+
sniName
);
}
}
}
// no more than server name of the same name type
break
;
}
if
(
hostname
!=
null
)
{
return
hostname
.
getAsciiName
();
}
return
null
;
}
// Also used by X509KeyManagerImpl
static
List
<
SNIServerName
>
getRequestedServerNames
(
Socket
socket
)
{
if
(
socket
!=
null
&&
socket
.
isConnected
()
&&
socket
instanceof
SSLSocket
)
{
SSLSocket
sslSocket
=
(
SSLSocket
)
socket
;
SSLSession
session
=
sslSocket
.
getHandshakeSession
();
if
(
session
!=
null
&&
(
session
instanceof
ExtendedSSLSession
))
{
ExtendedSSLSession
extSession
=
(
ExtendedSSLSession
)
session
;
return
extSession
.
getRequestedServerNames
();
}
}
return
Collections
.<
SNIServerName
>
emptyList
();
}
// Also used by X509KeyManagerImpl
static
List
<
SNIServerName
>
getRequestedServerNames
(
SSLEngine
engine
)
{
if
(
engine
!=
null
)
{
SSLSession
session
=
engine
.
getHandshakeSession
();
if
(
session
!=
null
&&
(
session
instanceof
ExtendedSSLSession
))
{
ExtendedSSLSession
extSession
=
(
ExtendedSSLSession
)
session
;
return
extSession
.
getRequestedServerNames
();
}
}
return
Collections
.<
SNIServerName
>
emptyList
();
}
/*
* Per RFC 6066, if an application negotiates a server name using an
* application protocol and then upgrades to TLS, and if a server_name
* extension is sent, then the extension SHOULD contain the same name
* that was negotiated in the application protocol. If the server_name
* is established in the TLS session handshake, the client SHOULD NOT
* attempt to request a different server name at the application layer.
*
* According to the above spec, we only need to check either the identity
* in server_name extension or the peer host of the connection. Peer host
* is not always a reliable fully qualified domain name. The HostName in
* server_name extension is more reliable than peer host. So we prefer
* the identity checking aginst the server_name extension if present, and
* may failove to peer host checking.
*/
private
static
void
checkIdentity
(
SSLSession
session
,
X509Certificate
cert
,
String
algorithm
,
boolean
isClient
,
List
<
SNIServerName
>
sniNames
)
throws
CertificateException
{
boolean
identifiable
=
false
;
String
peerHost
=
session
.
getPeerHost
();
if
(
isClient
)
{
String
hostname
=
getHostNameInSNI
(
sniNames
);
if
(
hostname
!=
null
)
{
try
{
checkIdentity
(
hostname
,
cert
,
algorithm
);
identifiable
=
true
;
}
catch
(
CertificateException
ce
)
{
if
(
hostname
.
equalsIgnoreCase
(
peerHost
))
{
throw
ce
;
}
// otherwisw, failover to check peer host
}
}
}
if
(!
identifiable
)
{
checkIdentity
(
peerHost
,
cert
,
algorithm
);
}
}
/*
* Identify the peer by its certificate and hostname.
*
...
...
test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/LargePacket.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 2006, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 201
2
, 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
...
...
@@ -21,13 +21,18 @@
* questions.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
*
* @bug 6388456
* @summary Need adjustable TLS max record size for interoperability
* with non-compliant
* @run main/othervm
-Djsse.enableCBCProtection=false
LargePacket
* @run main/othervm LargePacket
*
* @author Xuelei Fan
*/
...
...
@@ -83,12 +88,12 @@ public class LargePacket extends SSLEngineService {
SocketChannel
sc
=
ssc
.
accept
();
// Complete connection.
while
(!
sc
.
finishConnect
()
)
{
while
(!
sc
.
finishConnect
())
{
// waiting for the connection completed.
}
// handshaking
handshaking
(
ssle
,
sc
);
handshaking
(
ssle
,
sc
,
null
);
// receive application data
receive
(
ssle
,
sc
);
...
...
@@ -131,7 +136,7 @@ public class LargePacket extends SSLEngineService {
}
// handshaking
handshaking
(
ssle
,
sc
);
handshaking
(
ssle
,
sc
,
null
);
// send out application data
deliver
(
ssle
,
sc
);
...
...
@@ -169,6 +174,8 @@ public class LargePacket extends SSLEngineService {
* Fork off the other side, then do your work.
*/
LargePacket
()
throws
Exception
{
super
(
"../../../../../etc"
);
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
...
...
test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/SSLEngineService.java
浏览文件 @
b80ffe55
/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006,
2012,
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
...
...
@@ -22,8 +22,6 @@
*/
/*
*
*
* @bug 6388456
* @summary Need adjustable TLS max record size for interoperability
* with non-compliant stacks
...
...
@@ -42,17 +40,31 @@ import java.nio.channels.*;
public
class
SSLEngineService
{
private
static
String
pathToStores
=
"../../../../../etc"
;
private
static
String
keyStoreFile
=
"keystore"
;
private
static
String
trustStoreFile
=
"truststore"
;
private
static
char
[]
passphrase
=
"passphrase"
.
toCharArray
();
private
static
String
keyFilename
=
private
String
pathToStores
;
private
String
keyFilename
;
private
String
trustFilename
;
protected
SSLEngineService
()
{
init
(
"../../../../../etc"
);
}
protected
SSLEngineService
(
String
pathToStores
)
{
init
(
pathToStores
);
}
private
void
init
(
String
pathToStores
)
{
this
.
pathToStores
=
pathToStores
;
this
.
keyFilename
=
System
.
getProperty
(
"test.src"
,
"./"
)
+
"/"
+
pathToStores
+
"/"
+
keyStoreFile
;
private
static
String
trustFilename
=
this
.
trustFilename
=
System
.
getProperty
(
"test.src"
,
"./"
)
+
"/"
+
pathToStores
+
"/"
+
trustStoreFile
;
}
// deliver local application data.
protected
static
void
deliver
(
SSLEngine
ssle
,
SocketChannel
sc
)
...
...
@@ -143,9 +155,12 @@ public class SSLEngineService {
ByteBuffer
peerNetData
=
ByteBuffer
.
allocate
(
netBufferMax
/
2
);
int
received
=
-
1
;
boolean
needToReadMore
=
true
;
while
(
received
!=
0
)
{
if
(
ssle
.
isInboundDone
()
||
sc
.
read
(
peerNetData
)
<
0
)
{
break
;
if
(
needToReadMore
)
{
if
(
ssle
.
isInboundDone
()
||
sc
.
read
(
peerNetData
)
<
0
)
{
break
;
}
}
peerNetData
.
flip
();
...
...
@@ -186,6 +201,8 @@ public class SSLEngineService {
" bytes large packet "
);
}
needToReadMore
=
(
peerNetData
.
position
()
>
0
)
?
false
:
true
;
break
;
case
BUFFER_OVERFLOW
:
...
...
@@ -206,6 +223,8 @@ public class SSLEngineService {
" bytes for BUFFER_UNDERFLOW"
);
peerNetData
=
enlargeBuffer
(
peerNetData
,
size
);
}
needToReadMore
=
true
;
break
;
default
:
// CLOSED :
...
...
@@ -215,8 +234,8 @@ public class SSLEngineService {
}
}
protected
static
void
handshaking
(
SSLEngine
ssle
,
SocketChannel
sc
)
throws
Exception
{
protected
static
void
handshaking
(
SSLEngine
ssle
,
SocketChannel
sc
,
ByteBuffer
additional
)
throws
Exception
{
int
appBufferMax
=
ssle
.
getSession
().
getApplicationBufferSize
();
int
netBufferMax
=
ssle
.
getSession
().
getPacketBufferSize
();
...
...
@@ -232,15 +251,39 @@ public class SSLEngineService {
SSLEngineResult
.
HandshakeStatus
hs
=
ssle
.
getHandshakeStatus
();
// start handshaking from unwrap
byte
[]
buffer
=
new
byte
[
0xFF
];
boolean
underflow
=
false
;
do
{
switch
(
hs
)
{
case
NEED_UNWRAP
:
if
(
peerNetData
.
position
()
==
0
)
{
if
(
additional
!=
null
&&
additional
.
hasRemaining
())
{
do
{
int
len
=
Math
.
min
(
buffer
.
length
,
peerNetData
.
remaining
());
len
=
Math
.
min
(
len
,
additional
.
remaining
());
if
(
len
!=
0
)
{
additional
.
get
(
buffer
,
0
,
len
);
peerNetData
.
put
(
buffer
,
0
,
len
);
}
}
while
(
peerNetData
.
remaining
()
>
0
&&
additional
.
hasRemaining
());
}
else
{
if
(
sc
.
read
(
peerNetData
)
<
0
)
{
ssle
.
closeInbound
();
return
;
}
}
}
if
(
underflow
)
{
if
(
sc
.
read
(
peerNetData
)
<
0
)
{
ssle
.
closeInbound
();
return
;
}
underflow
=
false
;
}
peerNetData
.
flip
();
...
...
@@ -259,6 +302,8 @@ public class SSLEngineService {
size
+
" bytes for BUFFER_UNDERFLOW"
);
peerNetData
=
enlargeBuffer
(
peerNetData
,
size
);
}
underflow
=
true
;
break
;
case
BUFFER_OVERFLOW
:
// maybe need to enlarge the peer application data buffer.
...
...
@@ -339,7 +384,7 @@ public class SSLEngineService {
/*
* Create an initialized SSLContext to use for this test.
*/
protected
static
SSLEngine
createSSLEngine
(
boolean
mode
)
throws
Exception
{
protected
SSLEngine
createSSLEngine
(
boolean
mode
)
throws
Exception
{
SSLEngine
ssle
;
...
...
test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorer.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @library ../NewAPIs/SSLEngine ../../../../templates
* @build SSLEngineService SSLCapabilities SSLExplorer
* @run main/othervm SSLEngineExplorer SSLv2Hello,SSLv3
* @run main/othervm SSLEngineExplorer SSLv3
* @run main/othervm SSLEngineExplorer TLSv1
* @run main/othervm SSLEngineExplorer TLSv1.1
* @run main/othervm SSLEngineExplorer TLSv1.2
*/
import
javax.net.ssl.*
;
import
java.nio.*
;
import
java.net.*
;
import
java.util.*
;
import
java.nio.channels.*
;
public
class
SSLEngineExplorer
extends
SSLEngineService
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
true
;
// Is the server ready to serve?
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
// create SSLEngine.
SSLEngine
ssle
=
createSSLEngine
(
false
);
// Create a server socket channel.
InetSocketAddress
isa
=
new
InetSocketAddress
(
InetAddress
.
getLocalHost
(),
serverPort
);
ServerSocketChannel
ssc
=
ServerSocketChannel
.
open
();
ssc
.
socket
().
bind
(
isa
);
serverPort
=
ssc
.
socket
().
getLocalPort
();
// Signal Client, we're ready for his connect.
serverReady
=
true
;
// Accept a socket channel.
SocketChannel
sc
=
ssc
.
accept
();
sc
.
configureBlocking
(
false
);
// Complete connection.
while
(!
sc
.
finishConnect
())
{
Thread
.
sleep
(
50
);
// waiting for the connection completed.
}
ByteBuffer
buffer
=
ByteBuffer
.
allocate
(
0xFF
);
int
position
=
0
;
SSLCapabilities
capabilities
=
null
;
// Read the header of TLS record
buffer
.
limit
(
SSLExplorer
.
RECORD_HEADER_SIZE
);
while
(
position
<
SSLExplorer
.
RECORD_HEADER_SIZE
)
{
int
n
=
sc
.
read
(
buffer
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
buffer
.
flip
();
int
recordLength
=
SSLExplorer
.
getRequiredSize
(
buffer
);
if
(
buffer
.
capacity
()
<
recordLength
)
{
ByteBuffer
oldBuffer
=
buffer
;
buffer
=
ByteBuffer
.
allocate
(
recordLength
);
buffer
.
put
(
oldBuffer
);
}
buffer
.
position
(
SSLExplorer
.
RECORD_HEADER_SIZE
);
buffer
.
limit
(
buffer
.
capacity
());
while
(
position
<
recordLength
)
{
int
n
=
sc
.
read
(
buffer
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
buffer
.
flip
();
capabilities
=
SSLExplorer
.
explore
(
buffer
);
if
(
capabilities
!=
null
)
{
System
.
out
.
println
(
"Record version: "
+
capabilities
.
getRecordVersion
());
System
.
out
.
println
(
"Hello version: "
+
capabilities
.
getHelloVersion
());
}
// handshaking
handshaking
(
ssle
,
sc
,
buffer
);
// receive application data
receive
(
ssle
,
sc
);
// send out application data
deliver
(
ssle
,
sc
);
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
ssle
.
getSession
();
checkCapabilities
(
capabilities
,
session
);
// close the socket channel.
sc
.
close
();
ssc
.
close
();
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
// create SSLEngine.
SSLEngine
ssle
=
createSSLEngine
(
true
);
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
// Create a non-blocking socket channel.
SocketChannel
sc
=
SocketChannel
.
open
();
sc
.
configureBlocking
(
false
);
InetSocketAddress
isa
=
new
InetSocketAddress
(
InetAddress
.
getLocalHost
(),
serverPort
);
sc
.
connect
(
isa
);
// Complete connection.
while
(!
sc
.
finishConnect
()
)
{
Thread
.
sleep
(
50
);
// waiting for the connection completed.
}
// enable the specified TLS protocol
ssle
.
setEnabledProtocols
(
supportedProtocols
);
// handshaking
handshaking
(
ssle
,
sc
,
null
);
// send out application data
deliver
(
ssle
,
sc
);
// receive application data
receive
(
ssle
,
sc
);
// close the socket channel.
sc
.
close
();
}
void
checkCapabilities
(
SSLCapabilities
capabilities
,
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(!
sessionSNI
.
equals
(
capabilities
.
getServerNames
()))
{
throw
new
Exception
(
"server name indication does not match capabilities"
);
}
}
private
static
String
[]
supportedProtocols
;
// supported protocols
private
static
void
parseArguments
(
String
[]
args
)
{
supportedProtocols
=
args
[
0
].
split
(
","
);
}
/*
* =============================================================
* The remainder is just support stuff
*/
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
// use any free port by default
volatile
int
serverPort
=
0
;
public
static
void
main
(
String
args
[])
throws
Exception
{
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Get the customized arguments.
*/
parseArguments
(
args
);
new
SSLEngineExplorer
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLEngineExplorer
()
throws
Exception
{
super
(
"../../../../etc"
);
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
*
* If the main thread excepted, that propagates back
* immediately. If the other thread threw an exception, we
* should report back.
*/
if
(
serverException
!=
null
)
{
System
.
out
.
print
(
"Server Exception:"
);
throw
serverException
;
}
if
(
clientException
!=
null
)
{
System
.
out
.
print
(
"Client Exception:"
);
throw
clientException
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
System
.
err
.
println
(
e
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
doServerSide
();
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
doClientSide
();
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @library ../NewAPIs/SSLEngine ../../../../templates
* @build SSLEngineService SSLCapabilities SSLExplorer
* @run main/othervm SSLEngineExplorerMatchedSNI www.example.com
* www\.example\.com
* @run main/othervm SSLEngineExplorerMatchedSNI www.example.com
* www\.example\.(com|org)
* @run main/othervm SSLEngineExplorerMatchedSNI example.com
* (.*\.)*example\.(com|org)
* @run main/othervm SSLEngineExplorerMatchedSNI www.example.com
* (.*\.)*example\.(com|org)
* @run main/othervm SSLEngineExplorerMatchedSNI www.us.example.com
* (.*\.)*example\.(com|org)
*/
import
javax.net.ssl.*
;
import
java.nio.*
;
import
java.net.*
;
import
java.util.*
;
import
java.nio.channels.*
;
public
class
SSLEngineExplorerMatchedSNI
extends
SSLEngineService
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
false
;
// Is the server ready to serve?
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
// create SSLEngine.
SSLEngine
ssle
=
createSSLEngine
(
false
);
// Create a server socket channel.
InetSocketAddress
isa
=
new
InetSocketAddress
(
InetAddress
.
getLocalHost
(),
serverPort
);
ServerSocketChannel
ssc
=
ServerSocketChannel
.
open
();
ssc
.
socket
().
bind
(
isa
);
serverPort
=
ssc
.
socket
().
getLocalPort
();
// Signal Client, we're ready for his connect.
serverReady
=
true
;
// Accept a socket channel.
SocketChannel
sc
=
ssc
.
accept
();
// Complete connection.
while
(!
sc
.
finishConnect
())
{
Thread
.
sleep
(
50
);
// waiting for the connection completed.
}
ByteBuffer
buffer
=
ByteBuffer
.
allocate
(
0xFF
);
int
position
=
0
;
SSLCapabilities
capabilities
=
null
;
// Read the header of TLS record
buffer
.
limit
(
SSLExplorer
.
RECORD_HEADER_SIZE
);
while
(
position
<
SSLExplorer
.
RECORD_HEADER_SIZE
)
{
int
n
=
sc
.
read
(
buffer
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
buffer
.
flip
();
int
recordLength
=
SSLExplorer
.
getRequiredSize
(
buffer
);
if
(
buffer
.
capacity
()
<
recordLength
)
{
ByteBuffer
oldBuffer
=
buffer
;
buffer
=
ByteBuffer
.
allocate
(
recordLength
);
buffer
.
put
(
oldBuffer
);
}
buffer
.
position
(
SSLExplorer
.
RECORD_HEADER_SIZE
);
buffer
.
limit
(
buffer
.
capacity
());
while
(
position
<
recordLength
)
{
int
n
=
sc
.
read
(
buffer
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
buffer
.
flip
();
capabilities
=
SSLExplorer
.
explore
(
buffer
);
if
(
capabilities
!=
null
)
{
System
.
out
.
println
(
"Record version: "
+
capabilities
.
getRecordVersion
());
System
.
out
.
println
(
"Hello version: "
+
capabilities
.
getHelloVersion
());
}
// enable server name indication checking
SNIMatcher
matcher
=
SNIHostName
.
createSNIMatcher
(
serverAcceptableHostname
);
Collection
<
SNIMatcher
>
matchers
=
new
ArrayList
<>(
1
);
matchers
.
add
(
matcher
);
SSLParameters
params
=
ssle
.
getSSLParameters
();
params
.
setSNIMatchers
(
matchers
);
ssle
.
setSSLParameters
(
params
);
// handshaking
handshaking
(
ssle
,
sc
,
buffer
);
// receive application data
receive
(
ssle
,
sc
);
// send out application data
deliver
(
ssle
,
sc
);
// check server name indication
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
ssle
.
getSession
();
checkCapabilities
(
capabilities
,
session
);
// close the socket channel.
sc
.
close
();
ssc
.
close
();
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
// create SSLEngine.
SSLEngine
ssle
=
createSSLEngine
(
true
);
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
// Create a non-blocking socket channel.
SocketChannel
sc
=
SocketChannel
.
open
();
sc
.
configureBlocking
(
false
);
InetSocketAddress
isa
=
new
InetSocketAddress
(
InetAddress
.
getLocalHost
(),
serverPort
);
sc
.
connect
(
isa
);
// Complete connection.
while
(!
sc
.
finishConnect
()
)
{
Thread
.
sleep
(
50
);
// waiting for the connection completed.
}
SNIHostName
serverName
=
new
SNIHostName
(
clientRequestedHostname
);
List
<
SNIServerName
>
serverNames
=
new
ArrayList
<>(
1
);
serverNames
.
add
(
serverName
);
SSLParameters
params
=
ssle
.
getSSLParameters
();
params
.
setServerNames
(
serverNames
);
ssle
.
setSSLParameters
(
params
);
// handshaking
handshaking
(
ssle
,
sc
,
null
);
// send out application data
deliver
(
ssle
,
sc
);
// receive application data
receive
(
ssle
,
sc
);
// check server name indication
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
ssle
.
getSession
();
checkSNIInSession
(
session
);
// close the socket channel.
sc
.
close
();
}
void
checkCapabilities
(
SSLCapabilities
capabilities
,
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(!
sessionSNI
.
equals
(
capabilities
.
getServerNames
()))
{
for
(
SNIServerName
sni
:
sessionSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
List
<
SNIServerName
>
capaSNI
=
capabilities
.
getServerNames
();
for
(
SNIServerName
sni
:
capaSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
throw
new
Exception
(
"server name indication does not match capabilities"
);
}
checkSNIInSession
(
session
);
}
void
checkSNIInSession
(
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(
sessionSNI
.
isEmpty
())
{
throw
new
Exception
(
"unexpected empty request server name indication"
);
}
if
(
sessionSNI
.
size
()
!=
1
)
{
throw
new
Exception
(
"unexpected request server name indication"
);
}
SNIServerName
serverName
=
sessionSNI
.
get
(
0
);
if
(!(
serverName
instanceof
SNIHostName
))
{
throw
new
Exception
(
"unexpected instance of request server name indication"
);
}
String
hostname
=
((
SNIHostName
)
serverName
).
getAsciiName
();
if
(!
clientRequestedHostname
.
equalsIgnoreCase
(
hostname
))
{
throw
new
Exception
(
"unexpected request server name indication value"
);
}
}
private
static
String
clientRequestedHostname
;
private
static
String
serverAcceptableHostname
;
private
static
void
parseArguments
(
String
[]
args
)
{
clientRequestedHostname
=
args
[
0
];
serverAcceptableHostname
=
args
[
1
];
}
/*
* =============================================================
* The remainder is just support stuff
*/
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
// use any free port by default
volatile
int
serverPort
=
0
;
public
static
void
main
(
String
args
[])
throws
Exception
{
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Get the customized arguments.
*/
parseArguments
(
args
);
new
SSLEngineExplorerMatchedSNI
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLEngineExplorerMatchedSNI
()
throws
Exception
{
super
(
"../../../../etc"
);
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
*
* If the main thread excepted, that propagates back
* immediately. If the other thread threw an exception, we
* should report back.
*/
if
(
serverException
!=
null
)
{
System
.
out
.
print
(
"Server Exception:"
);
throw
serverException
;
}
if
(
clientException
!=
null
)
{
System
.
out
.
print
(
"Client Exception:"
);
throw
clientException
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
System
.
err
.
println
(
e
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
doServerSide
();
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
doClientSide
();
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @library ../NewAPIs/SSLEngine ../../../../templates
* @build SSLEngineService SSLCapabilities SSLExplorer
* @run main/othervm SSLEngineExplorerUnmatchedSNI www.example.com
* www\.example\.org
*/
import
javax.net.ssl.*
;
import
java.io.*
;
import
java.nio.*
;
import
java.net.*
;
import
java.util.*
;
import
java.nio.channels.*
;
public
class
SSLEngineExplorerUnmatchedSNI
extends
SSLEngineService
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
false
;
// Is the server ready to serve?
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
// create SSLEngine.
SSLEngine
ssle
=
createSSLEngine
(
false
);
// Create a server socket channel.
InetSocketAddress
isa
=
new
InetSocketAddress
(
InetAddress
.
getLocalHost
(),
serverPort
);
ServerSocketChannel
ssc
=
ServerSocketChannel
.
open
();
ssc
.
socket
().
bind
(
isa
);
serverPort
=
ssc
.
socket
().
getLocalPort
();
// Signal Client, we're ready for his connect.
serverReady
=
true
;
// Accept a socket channel.
SocketChannel
sc
=
ssc
.
accept
();
// Complete connection.
while
(!
sc
.
finishConnect
())
{
Thread
.
sleep
(
50
);
// waiting for the connection completed.
}
ByteBuffer
buffer
=
ByteBuffer
.
allocate
(
0xFF
);
int
position
=
0
;
SSLCapabilities
capabilities
=
null
;
// Read the header of TLS record
buffer
.
limit
(
SSLExplorer
.
RECORD_HEADER_SIZE
);
while
(
position
<
SSLExplorer
.
RECORD_HEADER_SIZE
)
{
int
n
=
sc
.
read
(
buffer
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
buffer
.
flip
();
int
recordLength
=
SSLExplorer
.
getRequiredSize
(
buffer
);
if
(
buffer
.
capacity
()
<
recordLength
)
{
ByteBuffer
oldBuffer
=
buffer
;
buffer
=
ByteBuffer
.
allocate
(
recordLength
);
buffer
.
put
(
oldBuffer
);
}
buffer
.
position
(
SSLExplorer
.
RECORD_HEADER_SIZE
);
buffer
.
limit
(
buffer
.
capacity
());
while
(
position
<
recordLength
)
{
int
n
=
sc
.
read
(
buffer
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
buffer
.
flip
();
capabilities
=
SSLExplorer
.
explore
(
buffer
);
if
(
capabilities
!=
null
)
{
System
.
out
.
println
(
"Record version: "
+
capabilities
.
getRecordVersion
());
System
.
out
.
println
(
"Hello version: "
+
capabilities
.
getHelloVersion
());
}
// enable server name indication checking
SNIMatcher
matcher
=
SNIHostName
.
createSNIMatcher
(
serverAcceptableHostname
);
Collection
<
SNIMatcher
>
matchers
=
new
ArrayList
<>(
1
);
matchers
.
add
(
matcher
);
SSLParameters
params
=
ssle
.
getSSLParameters
();
params
.
setSNIMatchers
(
matchers
);
ssle
.
setSSLParameters
(
params
);
try
{
// handshaking
handshaking
(
ssle
,
sc
,
buffer
);
// receive application data
receive
(
ssle
,
sc
);
// send out application data
deliver
(
ssle
,
sc
);
// check server name indication
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
ssle
.
getSession
();
checkCapabilities
(
capabilities
,
session
);
throw
new
Exception
(
"Mismatched server name indication was accepted"
);
}
catch
(
SSLHandshakeException
sslhe
)
{
// the expected unrecognized server name indication exception
}
catch
(
IOException
ioe
)
{
// the peer may have closed the socket because of the unmatched
// server name indication.
}
finally
{
// close the socket channel.
sc
.
close
();
ssc
.
close
();
}
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
// create SSLEngine.
SSLEngine
ssle
=
createSSLEngine
(
true
);
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
// Create a non-blocking socket channel.
SocketChannel
sc
=
SocketChannel
.
open
();
sc
.
configureBlocking
(
false
);
InetSocketAddress
isa
=
new
InetSocketAddress
(
InetAddress
.
getLocalHost
(),
serverPort
);
sc
.
connect
(
isa
);
// Complete connection.
while
(!
sc
.
finishConnect
()
)
{
Thread
.
sleep
(
50
);
// waiting for the connection completed.
}
SNIHostName
serverName
=
new
SNIHostName
(
clientRequestedHostname
);
List
<
SNIServerName
>
serverNames
=
new
ArrayList
<>(
1
);
serverNames
.
add
(
serverName
);
SSLParameters
params
=
ssle
.
getSSLParameters
();
params
.
setServerNames
(
serverNames
);
ssle
.
setSSLParameters
(
params
);
try
{
// handshaking
handshaking
(
ssle
,
sc
,
null
);
// send out application data
deliver
(
ssle
,
sc
);
// receive application data
receive
(
ssle
,
sc
);
// check server name indication
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
ssle
.
getSession
();
checkSNIInSession
(
session
);
throw
new
Exception
(
"Mismatched server name indication was accepted"
);
}
catch
(
SSLHandshakeException
sslhe
)
{
// the expected unrecognized server name indication exception
}
catch
(
IOException
ioe
)
{
// the peer may have closed the socket because of the unmatched
// server name indication.
}
finally
{
// close the socket channel.
sc
.
close
();
}
}
void
checkCapabilities
(
SSLCapabilities
capabilities
,
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(!
sessionSNI
.
equals
(
capabilities
.
getServerNames
()))
{
for
(
SNIServerName
sni
:
sessionSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
List
<
SNIServerName
>
capaSNI
=
capabilities
.
getServerNames
();
for
(
SNIServerName
sni
:
capaSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
throw
new
Exception
(
"server name indication does not match capabilities"
);
}
checkSNIInSession
(
session
);
}
void
checkSNIInSession
(
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(
sessionSNI
.
isEmpty
())
{
throw
new
Exception
(
"unexpected empty request server name indication"
);
}
if
(
sessionSNI
.
size
()
!=
1
)
{
throw
new
Exception
(
"unexpected request server name indication"
);
}
SNIServerName
serverName
=
sessionSNI
.
get
(
0
);
if
(!(
serverName
instanceof
SNIHostName
))
{
throw
new
Exception
(
"unexpected instance of request server name indication"
);
}
String
hostname
=
((
SNIHostName
)
serverName
).
getAsciiName
();
if
(!
clientRequestedHostname
.
equalsIgnoreCase
(
hostname
))
{
throw
new
Exception
(
"unexpected request server name indication value"
);
}
}
private
static
String
clientRequestedHostname
;
private
static
String
serverAcceptableHostname
;
private
static
void
parseArguments
(
String
[]
args
)
{
clientRequestedHostname
=
args
[
0
];
serverAcceptableHostname
=
args
[
1
];
}
/*
* =============================================================
* The remainder is just support stuff
*/
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
// use any free port by default
volatile
int
serverPort
=
0
;
public
static
void
main
(
String
args
[])
throws
Exception
{
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Get the customized arguments.
*/
parseArguments
(
args
);
new
SSLEngineExplorerUnmatchedSNI
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLEngineExplorerUnmatchedSNI
()
throws
Exception
{
super
(
"../../../../etc"
);
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
*
* If the main thread excepted, that propagates back
* immediately. If the other thread threw an exception, we
* should report back.
*/
if
(
serverException
!=
null
)
{
System
.
out
.
print
(
"Server Exception:"
);
throw
serverException
;
}
if
(
clientException
!=
null
)
{
System
.
out
.
print
(
"Client Exception:"
);
throw
clientException
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
System
.
err
.
println
(
e
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
doServerSide
();
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
doClientSide
();
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @library ../NewAPIs/SSLEngine ../../../../templates
* @build SSLEngineService SSLCapabilities SSLExplorer
* @run main/othervm SSLEngineExplorerWithCli
*/
import
javax.net.ssl.*
;
import
java.nio.*
;
import
java.net.*
;
import
java.util.*
;
import
java.nio.channels.*
;
public
class
SSLEngineExplorerWithCli
extends
SSLEngineService
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
true
;
// Is the server ready to serve?
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
// create SSLEngine.
SSLEngine
ssle
=
createSSLEngine
(
false
);
// Create a server socket channel.
InetSocketAddress
isa
=
new
InetSocketAddress
(
InetAddress
.
getLocalHost
(),
serverPort
);
ServerSocketChannel
ssc
=
ServerSocketChannel
.
open
();
ssc
.
socket
().
bind
(
isa
);
serverPort
=
ssc
.
socket
().
getLocalPort
();
// Signal Client, we're ready for his connect.
serverReady
=
true
;
// Accept a socket channel.
SocketChannel
sc
=
ssc
.
accept
();
// Complete connection.
while
(!
sc
.
finishConnect
())
{
Thread
.
sleep
(
50
);
// waiting for the connection completed.
}
ByteBuffer
buffer
=
ByteBuffer
.
allocate
(
0xFF
);
int
position
=
0
;
SSLCapabilities
capabilities
=
null
;
// Read the header of TLS record
buffer
.
limit
(
SSLExplorer
.
RECORD_HEADER_SIZE
);
while
(
position
<
SSLExplorer
.
RECORD_HEADER_SIZE
)
{
int
n
=
sc
.
read
(
buffer
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
buffer
.
flip
();
int
recordLength
=
SSLExplorer
.
getRequiredSize
(
buffer
);
if
(
buffer
.
capacity
()
<
recordLength
)
{
ByteBuffer
oldBuffer
=
buffer
;
buffer
=
ByteBuffer
.
allocate
(
recordLength
);
buffer
.
put
(
oldBuffer
);
}
buffer
.
position
(
SSLExplorer
.
RECORD_HEADER_SIZE
);
buffer
.
limit
(
buffer
.
capacity
());
while
(
position
<
recordLength
)
{
int
n
=
sc
.
read
(
buffer
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
buffer
.
flip
();
capabilities
=
SSLExplorer
.
explore
(
buffer
);
if
(
capabilities
!=
null
)
{
System
.
out
.
println
(
"Record version: "
+
capabilities
.
getRecordVersion
());
System
.
out
.
println
(
"Hello version: "
+
capabilities
.
getHelloVersion
());
}
// handshaking
handshaking
(
ssle
,
sc
,
buffer
);
// receive application data
receive
(
ssle
,
sc
);
// send out application data
deliver
(
ssle
,
sc
);
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
ssle
.
getSession
();
checkCapabilities
(
capabilities
,
session
);
// close the socket channel.
sc
.
close
();
ssc
.
close
();
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
// create SSLEngine.
SSLEngine
ssle
=
createSSLEngine
(
true
);
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
// Create a non-blocking socket channel.
SocketChannel
sc
=
SocketChannel
.
open
();
sc
.
configureBlocking
(
false
);
InetSocketAddress
isa
=
new
InetSocketAddress
(
InetAddress
.
getLocalHost
(),
serverPort
);
sc
.
connect
(
isa
);
// Complete connection.
while
(!
sc
.
finishConnect
()
)
{
Thread
.
sleep
(
50
);
// waiting for the connection completed.
}
SNIHostName
serverName
=
new
SNIHostName
(
clientRequestedHostname
);
List
<
SNIServerName
>
serverNames
=
new
ArrayList
<>(
1
);
serverNames
.
add
(
serverName
);
SSLParameters
params
=
ssle
.
getSSLParameters
();
params
.
setServerNames
(
serverNames
);
ssle
.
setSSLParameters
(
params
);
// handshaking
handshaking
(
ssle
,
sc
,
null
);
// send out application data
deliver
(
ssle
,
sc
);
// receive application data
receive
(
ssle
,
sc
);
// check server name indication
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
ssle
.
getSession
();
checkSNIInSession
(
session
);
// close the socket channel.
sc
.
close
();
}
private
static
String
clientRequestedHostname
=
"www.example.com"
;
private
static
String
serverAcceptableHostname
=
"www\\.example\\.(com|org)"
;
void
checkCapabilities
(
SSLCapabilities
capabilities
,
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(!
sessionSNI
.
equals
(
capabilities
.
getServerNames
()))
{
for
(
SNIServerName
sni
:
sessionSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
List
<
SNIServerName
>
capaSNI
=
capabilities
.
getServerNames
();
for
(
SNIServerName
sni
:
capaSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
throw
new
Exception
(
"server name indication does not match capabilities"
);
}
checkSNIInSession
(
session
);
}
void
checkSNIInSession
(
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(
sessionSNI
.
isEmpty
())
{
throw
new
Exception
(
"unexpected empty request server name indication"
);
}
if
(
sessionSNI
.
size
()
!=
1
)
{
throw
new
Exception
(
"unexpected request server name indication"
);
}
SNIServerName
serverName
=
sessionSNI
.
get
(
0
);
if
(!(
serverName
instanceof
SNIHostName
))
{
throw
new
Exception
(
"unexpected instance of request server name indication"
);
}
String
hostname
=
((
SNIHostName
)
serverName
).
getAsciiName
();
if
(!
clientRequestedHostname
.
equalsIgnoreCase
(
hostname
))
{
throw
new
Exception
(
"unexpected request server name indication value"
);
}
}
/*
* =============================================================
* The remainder is just support stuff
*/
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
// use any free port by default
volatile
int
serverPort
=
0
;
public
static
void
main
(
String
args
[])
throws
Exception
{
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
new
SSLEngineExplorerWithCli
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLEngineExplorerWithCli
()
throws
Exception
{
super
(
"../../../../etc"
);
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
*
* If the main thread excepted, that propagates back
* immediately. If the other thread threw an exception, we
* should report back.
*/
if
(
serverException
!=
null
)
{
System
.
out
.
print
(
"Server Exception:"
);
throw
serverException
;
}
if
(
clientException
!=
null
)
{
System
.
out
.
print
(
"Client Exception:"
);
throw
clientException
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
System
.
err
.
println
(
e
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
doServerSide
();
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
doClientSide
();
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @library ../NewAPIs/SSLEngine ../../../../templates
* @build SSLEngineService SSLCapabilities SSLExplorer
* @run main/othervm SSLEngineExplorerWithSrv
*/
import
javax.net.ssl.*
;
import
java.nio.*
;
import
java.net.*
;
import
java.util.*
;
import
java.nio.channels.*
;
public
class
SSLEngineExplorerWithSrv
extends
SSLEngineService
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
true
;
// Is the server ready to serve?
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
// create SSLEngine.
SSLEngine
ssle
=
createSSLEngine
(
false
);
// Create a server socket channel.
InetSocketAddress
isa
=
new
InetSocketAddress
(
InetAddress
.
getLocalHost
(),
serverPort
);
ServerSocketChannel
ssc
=
ServerSocketChannel
.
open
();
ssc
.
socket
().
bind
(
isa
);
serverPort
=
ssc
.
socket
().
getLocalPort
();
// Signal Client, we're ready for his connect.
serverReady
=
true
;
// Accept a socket channel.
SocketChannel
sc
=
ssc
.
accept
();
// Complete connection.
while
(!
sc
.
finishConnect
())
{
Thread
.
sleep
(
50
);
// waiting for the connection completed.
}
ByteBuffer
buffer
=
ByteBuffer
.
allocate
(
0xFF
);
int
position
=
0
;
SSLCapabilities
capabilities
=
null
;
// Read the header of TLS record
buffer
.
limit
(
SSLExplorer
.
RECORD_HEADER_SIZE
);
while
(
position
<
SSLExplorer
.
RECORD_HEADER_SIZE
)
{
int
n
=
sc
.
read
(
buffer
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
buffer
.
flip
();
int
recordLength
=
SSLExplorer
.
getRequiredSize
(
buffer
);
if
(
buffer
.
capacity
()
<
recordLength
)
{
ByteBuffer
oldBuffer
=
buffer
;
buffer
=
ByteBuffer
.
allocate
(
recordLength
);
buffer
.
put
(
oldBuffer
);
}
buffer
.
position
(
SSLExplorer
.
RECORD_HEADER_SIZE
);
buffer
.
limit
(
buffer
.
capacity
());
while
(
position
<
recordLength
)
{
int
n
=
sc
.
read
(
buffer
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
buffer
.
flip
();
capabilities
=
SSLExplorer
.
explore
(
buffer
);
if
(
capabilities
!=
null
)
{
System
.
out
.
println
(
"Record version: "
+
capabilities
.
getRecordVersion
());
System
.
out
.
println
(
"Hello version: "
+
capabilities
.
getHelloVersion
());
}
// enable server name indication checking
SNIMatcher
matcher
=
SNIHostName
.
createSNIMatcher
(
serverAcceptableHostname
);
Collection
<
SNIMatcher
>
matchers
=
new
ArrayList
<>(
1
);
matchers
.
add
(
matcher
);
SSLParameters
params
=
ssle
.
getSSLParameters
();
params
.
setSNIMatchers
(
matchers
);
ssle
.
setSSLParameters
(
params
);
// handshaking
handshaking
(
ssle
,
sc
,
buffer
);
// receive application data
receive
(
ssle
,
sc
);
// send out application data
deliver
(
ssle
,
sc
);
// check server name indication
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
ssle
.
getSession
();
checkCapabilities
(
capabilities
,
session
);
// close the socket channel.
sc
.
close
();
ssc
.
close
();
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
// create SSLEngine.
SSLEngine
ssle
=
createSSLEngine
(
true
);
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
// Create a non-blocking socket channel.
SocketChannel
sc
=
SocketChannel
.
open
();
sc
.
configureBlocking
(
false
);
InetSocketAddress
isa
=
new
InetSocketAddress
(
InetAddress
.
getLocalHost
(),
serverPort
);
sc
.
connect
(
isa
);
// Complete connection.
while
(!
sc
.
finishConnect
()
)
{
Thread
.
sleep
(
50
);
// waiting for the connection completed.
}
// handshaking
handshaking
(
ssle
,
sc
,
null
);
// send out application data
deliver
(
ssle
,
sc
);
// receive application data
receive
(
ssle
,
sc
);
// check server name indication
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
ssle
.
getSession
();
checkSNIInSession
(
session
);
// close the socket channel.
sc
.
close
();
}
private
static
String
clientRequestedHostname
=
"www.example.com"
;
private
static
String
serverAcceptableHostname
=
"www\\.example\\.(com|org)"
;
void
checkCapabilities
(
SSLCapabilities
capabilities
,
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(!
sessionSNI
.
equals
(
capabilities
.
getServerNames
()))
{
for
(
SNIServerName
sni
:
sessionSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
List
<
SNIServerName
>
capaSNI
=
capabilities
.
getServerNames
();
for
(
SNIServerName
sni
:
capaSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
throw
new
Exception
(
"server name indication does not match capabilities"
);
}
checkSNIInSession
(
session
);
}
void
checkSNIInSession
(
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(!
sessionSNI
.
isEmpty
())
{
throw
new
Exception
(
"should be empty request server name indication"
);
}
}
/*
* =============================================================
* The remainder is just support stuff
*/
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
// use any free port by default
volatile
int
serverPort
=
0
;
public
static
void
main
(
String
args
[])
throws
Exception
{
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
new
SSLEngineExplorerWithSrv
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLEngineExplorerWithSrv
()
throws
Exception
{
super
(
"../../../../etc"
);
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
*
* If the main thread excepted, that propagates back
* immediately. If the other thread threw an exception, we
* should report back.
*/
if
(
serverException
!=
null
)
{
System
.
out
.
print
(
"Server Exception:"
);
throw
serverException
;
}
if
(
clientException
!=
null
)
{
System
.
out
.
print
(
"Client Exception:"
);
throw
clientException
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
System
.
err
.
println
(
e
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
doServerSide
();
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
doClientSide
();
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketConsistentSNI.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/**
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @run main/othervm SSLSocketConsistentSNI
*/
import
java.io.*
;
import
java.nio.*
;
import
java.nio.channels.*
;
import
java.util.*
;
import
java.net.*
;
import
javax.net.ssl.*
;
public
class
SSLSocketConsistentSNI
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
true
;
/*
* Where do we find the keystores?
*/
static
String
pathToStores
=
"../../../../etc"
;
static
String
keyStoreFile
=
"keystore"
;
static
String
trustStoreFile
=
"truststore"
;
static
String
passwd
=
"passphrase"
;
/*
* Is the server ready to serve?
*/
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* If the client or server is doing some kind of object creation
* that the other side depends on, and that thread prematurely
* exits, you may experience a hang. The test harness will
* terminate all hung threads after its timeout has expired,
* currently 3 minutes by default, but you might try to be
* smart about it....
*/
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
SSLServerSocketFactory
sslssf
=
(
SSLServerSocketFactory
)
SSLServerSocketFactory
.
getDefault
();
SSLServerSocket
sslServerSocket
=
(
SSLServerSocket
)
sslssf
.
createServerSocket
(
serverPort
);
SNIMatcher
matcher
=
SNIHostName
.
createSNIMatcher
(
serverAcceptableHostname
);
Collection
<
SNIMatcher
>
matchers
=
new
ArrayList
<>(
1
);
matchers
.
add
(
matcher
);
SSLParameters
params
=
sslServerSocket
.
getSSLParameters
();
params
.
setSNIMatchers
(
matchers
);
sslServerSocket
.
setSSLParameters
(
params
);
serverPort
=
sslServerSocket
.
getLocalPort
();
/*
* Signal Client, we're ready for his connect.
*/
serverReady
=
true
;
SSLSocket
sslSocket
=
(
SSLSocket
)
sslServerSocket
.
accept
();
try
{
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslIS
.
read
();
sslOS
.
write
(
85
);
sslOS
.
flush
();
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
sslSocket
.
getSession
();
checkSNIInSession
(
session
);
}
finally
{
sslSocket
.
close
();
sslServerSocket
.
close
();
}
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
"localhost"
,
serverPort
);
SNIHostName
serverName
=
new
SNIHostName
(
clientRequestedHostname
);
List
<
SNIServerName
>
serverNames
=
new
ArrayList
<>(
1
);
serverNames
.
add
(
serverName
);
SSLParameters
params
=
sslSocket
.
getSSLParameters
();
params
.
setServerNames
(
serverNames
);
sslSocket
.
setSSLParameters
(
params
);
try
{
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslOS
.
write
(
280
);
sslOS
.
flush
();
sslIS
.
read
();
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
sslSocket
.
getSession
();
checkSNIInSession
(
session
);
}
finally
{
sslSocket
.
close
();
}
}
private
static
String
clientRequestedHostname
=
"www.example.com"
;
private
static
String
serverAcceptableHostname
=
"www\\.example\\.com"
;
void
checkSNIInSession
(
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(
sessionSNI
.
isEmpty
())
{
throw
new
Exception
(
"unexpected empty request server name indication"
);
}
if
(
sessionSNI
.
size
()
!=
1
)
{
throw
new
Exception
(
"unexpected request server name indication"
);
}
SNIServerName
serverName
=
sessionSNI
.
get
(
0
);
if
(!(
serverName
instanceof
SNIHostName
))
{
throw
new
Exception
(
"unexpected instance of request server name indication"
);
}
String
hostname
=
((
SNIHostName
)
serverName
).
getAsciiName
();
if
(!
clientRequestedHostname
.
equalsIgnoreCase
(
hostname
))
{
throw
new
Exception
(
"unexpected request server name indication value"
);
}
}
/*
* =============================================================
* The remainder is just support stuff
*/
// use any free port by default
volatile
int
serverPort
=
0
;
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
keyFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
keyStoreFile
;
String
trustFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
trustStoreFile
;
System
.
setProperty
(
"javax.net.ssl.keyStore"
,
keyFilename
);
System
.
setProperty
(
"javax.net.ssl.keyStorePassword"
,
passwd
);
System
.
setProperty
(
"javax.net.ssl.trustStore"
,
trustFilename
);
System
.
setProperty
(
"javax.net.ssl.trustStorePassword"
,
passwd
);
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Start the tests.
*/
new
SSLSocketConsistentSNI
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLSocketConsistentSNI
()
throws
Exception
{
try
{
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
}
catch
(
Exception
e
)
{
// swallow for now. Show later
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception
local
;
Exception
remote
;
String
whichRemote
;
if
(
separateServerThread
)
{
remote
=
serverException
;
local
=
clientException
;
whichRemote
=
"server"
;
}
else
{
remote
=
clientException
;
local
=
serverException
;
whichRemote
=
"client"
;
}
/*
* If both failed, return the curthread's exception, but also
* print the remote side Exception
*/
if
((
local
!=
null
)
&&
(
remote
!=
null
))
{
System
.
out
.
println
(
whichRemote
+
" also threw:"
);
remote
.
printStackTrace
();
System
.
out
.
println
();
throw
local
;
}
if
(
remote
!=
null
)
{
throw
remote
;
}
if
(
local
!=
null
)
{
throw
local
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
serverException
=
e
;
}
finally
{
serverReady
=
true
;
}
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
clientException
=
e
;
}
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorer.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/**
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @library ../../../../templates
* @build SSLCapabilities SSLExplorer
* @run main/othervm SSLSocketExplorer SSLv2Hello,SSLv3
* @run main/othervm SSLSocketExplorer SSLv3
* @run main/othervm SSLSocketExplorer TLSv1
* @run main/othervm SSLSocketExplorer TLSv1.1
* @run main/othervm SSLSocketExplorer TLSv1.2
*/
import
java.io.*
;
import
java.nio.*
;
import
java.nio.channels.*
;
import
java.util.*
;
import
java.net.*
;
import
javax.net.ssl.*
;
public
class
SSLSocketExplorer
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
true
;
/*
* Where do we find the keystores?
*/
static
String
pathToStores
=
"../../../../etc"
;
static
String
keyStoreFile
=
"keystore"
;
static
String
trustStoreFile
=
"truststore"
;
static
String
passwd
=
"passphrase"
;
/*
* Is the server ready to serve?
*/
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* If the client or server is doing some kind of object creation
* that the other side depends on, and that thread prematurely
* exits, you may experience a hang. The test harness will
* terminate all hung threads after its timeout has expired,
* currently 3 minutes by default, but you might try to be
* smart about it....
*/
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
ServerSocket
serverSocket
=
new
ServerSocket
(
serverPort
);
// Signal Client, we're ready for his connect.
serverPort
=
serverSocket
.
getLocalPort
();
serverReady
=
true
;
Socket
socket
=
serverSocket
.
accept
();
InputStream
ins
=
socket
.
getInputStream
();
byte
[]
buffer
=
new
byte
[
0xFF
];
int
position
=
0
;
SSLCapabilities
capabilities
=
null
;
// Read the header of TLS record
while
(
position
<
SSLExplorer
.
RECORD_HEADER_SIZE
)
{
int
count
=
SSLExplorer
.
RECORD_HEADER_SIZE
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
int
recordLength
=
SSLExplorer
.
getRequiredSize
(
buffer
,
0
,
position
);
if
(
buffer
.
length
<
recordLength
)
{
buffer
=
Arrays
.
copyOf
(
buffer
,
recordLength
);
}
while
(
position
<
recordLength
)
{
int
count
=
recordLength
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
capabilities
=
SSLExplorer
.
explore
(
buffer
,
0
,
recordLength
);;
if
(
capabilities
!=
null
)
{
System
.
out
.
println
(
"Record version: "
+
capabilities
.
getRecordVersion
());
System
.
out
.
println
(
"Hello version: "
+
capabilities
.
getHelloVersion
());
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
buffer
,
0
,
position
);
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
socket
,
bais
,
true
);
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslIS
.
read
();
sslOS
.
write
(
85
);
sslOS
.
flush
();
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
sslSocket
.
getSession
();
checkCapabilities
(
capabilities
,
session
);
sslSocket
.
close
();
serverSocket
.
close
();
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
"localhost"
,
serverPort
);
// enable the specified TLS protocol
sslSocket
.
setEnabledProtocols
(
supportedProtocols
);
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslOS
.
write
(
280
);
sslOS
.
flush
();
sslIS
.
read
();
sslSocket
.
close
();
}
void
checkCapabilities
(
SSLCapabilities
capabilities
,
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(!
sessionSNI
.
equals
(
capabilities
.
getServerNames
()))
{
throw
new
Exception
(
"server name indication does not match capabilities"
);
}
}
private
static
String
[]
supportedProtocols
;
// supported protocols
private
static
void
parseArguments
(
String
[]
args
)
{
supportedProtocols
=
args
[
0
].
split
(
","
);
}
/*
* =============================================================
* The remainder is just support stuff
*/
// use any free port by default
volatile
int
serverPort
=
0
;
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
keyFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
keyStoreFile
;
String
trustFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
trustStoreFile
;
System
.
setProperty
(
"javax.net.ssl.keyStore"
,
keyFilename
);
System
.
setProperty
(
"javax.net.ssl.keyStorePassword"
,
passwd
);
System
.
setProperty
(
"javax.net.ssl.trustStore"
,
trustFilename
);
System
.
setProperty
(
"javax.net.ssl.trustStorePassword"
,
passwd
);
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Get the customized arguments.
*/
parseArguments
(
args
);
/*
* Start the tests.
*/
new
SSLSocketExplorer
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLSocketExplorer
()
throws
Exception
{
try
{
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
}
catch
(
Exception
e
)
{
// swallow for now. Show later
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception
local
;
Exception
remote
;
String
whichRemote
;
if
(
separateServerThread
)
{
remote
=
serverException
;
local
=
clientException
;
whichRemote
=
"server"
;
}
else
{
remote
=
clientException
;
local
=
serverException
;
whichRemote
=
"client"
;
}
/*
* If both failed, return the curthread's exception, but also
* print the remote side Exception
*/
if
((
local
!=
null
)
&&
(
remote
!=
null
))
{
System
.
out
.
println
(
whichRemote
+
" also threw:"
);
remote
.
printStackTrace
();
System
.
out
.
println
();
throw
local
;
}
if
(
remote
!=
null
)
{
throw
remote
;
}
if
(
local
!=
null
)
{
throw
local
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
serverException
=
e
;
}
finally
{
serverReady
=
true
;
}
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
clientException
=
e
;
}
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/**
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @library ../../../../templates
* @build SSLCapabilities SSLExplorer
* @run main/othervm SSLSocketExplorerFailure SSLv2Hello,SSLv3
* @run main/othervm SSLSocketExplorerFailure SSLv3
* @run main/othervm SSLSocketExplorerFailure TLSv1
* @run main/othervm SSLSocketExplorerFailure TLSv1.1
* @run main/othervm SSLSocketExplorerFailure TLSv1.2
*/
import
java.io.*
;
import
java.nio.*
;
import
java.nio.channels.*
;
import
java.util.*
;
import
java.net.*
;
import
javax.net.ssl.*
;
public
class
SSLSocketExplorerFailure
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
true
;
/*
* Where do we find the keystores?
*/
static
String
pathToStores
=
"../../../../etc"
;
static
String
keyStoreFile
=
"keystore"
;
static
String
trustStoreFile
=
"truststore"
;
static
String
passwd
=
"passphrase"
;
/*
* Is the server ready to serve?
*/
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* If the client or server is doing some kind of object creation
* that the other side depends on, and that thread prematurely
* exits, you may experience a hang. The test harness will
* terminate all hung threads after its timeout has expired,
* currently 3 minutes by default, but you might try to be
* smart about it....
*/
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
ServerSocket
serverSocket
=
new
ServerSocket
(
serverPort
);
// Signal Client, we're ready for his connect.
serverPort
=
serverSocket
.
getLocalPort
();
serverReady
=
true
;
Socket
socket
=
serverSocket
.
accept
();
InputStream
ins
=
socket
.
getInputStream
();
byte
[]
buffer
=
new
byte
[
0xFF
];
int
position
=
0
;
SSLCapabilities
capabilities
=
null
;
boolean
failed
=
false
;
try
{
// Read the header of TLS record
while
(
position
<
SSLExplorer
.
RECORD_HEADER_SIZE
)
{
int
count
=
SSLExplorer
.
RECORD_HEADER_SIZE
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
int
recordLength
=
SSLExplorer
.
getRequiredSize
(
buffer
,
0
,
position
);
if
(
buffer
.
length
<
recordLength
)
{
buffer
=
Arrays
.
copyOf
(
buffer
,
recordLength
);
}
while
(
position
<
recordLength
)
{
int
count
=
recordLength
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
capabilities
=
SSLExplorer
.
explore
(
buffer
,
0
,
recordLength
);;
if
(
capabilities
!=
null
)
{
System
.
out
.
println
(
"Record version: "
+
capabilities
.
getRecordVersion
());
System
.
out
.
println
(
"Hello version: "
+
capabilities
.
getHelloVersion
());
}
// want an I/O exception
throw
new
IOException
(
"We just want a I/O exception"
);
}
catch
(
Exception
e
)
{
failed
=
true
;
}
// off course, the above explore failed. Faile to failure handler
SSLContext
context
=
SSLContext
.
getInstance
(
"TLS"
);
context
.
init
(
null
,
null
,
null
);
SSLSocketFactory
sslsf
=
context
.
getSocketFactory
();
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
buffer
,
0
,
position
);
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
socket
,
bais
,
true
);
try
{
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslIS
.
read
();
if
(!
failed
)
{
sslOS
.
write
(
85
);
sslOS
.
flush
();
}
else
{
sslSocket
.
close
();
}
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
"server exception "
+
e
);
}
finally
{
sslSocket
.
close
();
serverSocket
.
close
();
}
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
"localhost"
,
serverPort
);
// enable the specified TLS protocol
sslSocket
.
setEnabledProtocols
(
supportedProtocols
);
try
{
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslOS
.
write
(
280
);
sslOS
.
flush
();
sslIS
.
read
();
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
"client exception "
+
e
);
}
finally
{
sslSocket
.
close
();
}
}
private
static
String
[]
supportedProtocols
;
// supported protocols
private
static
void
parseArguments
(
String
[]
args
)
{
supportedProtocols
=
args
[
0
].
split
(
","
);
}
/*
* =============================================================
* The remainder is just support stuff
*/
// use any free port by default
volatile
int
serverPort
=
0
;
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
keyFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
keyStoreFile
;
String
trustFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
trustStoreFile
;
System
.
setProperty
(
"javax.net.ssl.keyStore"
,
keyFilename
);
System
.
setProperty
(
"javax.net.ssl.keyStorePassword"
,
passwd
);
System
.
setProperty
(
"javax.net.ssl.trustStore"
,
trustFilename
);
System
.
setProperty
(
"javax.net.ssl.trustStorePassword"
,
passwd
);
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Get the customized arguments.
*/
parseArguments
(
args
);
/*
* Start the tests.
*/
new
SSLSocketExplorerFailure
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLSocketExplorerFailure
()
throws
Exception
{
try
{
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
}
catch
(
Exception
e
)
{
// swallow for now. Show later
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception
local
;
Exception
remote
;
String
whichRemote
;
if
(
separateServerThread
)
{
remote
=
serverException
;
local
=
clientException
;
whichRemote
=
"server"
;
}
else
{
remote
=
clientException
;
local
=
serverException
;
whichRemote
=
"client"
;
}
/*
* If both failed, return the curthread's exception, but also
* print the remote side Exception
*/
if
((
local
!=
null
)
&&
(
remote
!=
null
))
{
System
.
out
.
println
(
whichRemote
+
" also threw:"
);
remote
.
printStackTrace
();
System
.
out
.
println
();
throw
local
;
}
if
(
remote
!=
null
)
{
throw
remote
;
}
if
(
local
!=
null
)
{
throw
local
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
serverException
=
e
;
}
finally
{
serverReady
=
true
;
}
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
clientException
=
e
;
}
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/**
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @library ../../../../templates
* @build SSLCapabilities SSLExplorer
* @run main/othervm SSLSocketExplorerMatchedSNI www.example.com
* www\.example\.com
* @run main/othervm SSLSocketExplorerMatchedSNI www.example.com
* www\.example\.(com|org)
* @run main/othervm SSLSocketExplorerMatchedSNI example.com
* (.*\.)*example\.(com|org)
* @run main/othervm SSLSocketExplorerMatchedSNI www.example.com
* (.*\.)*example\.(com|org)
* @run main/othervm SSLSocketExplorerMatchedSNI www.us.example.com
* (.*\.)*example\.(com|org)
*/
import
java.io.*
;
import
java.nio.*
;
import
java.nio.channels.*
;
import
java.util.*
;
import
java.net.*
;
import
javax.net.ssl.*
;
public
class
SSLSocketExplorerMatchedSNI
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
false
;
/*
* Where do we find the keystores?
*/
static
String
pathToStores
=
"../../../../etc"
;
static
String
keyStoreFile
=
"keystore"
;
static
String
trustStoreFile
=
"truststore"
;
static
String
passwd
=
"passphrase"
;
/*
* Is the server ready to serve?
*/
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* If the client or server is doing some kind of object creation
* that the other side depends on, and that thread prematurely
* exits, you may experience a hang. The test harness will
* terminate all hung threads after its timeout has expired,
* currently 3 minutes by default, but you might try to be
* smart about it....
*/
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
ServerSocket
serverSocket
=
new
ServerSocket
(
serverPort
);
// Signal Client, we're ready for his connect.
serverPort
=
serverSocket
.
getLocalPort
();
serverReady
=
true
;
Socket
socket
=
serverSocket
.
accept
();
InputStream
ins
=
socket
.
getInputStream
();
byte
[]
buffer
=
new
byte
[
0xFF
];
int
position
=
0
;
SSLCapabilities
capabilities
=
null
;
// Read the header of TLS record
while
(
position
<
SSLExplorer
.
RECORD_HEADER_SIZE
)
{
int
count
=
SSLExplorer
.
RECORD_HEADER_SIZE
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
int
recordLength
=
SSLExplorer
.
getRequiredSize
(
buffer
,
0
,
position
);
if
(
buffer
.
length
<
recordLength
)
{
buffer
=
Arrays
.
copyOf
(
buffer
,
recordLength
);
}
while
(
position
<
recordLength
)
{
int
count
=
recordLength
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
capabilities
=
SSLExplorer
.
explore
(
buffer
,
0
,
recordLength
);;
if
(
capabilities
!=
null
)
{
System
.
out
.
println
(
"Record version: "
+
capabilities
.
getRecordVersion
());
System
.
out
.
println
(
"Hello version: "
+
capabilities
.
getHelloVersion
());
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
buffer
,
0
,
position
);
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
socket
,
bais
,
true
);
SNIMatcher
matcher
=
SNIHostName
.
createSNIMatcher
(
serverAcceptableHostname
);
Collection
<
SNIMatcher
>
matchers
=
new
ArrayList
<>(
1
);
matchers
.
add
(
matcher
);
SSLParameters
params
=
sslSocket
.
getSSLParameters
();
params
.
setSNIMatchers
(
matchers
);
sslSocket
.
setSSLParameters
(
params
);
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslIS
.
read
();
sslOS
.
write
(
85
);
sslOS
.
flush
();
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
sslSocket
.
getSession
();
checkCapabilities
(
capabilities
,
session
);
sslSocket
.
close
();
serverSocket
.
close
();
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
"localhost"
,
serverPort
);
SNIHostName
serverName
=
new
SNIHostName
(
clientRequestedHostname
);
List
<
SNIServerName
>
serverNames
=
new
ArrayList
<>(
1
);
serverNames
.
add
(
serverName
);
SSLParameters
params
=
sslSocket
.
getSSLParameters
();
params
.
setServerNames
(
serverNames
);
sslSocket
.
setSSLParameters
(
params
);
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslOS
.
write
(
280
);
sslOS
.
flush
();
sslIS
.
read
();
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
sslSocket
.
getSession
();
checkSNIInSession
(
session
);
sslSocket
.
close
();
}
void
checkCapabilities
(
SSLCapabilities
capabilities
,
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(!
sessionSNI
.
equals
(
capabilities
.
getServerNames
()))
{
for
(
SNIServerName
sni
:
sessionSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
List
<
SNIServerName
>
capaSNI
=
capabilities
.
getServerNames
();
for
(
SNIServerName
sni
:
capaSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
throw
new
Exception
(
"server name indication does not match capabilities"
);
}
checkSNIInSession
(
session
);
}
void
checkSNIInSession
(
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(
sessionSNI
.
isEmpty
())
{
throw
new
Exception
(
"unexpected empty request server name indication"
);
}
if
(
sessionSNI
.
size
()
!=
1
)
{
throw
new
Exception
(
"unexpected request server name indication"
);
}
SNIServerName
serverName
=
sessionSNI
.
get
(
0
);
if
(!(
serverName
instanceof
SNIHostName
))
{
throw
new
Exception
(
"unexpected instance of request server name indication"
);
}
String
hostname
=
((
SNIHostName
)
serverName
).
getAsciiName
();
if
(!
clientRequestedHostname
.
equalsIgnoreCase
(
hostname
))
{
throw
new
Exception
(
"unexpected request server name indication value"
);
}
}
private
static
String
clientRequestedHostname
;
private
static
String
serverAcceptableHostname
;
private
static
void
parseArguments
(
String
[]
args
)
{
clientRequestedHostname
=
args
[
0
];
serverAcceptableHostname
=
args
[
1
];
}
/*
* =============================================================
* The remainder is just support stuff
*/
// use any free port by default
volatile
int
serverPort
=
0
;
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
keyFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
keyStoreFile
;
String
trustFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
trustStoreFile
;
System
.
setProperty
(
"javax.net.ssl.keyStore"
,
keyFilename
);
System
.
setProperty
(
"javax.net.ssl.keyStorePassword"
,
passwd
);
System
.
setProperty
(
"javax.net.ssl.trustStore"
,
trustFilename
);
System
.
setProperty
(
"javax.net.ssl.trustStorePassword"
,
passwd
);
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Get the customized arguments.
*/
parseArguments
(
args
);
/*
* Start the tests.
*/
new
SSLSocketExplorerMatchedSNI
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLSocketExplorerMatchedSNI
()
throws
Exception
{
try
{
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
}
catch
(
Exception
e
)
{
// swallow for now. Show later
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception
local
;
Exception
remote
;
String
whichRemote
;
if
(
separateServerThread
)
{
remote
=
serverException
;
local
=
clientException
;
whichRemote
=
"server"
;
}
else
{
remote
=
clientException
;
local
=
serverException
;
whichRemote
=
"client"
;
}
/*
* If both failed, return the curthread's exception, but also
* print the remote side Exception
*/
if
((
local
!=
null
)
&&
(
remote
!=
null
))
{
System
.
out
.
println
(
whichRemote
+
" also threw:"
);
remote
.
printStackTrace
();
System
.
out
.
println
();
throw
local
;
}
if
(
remote
!=
null
)
{
throw
remote
;
}
if
(
local
!=
null
)
{
throw
local
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
serverException
=
e
;
}
finally
{
serverReady
=
true
;
}
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
clientException
=
e
;
}
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/**
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @library ../../../../templates
* @build SSLCapabilities SSLExplorer
* @run main/othervm SSLSocketExplorerUnmatchedSNI www.example.com
* www\.example\.org
*/
import
java.io.*
;
import
java.nio.*
;
import
java.nio.channels.*
;
import
java.util.*
;
import
java.net.*
;
import
javax.net.ssl.*
;
public
class
SSLSocketExplorerUnmatchedSNI
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
false
;
/*
* Where do we find the keystores?
*/
static
String
pathToStores
=
"../../../../etc"
;
static
String
keyStoreFile
=
"keystore"
;
static
String
trustStoreFile
=
"truststore"
;
static
String
passwd
=
"passphrase"
;
/*
* Is the server ready to serve?
*/
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* If the client or server is doing some kind of object creation
* that the other side depends on, and that thread prematurely
* exits, you may experience a hang. The test harness will
* terminate all hung threads after its timeout has expired,
* currently 3 minutes by default, but you might try to be
* smart about it....
*/
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
ServerSocket
serverSocket
=
new
ServerSocket
(
serverPort
);
// Signal Client, we're ready for his connect.
serverPort
=
serverSocket
.
getLocalPort
();
serverReady
=
true
;
Socket
socket
=
serverSocket
.
accept
();
InputStream
ins
=
socket
.
getInputStream
();
byte
[]
buffer
=
new
byte
[
0xFF
];
int
position
=
0
;
SSLCapabilities
capabilities
=
null
;
// Read the header of TLS record
while
(
position
<
SSLExplorer
.
RECORD_HEADER_SIZE
)
{
int
count
=
SSLExplorer
.
RECORD_HEADER_SIZE
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
int
recordLength
=
SSLExplorer
.
getRequiredSize
(
buffer
,
0
,
position
);
if
(
buffer
.
length
<
recordLength
)
{
buffer
=
Arrays
.
copyOf
(
buffer
,
recordLength
);
}
while
(
position
<
recordLength
)
{
int
count
=
recordLength
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
capabilities
=
SSLExplorer
.
explore
(
buffer
,
0
,
recordLength
);;
if
(
capabilities
!=
null
)
{
System
.
out
.
println
(
"Record version: "
+
capabilities
.
getRecordVersion
());
System
.
out
.
println
(
"Hello version: "
+
capabilities
.
getHelloVersion
());
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
buffer
,
0
,
position
);
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
socket
,
bais
,
true
);
SNIMatcher
matcher
=
SNIHostName
.
createSNIMatcher
(
serverAcceptableHostname
);
Collection
<
SNIMatcher
>
matchers
=
new
ArrayList
<>(
1
);
matchers
.
add
(
matcher
);
SSLParameters
params
=
sslSocket
.
getSSLParameters
();
params
.
setSNIMatchers
(
matchers
);
sslSocket
.
setSSLParameters
(
params
);
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
try
{
sslIS
.
read
();
sslOS
.
write
(
85
);
sslOS
.
flush
();
throw
new
Exception
(
"Mismatched server name indication was accepted"
);
}
catch
(
SSLHandshakeException
sslhe
)
{
// the expected unrecognized server name indication exception
}
catch
(
IOException
ioe
)
{
// the peer may have closed the socket because of the unmatched
// server name indication.
}
finally
{
sslSocket
.
close
();
serverSocket
.
close
();
}
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
"localhost"
,
serverPort
);
SNIHostName
serverName
=
new
SNIHostName
(
clientRequestedHostname
);
List
<
SNIServerName
>
serverNames
=
new
ArrayList
<>(
1
);
serverNames
.
add
(
serverName
);
SSLParameters
params
=
sslSocket
.
getSSLParameters
();
params
.
setServerNames
(
serverNames
);
sslSocket
.
setSSLParameters
(
params
);
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
try
{
sslOS
.
write
(
280
);
sslOS
.
flush
();
sslIS
.
read
();
throw
new
Exception
(
"Mismatched server name indication was accepted"
);
}
catch
(
SSLHandshakeException
sslhe
)
{
// the expected unrecognized server name indication exception
}
catch
(
IOException
ioe
)
{
// the peer may have closed the socket because of the unmatched
// server name indication.
}
finally
{
sslSocket
.
close
();
}
}
private
static
String
clientRequestedHostname
;
private
static
String
serverAcceptableHostname
;
private
static
void
parseArguments
(
String
[]
args
)
{
clientRequestedHostname
=
args
[
0
];
serverAcceptableHostname
=
args
[
1
];
}
/*
* =============================================================
* The remainder is just support stuff
*/
// use any free port by default
volatile
int
serverPort
=
0
;
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
keyFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
keyStoreFile
;
String
trustFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
trustStoreFile
;
System
.
setProperty
(
"javax.net.ssl.keyStore"
,
keyFilename
);
System
.
setProperty
(
"javax.net.ssl.keyStorePassword"
,
passwd
);
System
.
setProperty
(
"javax.net.ssl.trustStore"
,
trustFilename
);
System
.
setProperty
(
"javax.net.ssl.trustStorePassword"
,
passwd
);
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Get the customized arguments.
*/
parseArguments
(
args
);
/*
* Start the tests.
*/
new
SSLSocketExplorerUnmatchedSNI
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLSocketExplorerUnmatchedSNI
()
throws
Exception
{
try
{
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
}
catch
(
Exception
e
)
{
// swallow for now. Show later
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception
local
;
Exception
remote
;
String
whichRemote
;
if
(
separateServerThread
)
{
remote
=
serverException
;
local
=
clientException
;
whichRemote
=
"server"
;
}
else
{
remote
=
clientException
;
local
=
serverException
;
whichRemote
=
"client"
;
}
/*
* If both failed, return the curthread's exception, but also
* print the remote side Exception
*/
if
((
local
!=
null
)
&&
(
remote
!=
null
))
{
System
.
out
.
println
(
whichRemote
+
" also threw:"
);
remote
.
printStackTrace
();
System
.
out
.
println
();
throw
local
;
}
if
(
remote
!=
null
)
{
throw
remote
;
}
if
(
local
!=
null
)
{
throw
local
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
serverException
=
e
;
}
finally
{
serverReady
=
true
;
}
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
clientException
=
e
;
}
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/**
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @library ../../../../templates
* @build SSLCapabilities SSLExplorer
* @run main/othervm SSLSocketExplorerWithCliSNI
*/
import
java.io.*
;
import
java.nio.*
;
import
java.nio.channels.*
;
import
java.util.*
;
import
java.net.*
;
import
javax.net.ssl.*
;
public
class
SSLSocketExplorerWithCliSNI
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
true
;
/*
* Where do we find the keystores?
*/
static
String
pathToStores
=
"../../../../etc"
;
static
String
keyStoreFile
=
"keystore"
;
static
String
trustStoreFile
=
"truststore"
;
static
String
passwd
=
"passphrase"
;
/*
* Is the server ready to serve?
*/
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* If the client or server is doing some kind of object creation
* that the other side depends on, and that thread prematurely
* exits, you may experience a hang. The test harness will
* terminate all hung threads after its timeout has expired,
* currently 3 minutes by default, but you might try to be
* smart about it....
*/
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
ServerSocket
serverSocket
=
new
ServerSocket
(
serverPort
);
// Signal Client, we're ready for his connect.
serverPort
=
serverSocket
.
getLocalPort
();
serverReady
=
true
;
Socket
socket
=
serverSocket
.
accept
();
InputStream
ins
=
socket
.
getInputStream
();
byte
[]
buffer
=
new
byte
[
0xFF
];
int
position
=
0
;
SSLCapabilities
capabilities
=
null
;
// Read the header of TLS record
while
(
position
<
SSLExplorer
.
RECORD_HEADER_SIZE
)
{
int
count
=
SSLExplorer
.
RECORD_HEADER_SIZE
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
int
recordLength
=
SSLExplorer
.
getRequiredSize
(
buffer
,
0
,
position
);
if
(
buffer
.
length
<
recordLength
)
{
buffer
=
Arrays
.
copyOf
(
buffer
,
recordLength
);
}
while
(
position
<
recordLength
)
{
int
count
=
recordLength
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
capabilities
=
SSLExplorer
.
explore
(
buffer
,
0
,
recordLength
);;
if
(
capabilities
!=
null
)
{
System
.
out
.
println
(
"Record version: "
+
capabilities
.
getRecordVersion
());
System
.
out
.
println
(
"Hello version: "
+
capabilities
.
getHelloVersion
());
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
buffer
,
0
,
position
);
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
socket
,
bais
,
true
);
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslIS
.
read
();
sslOS
.
write
(
85
);
sslOS
.
flush
();
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
sslSocket
.
getSession
();
checkCapabilities
(
capabilities
,
session
);
sslSocket
.
close
();
serverSocket
.
close
();
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
"localhost"
,
serverPort
);
SNIHostName
serverName
=
new
SNIHostName
(
clientRequestedHostname
);
List
<
SNIServerName
>
serverNames
=
new
ArrayList
<>(
1
);
serverNames
.
add
(
serverName
);
SSLParameters
params
=
sslSocket
.
getSSLParameters
();
params
.
setServerNames
(
serverNames
);
sslSocket
.
setSSLParameters
(
params
);
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslOS
.
write
(
280
);
sslOS
.
flush
();
sslIS
.
read
();
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
sslSocket
.
getSession
();
checkSNIInSession
(
session
);
sslSocket
.
close
();
}
private
static
String
clientRequestedHostname
=
"www.example.com"
;
private
static
String
serverAcceptableHostname
=
"www\\.example\\.(com|org)"
;
void
checkCapabilities
(
SSLCapabilities
capabilities
,
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(!
sessionSNI
.
equals
(
capabilities
.
getServerNames
()))
{
for
(
SNIServerName
sni
:
sessionSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
List
<
SNIServerName
>
capaSNI
=
capabilities
.
getServerNames
();
for
(
SNIServerName
sni
:
capaSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
throw
new
Exception
(
"server name indication does not match capabilities"
);
}
checkSNIInSession
(
session
);
}
void
checkSNIInSession
(
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(
sessionSNI
.
isEmpty
())
{
throw
new
Exception
(
"unexpected empty request server name indication"
);
}
if
(
sessionSNI
.
size
()
!=
1
)
{
throw
new
Exception
(
"unexpected request server name indication"
);
}
SNIServerName
serverName
=
sessionSNI
.
get
(
0
);
if
(!(
serverName
instanceof
SNIHostName
))
{
throw
new
Exception
(
"unexpected instance of request server name indication"
);
}
String
hostname
=
((
SNIHostName
)
serverName
).
getAsciiName
();
if
(!
clientRequestedHostname
.
equalsIgnoreCase
(
hostname
))
{
throw
new
Exception
(
"unexpected request server name indication value"
);
}
}
/*
* =============================================================
* The remainder is just support stuff
*/
// use any free port by default
volatile
int
serverPort
=
0
;
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
keyFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
keyStoreFile
;
String
trustFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
trustStoreFile
;
System
.
setProperty
(
"javax.net.ssl.keyStore"
,
keyFilename
);
System
.
setProperty
(
"javax.net.ssl.keyStorePassword"
,
passwd
);
System
.
setProperty
(
"javax.net.ssl.trustStore"
,
trustFilename
);
System
.
setProperty
(
"javax.net.ssl.trustStorePassword"
,
passwd
);
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Start the tests.
*/
new
SSLSocketExplorerWithCliSNI
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLSocketExplorerWithCliSNI
()
throws
Exception
{
try
{
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
}
catch
(
Exception
e
)
{
// swallow for now. Show later
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception
local
;
Exception
remote
;
String
whichRemote
;
if
(
separateServerThread
)
{
remote
=
serverException
;
local
=
clientException
;
whichRemote
=
"server"
;
}
else
{
remote
=
clientException
;
local
=
serverException
;
whichRemote
=
"client"
;
}
/*
* If both failed, return the curthread's exception, but also
* print the remote side Exception
*/
if
((
local
!=
null
)
&&
(
remote
!=
null
))
{
System
.
out
.
println
(
whichRemote
+
" also threw:"
);
remote
.
printStackTrace
();
System
.
out
.
println
();
throw
local
;
}
if
(
remote
!=
null
)
{
throw
remote
;
}
if
(
local
!=
null
)
{
throw
local
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
serverException
=
e
;
}
finally
{
serverReady
=
true
;
}
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
clientException
=
e
;
}
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/**
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @library ../../../../templates
* @build SSLCapabilities SSLExplorer
* @run main/othervm SSLSocketExplorerWithSrvSNI
*/
import
java.io.*
;
import
java.nio.*
;
import
java.nio.channels.*
;
import
java.util.*
;
import
java.net.*
;
import
javax.net.ssl.*
;
public
class
SSLSocketExplorerWithSrvSNI
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
true
;
/*
* Where do we find the keystores?
*/
static
String
pathToStores
=
"../../../../etc"
;
static
String
keyStoreFile
=
"keystore"
;
static
String
trustStoreFile
=
"truststore"
;
static
String
passwd
=
"passphrase"
;
/*
* Is the server ready to serve?
*/
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* If the client or server is doing some kind of object creation
* that the other side depends on, and that thread prematurely
* exits, you may experience a hang. The test harness will
* terminate all hung threads after its timeout has expired,
* currently 3 minutes by default, but you might try to be
* smart about it....
*/
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
ServerSocket
serverSocket
=
new
ServerSocket
(
serverPort
);
// Signal Client, we're ready for his connect.
serverPort
=
serverSocket
.
getLocalPort
();
serverReady
=
true
;
Socket
socket
=
serverSocket
.
accept
();
InputStream
ins
=
socket
.
getInputStream
();
byte
[]
buffer
=
new
byte
[
0xFF
];
int
position
=
0
;
SSLCapabilities
capabilities
=
null
;
// Read the header of TLS record
while
(
position
<
SSLExplorer
.
RECORD_HEADER_SIZE
)
{
int
count
=
SSLExplorer
.
RECORD_HEADER_SIZE
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
int
recordLength
=
SSLExplorer
.
getRequiredSize
(
buffer
,
0
,
position
);
if
(
buffer
.
length
<
recordLength
)
{
buffer
=
Arrays
.
copyOf
(
buffer
,
recordLength
);
}
while
(
position
<
recordLength
)
{
int
count
=
recordLength
-
position
;
int
n
=
ins
.
read
(
buffer
,
position
,
count
);
if
(
n
<
0
)
{
throw
new
Exception
(
"unexpected end of stream!"
);
}
position
+=
n
;
}
capabilities
=
SSLExplorer
.
explore
(
buffer
,
0
,
recordLength
);;
if
(
capabilities
!=
null
)
{
System
.
out
.
println
(
"Record version: "
+
capabilities
.
getRecordVersion
());
System
.
out
.
println
(
"Hello version: "
+
capabilities
.
getHelloVersion
());
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
buffer
,
0
,
position
);
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
socket
,
bais
,
true
);
SNIMatcher
matcher
=
SNIHostName
.
createSNIMatcher
(
serverAcceptableHostname
);
Collection
<
SNIMatcher
>
matchers
=
new
ArrayList
<>(
1
);
matchers
.
add
(
matcher
);
SSLParameters
params
=
sslSocket
.
getSSLParameters
();
params
.
setSNIMatchers
(
matchers
);
sslSocket
.
setSSLParameters
(
params
);
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslIS
.
read
();
sslOS
.
write
(
85
);
sslOS
.
flush
();
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
sslSocket
.
getSession
();
checkCapabilities
(
capabilities
,
session
);
sslSocket
.
close
();
serverSocket
.
close
();
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
"localhost"
,
serverPort
);
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslOS
.
write
(
280
);
sslOS
.
flush
();
sslIS
.
read
();
ExtendedSSLSession
session
=
(
ExtendedSSLSession
)
sslSocket
.
getSession
();
checkSNIInSession
(
session
);
sslSocket
.
close
();
}
private
static
String
clientRequestedHostname
=
"www.example.com"
;
private
static
String
serverAcceptableHostname
=
"www\\.example\\.(com|org)"
;
void
checkCapabilities
(
SSLCapabilities
capabilities
,
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(!
sessionSNI
.
equals
(
capabilities
.
getServerNames
()))
{
for
(
SNIServerName
sni
:
sessionSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
List
<
SNIServerName
>
capaSNI
=
capabilities
.
getServerNames
();
for
(
SNIServerName
sni
:
capaSNI
)
{
System
.
out
.
println
(
"SNI in session is "
+
sni
);
}
throw
new
Exception
(
"server name indication does not match capabilities"
);
}
checkSNIInSession
(
session
);
}
void
checkSNIInSession
(
ExtendedSSLSession
session
)
throws
Exception
{
List
<
SNIServerName
>
sessionSNI
=
session
.
getRequestedServerNames
();
if
(!
sessionSNI
.
isEmpty
())
{
throw
new
Exception
(
"should be empty request server name indication"
);
}
}
/*
* =============================================================
* The remainder is just support stuff
*/
// use any free port by default
volatile
int
serverPort
=
0
;
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
keyFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
keyStoreFile
;
String
trustFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
trustStoreFile
;
System
.
setProperty
(
"javax.net.ssl.keyStore"
,
keyFilename
);
System
.
setProperty
(
"javax.net.ssl.keyStorePassword"
,
passwd
);
System
.
setProperty
(
"javax.net.ssl.trustStore"
,
trustFilename
);
System
.
setProperty
(
"javax.net.ssl.trustStorePassword"
,
passwd
);
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Start the tests.
*/
new
SSLSocketExplorerWithSrvSNI
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLSocketExplorerWithSrvSNI
()
throws
Exception
{
try
{
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
}
catch
(
Exception
e
)
{
// swallow for now. Show later
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception
local
;
Exception
remote
;
String
whichRemote
;
if
(
separateServerThread
)
{
remote
=
serverException
;
local
=
clientException
;
whichRemote
=
"server"
;
}
else
{
remote
=
clientException
;
local
=
serverException
;
whichRemote
=
"client"
;
}
/*
* If both failed, return the curthread's exception, but also
* print the remote side Exception
*/
if
((
local
!=
null
)
&&
(
remote
!=
null
))
{
System
.
out
.
println
(
whichRemote
+
" also threw:"
);
remote
.
printStackTrace
();
System
.
out
.
println
();
throw
local
;
}
if
(
remote
!=
null
)
{
throw
remote
;
}
if
(
local
!=
null
)
{
throw
local
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
serverException
=
e
;
}
finally
{
serverReady
=
true
;
}
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
clientException
=
e
;
}
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketInconsistentSNI.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/**
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @run main/othervm SSLSocketInconsistentSNI
*/
import
java.io.*
;
import
java.nio.*
;
import
java.nio.channels.*
;
import
java.util.*
;
import
java.net.*
;
import
javax.net.ssl.*
;
public
class
SSLSocketInconsistentSNI
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
true
;
/*
* Where do we find the keystores?
*/
static
String
pathToStores
=
"../../../../etc"
;
static
String
keyStoreFile
=
"keystore"
;
static
String
trustStoreFile
=
"truststore"
;
static
String
passwd
=
"passphrase"
;
/*
* Is the server ready to serve?
*/
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* If the client or server is doing some kind of object creation
* that the other side depends on, and that thread prematurely
* exits, you may experience a hang. The test harness will
* terminate all hung threads after its timeout has expired,
* currently 3 minutes by default, but you might try to be
* smart about it....
*/
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
SSLServerSocketFactory
sslssf
=
(
SSLServerSocketFactory
)
SSLServerSocketFactory
.
getDefault
();
SSLServerSocket
sslServerSocket
=
(
SSLServerSocket
)
sslssf
.
createServerSocket
(
serverPort
);
SNIMatcher
matcher
=
SNIHostName
.
createSNIMatcher
(
serverAcceptableHostname
);
Collection
<
SNIMatcher
>
matchers
=
new
ArrayList
<>(
1
);
matchers
.
add
(
matcher
);
SSLParameters
params
=
sslServerSocket
.
getSSLParameters
();
params
.
setSNIMatchers
(
matchers
);
sslServerSocket
.
setSSLParameters
(
params
);
serverPort
=
sslServerSocket
.
getLocalPort
();
/*
* Signal Client, we're ready for his connect.
*/
serverReady
=
true
;
SSLSocket
sslSocket
=
(
SSLSocket
)
sslServerSocket
.
accept
();
try
{
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslIS
.
read
();
sslOS
.
write
(
85
);
sslOS
.
flush
();
throw
new
Exception
(
"Mismatched server name indication was accepted"
);
}
catch
(
SSLHandshakeException
sslhe
)
{
// the expected unrecognized server name indication exception
}
catch
(
IOException
ioe
)
{
// the peer may have closed the socket because of the unmatched
// server name indication.
}
finally
{
sslSocket
.
close
();
sslServerSocket
.
close
();
}
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
SSLSocketFactory
sslsf
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
"localhost"
,
serverPort
);
SNIHostName
serverName
=
new
SNIHostName
(
clientRequestedHostname
);
List
<
SNIServerName
>
serverNames
=
new
ArrayList
<>(
1
);
serverNames
.
add
(
serverName
);
SSLParameters
params
=
sslSocket
.
getSSLParameters
();
params
.
setServerNames
(
serverNames
);
sslSocket
.
setSSLParameters
(
params
);
try
{
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslOS
.
write
(
280
);
sslOS
.
flush
();
sslIS
.
read
();
throw
new
Exception
(
"Mismatched server name indication was accepted"
);
}
catch
(
SSLHandshakeException
sslhe
)
{
// the expected unrecognized server name indication exception
}
catch
(
IOException
ioe
)
{
// the peer may have closed the socket because of the unmatched
// server name indication.
}
finally
{
sslSocket
.
close
();
}
}
private
static
String
clientRequestedHostname
=
"www.example.com"
;
private
static
String
serverAcceptableHostname
=
"www\\.example\\.org"
;
/*
* =============================================================
* The remainder is just support stuff
*/
// use any free port by default
volatile
int
serverPort
=
0
;
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
keyFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
keyStoreFile
;
String
trustFilename
=
System
.
getProperty
(
"test.src"
,
"."
)
+
"/"
+
pathToStores
+
"/"
+
trustStoreFile
;
System
.
setProperty
(
"javax.net.ssl.keyStore"
,
keyFilename
);
System
.
setProperty
(
"javax.net.ssl.keyStorePassword"
,
passwd
);
System
.
setProperty
(
"javax.net.ssl.trustStore"
,
trustFilename
);
System
.
setProperty
(
"javax.net.ssl.trustStorePassword"
,
passwd
);
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Start the tests.
*/
new
SSLSocketInconsistentSNI
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLSocketInconsistentSNI
()
throws
Exception
{
try
{
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
}
catch
(
Exception
e
)
{
// swallow for now. Show later
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception
local
;
Exception
remote
;
String
whichRemote
;
if
(
separateServerThread
)
{
remote
=
serverException
;
local
=
clientException
;
whichRemote
=
"server"
;
}
else
{
remote
=
clientException
;
local
=
serverException
;
whichRemote
=
"client"
;
}
/*
* If both failed, return the curthread's exception, but also
* print the remote side Exception
*/
if
((
local
!=
null
)
&&
(
remote
!=
null
))
{
System
.
out
.
println
(
whichRemote
+
" also threw:"
);
remote
.
printStackTrace
();
System
.
out
.
println
();
throw
local
;
}
if
(
remote
!=
null
)
{
throw
remote
;
}
if
(
local
!=
null
)
{
throw
local
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
serverException
=
e
;
}
finally
{
serverReady
=
true
;
}
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
clientException
=
e
;
}
}
}
}
test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketSNISensitive.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
* @bug 7068321
* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
* @run main/othervm SSLSocketSNISensitive PKIX www.example.com
* @run main/othervm SSLSocketSNISensitive SunX509 www.example.com
* @run main/othervm SSLSocketSNISensitive PKIX www.example.net
* @run main/othervm SSLSocketSNISensitive SunX509 www.example.net
* @run main/othervm SSLSocketSNISensitive PKIX www.invalid.com
* @run main/othervm SSLSocketSNISensitive SunX509 www.invalid.com
*/
import
java.net.*
;
import
java.util.*
;
import
java.io.*
;
import
javax.net.ssl.*
;
import
java.security.KeyStore
;
import
java.security.KeyFactory
;
import
java.security.cert.Certificate
;
import
java.security.cert.X509Certificate
;
import
java.security.cert.CertificateFactory
;
import
java.security.spec.*
;
import
java.security.interfaces.*
;
import
sun.misc.BASE64Decoder
;
public
class
SSLSocketSNISensitive
{
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static
boolean
separateServerThread
=
false
;
/*
* Where do we find the keystores?
*/
// Certificates and key used in the test.
static
String
trustedCertStr
=
"-----BEGIN CERTIFICATE-----\n"
+
"MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n"
+
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n"
+
"MTIwNDE3MTIwNjA3WhcNMzMwMzI4MTIwNjA3WjA7MQswCQYDVQQGEwJVUzENMAsG\n"
+
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n"
+
"KoZIhvcNAQEBBQADgY0AMIGJAoGBANY+7Enp+1S566kLcKk+qe4Ki6BxaHGZ+v7r\n"
+
"vLksx9IQZCbAEf4YLbrZhKzKD3SPIJXyxPFwknAknIh3Knk8mViOZks7T8L3GnJr\n"
+
"TBaVvDyTzDJum/QYiahfO2qpfN/Oya2UILmqsBAeLyWpzbQsAyWBXfoUtkOUgnzK\n"
+
"fk6QAKYrAgMBAAGjgaUwgaIwHQYDVR0OBBYEFEtmQi7jT1ijXOafPsfkrLwSVu9e\n"
+
"MGMGA1UdIwRcMFqAFEtmQi7jT1ijXOafPsfkrLwSVu9eoT+kPTA7MQswCQYDVQQG\n"
+
"EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n"
+
"Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n"
+
"BQADgYEAkKWxMc4+ODk5WwLXXweB8/IKfVfrizNn0KLEgsZ6xNXFIXDpiPGAFcgl\n"
+
"MzFO424JgyvUulsUc/X16Cnuwwntkk6KUG7vEV7h4o9sAV7Cax3gfQE/EZFb4ybn\n"
+
"aBm1UsujMKd/ovqbbbxJbmOWzCeo0QfIGleDEyh3NBBZ0i11Kiw=\n"
+
"-----END CERTIFICATE-----"
;
// web server certificate, www.example.com
static
String
targetCertStr_A
=
"-----BEGIN CERTIFICATE-----\n"
+
"MIICVTCCAb6gAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n"
+
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n"
+
"MTIwNDE3MTIwNjA4WhcNMzIwMTAzMTIwNjA4WjBVMQswCQYDVQQGEwJVUzENMAsG\n"
+
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n"
+
"BAMTD3d3dy5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n"
+
"4zFp3PZNzsd3ZwG6FNNWO9eSN+UBymlf8oCwpKJM2tIinmMWvWIXnlx/2UXIfSAq\n"
+
"QEG3aXkAFyEiGGpQlBbqcfrESsHsiz2pnnm5dG2v/eS0Bwz1jmcuNmwnh3UQw2Vl\n"
+
"+BLk8ukdrLjiCT8jARiHExYf1Xg+wUqQ9y8NV26hdaUCAwEAAaNPME0wCwYDVR0P\n"
+
"BAQDAgPoMB0GA1UdDgQWBBQwtx+gqzn2w4y82brXlp7tqBYEZDAfBgNVHSMEGDAW\n"
+
"gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQAJWo8B6Ud+\n"
+
"/OU+UcZLihlfMX02OSlK2ZB7mfqpj2G3JT9yb0A+VbY3uuajmaYYIIxl3kXGz/n8\n"
+
"M2Q/Ux/MDxG+IFKHC26Kuj4dAQgzjq2pILVPTE2QnaQTNCsgVZtTaC47SG9FRSoC\n"
+
"qvnIvn/oTpKSqus76I1cR4joDtiV2OEuVw==\n"
+
"-----END CERTIFICATE-----"
;
// Private key in the format of PKCS#8
static
String
targetPrivateKey_A
=
"MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOMxadz2Tc7Hd2cB\n"
+
"uhTTVjvXkjflAcppX/KAsKSiTNrSIp5jFr1iF55cf9lFyH0gKkBBt2l5ABchIhhq\n"
+
"UJQW6nH6xErB7Is9qZ55uXRtr/3ktAcM9Y5nLjZsJ4d1EMNlZfgS5PLpHay44gk/\n"
+
"IwEYhxMWH9V4PsFKkPcvDVduoXWlAgMBAAECgYAqX2nuIyXp3fvgA0twXOYlbRRB\n"
+
"Rn3qAXM6qFPJsNeCrFR2k+aG1cev6nKR1FkLNTeMGnWZv06MAcr5IML8i7WXyG4C\n"
+
"LY/C0gedn94FDKFlln+bTENwQTGjn4lKysDA+IuNpasTeMCajbic+dPByhIdTOjZ\n"
+
"iMCyxbLfpk40zQopVQJBAPyfGmkeHB3GjdbdgujWCGKb2UxBa4O8dy3O4l2yizTn\n"
+
"uUqMGcwGY4ciNSVvZQ7jKo4vDmkSuYib4/woPChaNfMCQQDmO0BQuSWYGNtSwV35\n"
+
"lafZfX1dNCLKm1iNA6A12evXgvQiE9WT4mqionig0VZW16HtiY4/BkHOcos/K9Um\n"
+
"ARQHAkA8mkaRtSF1my5nv1gqVz5Hua+VdZQ/VDUbDiiL5cszc+ulkJqXsWirAG/T\n"
+
"fTe3LJQG7A7+8fkEZrF4yoY0AAA1AkEAotokezULj5N9iAL5SzL9wIzQYV4ggfny\n"
+
"YATBjXXxKccakwQ+ndWZIiMUeoS4ssLialhTgucVI0fIkU2a/r/ifwJAc6e+5Pvh\n"
+
"MghQj/U788Od/v6rgqz/NGsduZ7uilCMcWiwA73OR2MHMH/OIuoofuEPrfuV9isV\n"
+
"xVXhgpKfP/pdOA=="
;
// web server certificate, www.example.net
static
String
targetCertStr_B
=
"-----BEGIN CERTIFICATE-----\n"
+
"MIICVTCCAb6gAwIBAgIBBDANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n"
+
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n"
+
"MTIwNDE3MTIwNjA5WhcNMzIwMTAzMTIwNjA5WjBVMQswCQYDVQQGEwJVUzENMAsG\n"
+
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n"
+
"BAMTD3d3dy5leGFtcGxlLm5ldDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n"
+
"2VlzF1fvWYczDChrUeJiLJ1M/dIShCaOTfYGiXfQGEZCAWTacUclwr+rVMnZ75/c\n"
+
"wwg5pNdXRijxMil8DBTS1gFcIFQhosLHvzIAe6ULlg/xB+/L6KBz+NTWfo/2KF6t\n"
+
"xatmcToNrCcwi7eUOfbzQje65Tizs56jJYem2m7Rk0ECAwEAAaNPME0wCwYDVR0P\n"
+
"BAQDAgPoMB0GA1UdDgQWBBQT/FR0cAWcZQ7h0X79KGki34OSQjAfBgNVHSMEGDAW\n"
+
"gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQB67cPIT6fz\n"
+
"6Ws8fBpYgW2ad4ci66i1WduBD9CpGFE+jRK2feRj6hvYBXocKj0AMWUFIEB2E3hA\n"
+
"oIjxcf1GxIpHVl9DjlhxqXbA0Ktl7/NGNRlDSLTizOTl3FB1mMTlOGvXDVmpcFhl\n"
+
"HuoP1hYvhTsBwPx5igGNchuPtDIUzL2mXw==\n"
+
"-----END CERTIFICATE-----"
;
static
String
targetPrivateKey_B
=
"MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANlZcxdX71mHMwwo\n"
+
"a1HiYiydTP3SEoQmjk32Bol30BhGQgFk2nFHJcK/q1TJ2e+f3MMIOaTXV0Yo8TIp\n"
+
"fAwU0tYBXCBUIaLCx78yAHulC5YP8Qfvy+igc/jU1n6P9ihercWrZnE6DawnMIu3\n"
+
"lDn280I3uuU4s7OeoyWHptpu0ZNBAgMBAAECgYEAl19H26sfhD+32rDPxZCgBShs\n"
+
"dZ33zVe45i0Bcn4iTLWpxKTDyf7eGps4rO2DvfKdYqt40ggzvSZIjUH9JcDe8GmG\n"
+
"d3m0ILB7pg4jsFlpyeHpTO8grPLxA1G9s3o0DoFpz/rooqgFfe/DrRDmRoOSkgfV\n"
+
"/gseIbgJHRO/Ctyvdh0CQQD6uFd0HxhH1jl/JzvPzIH4LSnPcdEh9zsMEb6uzh75\n"
+
"9qL+IHD5N2I/pYZTKqDFIwhJf701+LKag55AX/zrDt7rAkEA3e00AbnwanDMa6Wj\n"
+
"+gFekUQveSVra38LiihzCkyVvQpFjbiF1rUhSNQ0dpU5/hmrYF0C6H9VXAesfkUY\n"
+
"WhpDgwJAYjgZOop77piDycZK7isFt32p5XSHIzFBVocVFlH1XKM8UyXOXDNQL/Le\n"
+
"XnJSrSf+NRzvuNcG0PVC56Ey6brXpQJAY4M4vcltt5zq3R5CQBmbGRJ1IyKXX3Vx\n"
+
"bDslEqoyvri7ZYgnY5aG3UxiVgYmIf3KrgQnCLAIS6MZQumiuMxsFwJAK5pEG063\n"
+
"9ngUof4fDMvZphqZjZR1zMKz/V/9ge0DWBINaqFgsgebNu+MyImsC8C6WKjGmV/2\n"
+
"f1MY0D7sC2vU/Q=="
;
// web server certificate, www.invalid.com
static
String
targetCertStr_C
=
"-----BEGIN CERTIFICATE-----\n"
+
"MIICVTCCAb6gAwIBAgIBAzANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n"
+
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n"
+
"MTIwNDE3MTIwNjA5WhcNMzIwMTAzMTIwNjA5WjBVMQswCQYDVQQGEwJVUzENMAsG\n"
+
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n"
+
"BAMTD3d3dy5pbnZhbGlkLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n"
+
"q6MyQwzCr2nJ41l0frmHL0qULSyW51MhevBC+1W28i0LE/efrmpwV3LdnlQEGFak\n"
+
"DLDwtnff3iru8dSMcA7KdWVkivsE7ZTP+qFDaWBAy7XXiSsv6yZ2Nh4jJb0YcD28\n"
+
"45zk2nAl5Az1/PuoTi1vpQxzFZKuBm1HGgz3MEZvBvMCAwEAAaNPME0wCwYDVR0P\n"
+
"BAQDAgPoMB0GA1UdDgQWBBRRMifrND015Nm8N6gV5X7cg1YjjjAfBgNVHSMEGDAW\n"
+
"gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQBjkUO6Ri/B\n"
+
"uDC2gDMIyL5+NTe/1dPPQYM4HhCNa/KQYvU5lzCKO9Vpa+i+nyrUNNXUu8Tkyq4Y\n"
+
"A+aGSm6+FT/i9rFwkYUdorBtD3KfQiwTIWrVERXBkWI5iZNaVZhx0TFy4vUpf65d\n"
+
"QtwkbHpC66fdKc2EdLXkuY9KkmtZZJJ7YA==\n"
+
"-----END CERTIFICATE-----"
;
static
String
targetPrivateKey_C
=
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKujMkMMwq9pyeNZ\n"
+
"dH65hy9KlC0sludTIXrwQvtVtvItCxP3n65qcFdy3Z5UBBhWpAyw8LZ3394q7vHU\n"
+
"jHAOynVlZIr7BO2Uz/qhQ2lgQMu114krL+smdjYeIyW9GHA9vOOc5NpwJeQM9fz7\n"
+
"qE4tb6UMcxWSrgZtRxoM9zBGbwbzAgMBAAECgYASJDK40Y12Wvki1Z6xkkyOnBRj\n"
+
"XfYpRykfxGtgA2RN3qLwHlk7Zzaul46DIKA6LlYynTUkJDF+Ww1cdDnP0lBlwcmM\n"
+
"iD0ck3zYyYBLhQHuVbkK3SYE+ANRhM0icvvqANP2at/U4awQcPNEae/KCiecLNu3\n"
+
"CJGqyhPDdrEAqPuJGQJBAN46pQC6l3yrcSYE2s53jSmsm2HVVOFlFXjU6k/RMTxG\n"
+
"FfDJtGUAOQ37rPQ06ugr/gjLAmmPp+FXozaBdA32D80CQQDFuGRgv3WYqbglIcRL\n"
+
"JRs6xlj9w1F97s/aiUenuwhIPNiUoRbV7mnNuZ/sGF0svOVE7SazRjuFX6UqL9Y9\n"
+
"HzG/AkEA170pCI8cl4w8eUNHRB9trGKEKjMXhwVCFh7lJf2ZBcGodSzr8w2HVhrZ\n"
+
"Ke7hiemDYffrbJ1oxmv05+o+x3r0lQJBAL6adVm2+FyFMFnLZXmzeb59O4jWY5bt\n"
+
"Qz6/HG6bpO5OidMuP99YCHMkQQDOs/PO3Y5GuAoW6IY4n/Y9S2B80+0CQBl1/H9/\n"
+
"0n/vrb6vW6Azds49tuS82RFAnOhtwTyBEajs08WF8rZQ3WD2RHJnH0+jjfL0anIp\n"
+
"dQBSeNN7s7b6rRk="
;
// This is a certificate for client
static
String
targetCertStr_D
=
"-----BEGIN CERTIFICATE-----\n"
+
"MIICVDCCAb2gAwIBAgIBBTANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n"
+
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n"
+
"MTIwNDE3MTIwNjEwWhcNMzIwMTAzMTIwNjEwWjBUMQswCQYDVQQGEwJVUzENMAsG\n"
+
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxFzAVBgNV\n"
+
"BAMTDkludGVyT3AgVGVzdGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo\n"
+
"Q/KoAIAC2ljFfW2KwjnxTzi4NQJeUuk2seqKpsAY8x4O5dvixzUl6142zmljapqi\n"
+
"bJloQVpfB+CEc5/l4h5gzGRVzkuqP1oPzDrpZ5GsvmvuHenV/TzCIgX1cLETzQVt\n"
+
"6Rk06okoBPnw3hDJEJiEc1Rv7HCE8p/p+SaiHrskwwIDAQABo08wTTALBgNVHQ8E\n"
+
"BAMCA+gwHQYDVR0OBBYEFPr91O33RIGfFSqza2AwQIgE4QswMB8GA1UdIwQYMBaA\n"
+
"FEtmQi7jT1ijXOafPsfkrLwSVu9eMA0GCSqGSIb3DQEBBAUAA4GBANIDFYgAhoj3\n"
+
"B8u1YpqeoEp2Lt9TwrYBshaIrbmBPCwCGio0JIsoov3n8BCSg5F+8MnOtPl+TjeO\n"
+
"0Ug+7guPdCk/wg8YNxLHgSsQlpcNJDjWiErqmUPVrg5BPPQb65qMund6KTmMN0y6\n"
+
"4EbSmxRpZO/N0/5oK4umTk0EeXKNekBj\n"
+
"-----END CERTIFICATE-----"
;
static
String
targetPrivateKey_D
=
"MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOhD8qgAgALaWMV9\n"
+
"bYrCOfFPOLg1Al5S6Tax6oqmwBjzHg7l2+LHNSXrXjbOaWNqmqJsmWhBWl8H4IRz\n"
+
"n+XiHmDMZFXOS6o/Wg/MOulnkay+a+4d6dX9PMIiBfVwsRPNBW3pGTTqiSgE+fDe\n"
+
"EMkQmIRzVG/scITyn+n5JqIeuyTDAgMBAAECgYBw37yIKp4LRONJLnhSq6sO+0n8\n"
+
"Mz6waiiN/Q6XTQwj09pysQAYCGlqwSRrDAqpVsBJWO+Ae+oYLrLMi4hUZnwN75v3\n"
+
"pe1nXlrD11RmPLXwBxqFxNSvAs2FgLHZEtwHI7Bn8KybT/8bGkQ8csLceInYtMDD\n"
+
"MuTyy2KRk/pj60zIKQJBAPgebQiAH6viFQ88AwHaNvQhlUfwmSC1i6f8LVoeqaHC\n"
+
"lnP0LJBwlyDeeEInhHrCR2ibnCB6I/Pig+49XQgabK8CQQDvpJwuGEbsOO+3rkJJ\n"
+
"OpOw4toG0QJZdRnT6l8I6BlboQRZSfFh+lGGahvFXkxc4KdUpJ7QPtXU7HHk6Huk\n"
+
"8RYtAkA9CW8VGj+wTuuTVdX/jKjcIa7RhbSFwWNbrcOSWdys+Gt+luCnn6rt4QyA\n"
+
"aaxDbquWZkFgE+voQR7nap0KM0XtAkAznd0WAJymHM1lXt9gLoHJQ9N6TGKZKiPa\n"
+
"BU1a+cMcfV4WbVrUo7oTnZ9Fr73681iXXq3mZOJh7lvJ1llreZIxAkBEnbiTgEf4\n"
+
"tvku68jHcRbRPmdS7CBSWNEBaHLOm4pUSTcxVTKKMHw7vmM5/UYUxJ8QNKCYxn6O\n"
+
"+vtiBwBawwzN"
;
static
String
[]
serverCerts
=
{
targetCertStr_A
,
targetCertStr_B
,
targetCertStr_C
};
static
String
[]
serverKeys
=
{
targetPrivateKey_A
,
targetPrivateKey_B
,
targetPrivateKey_C
};
static
String
[]
clientCerts
=
{
targetCertStr_D
};
static
String
[]
clientKeys
=
{
targetPrivateKey_D
};
static
char
passphrase
[]
=
"passphrase"
.
toCharArray
();
/*
* Is the server ready to serve?
*/
volatile
static
boolean
serverReady
=
false
;
/*
* Turn on SSL debugging?
*/
static
boolean
debug
=
false
;
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doServerSide
()
throws
Exception
{
SSLContext
context
=
generateSSLContext
(
false
);
SSLServerSocketFactory
sslssf
=
context
.
getServerSocketFactory
();
SSLServerSocket
sslServerSocket
=
(
SSLServerSocket
)
sslssf
.
createServerSocket
(
serverPort
);
serverPort
=
sslServerSocket
.
getLocalPort
();
/*
* Signal Client, we're ready for his connect.
*/
serverReady
=
true
;
SSLSocket
sslSocket
=
(
SSLSocket
)
sslServerSocket
.
accept
();
try
{
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslIS
.
read
();
sslOS
.
write
(
'A'
);
sslOS
.
flush
();
SSLSession
session
=
sslSocket
.
getSession
();
checkCertificate
(
session
.
getLocalCertificates
(),
clientRequestedHostname
);
}
finally
{
sslSocket
.
close
();
sslServerSocket
.
close
();
}
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void
doClientSide
()
throws
Exception
{
/*
* Wait for server to get started.
*/
while
(!
serverReady
)
{
Thread
.
sleep
(
50
);
}
SSLContext
context
=
generateSSLContext
(
true
);
SSLSocketFactory
sslsf
=
context
.
getSocketFactory
();
SSLSocket
sslSocket
=
(
SSLSocket
)
sslsf
.
createSocket
(
"localhost"
,
serverPort
);
SNIHostName
serverName
=
new
SNIHostName
(
clientRequestedHostname
);
List
<
SNIServerName
>
serverNames
=
new
ArrayList
<>(
1
);
serverNames
.
add
(
serverName
);
SSLParameters
params
=
sslSocket
.
getSSLParameters
();
params
.
setServerNames
(
serverNames
);
sslSocket
.
setSSLParameters
(
params
);
try
{
InputStream
sslIS
=
sslSocket
.
getInputStream
();
OutputStream
sslOS
=
sslSocket
.
getOutputStream
();
sslOS
.
write
(
'B'
);
sslOS
.
flush
();
sslIS
.
read
();
SSLSession
session
=
sslSocket
.
getSession
();
checkCertificate
(
session
.
getPeerCertificates
(),
clientRequestedHostname
);
}
finally
{
sslSocket
.
close
();
}
}
private
static
void
checkCertificate
(
Certificate
[]
certs
,
String
hostname
)
throws
Exception
{
if
(
certs
!=
null
&&
certs
.
length
!=
0
)
{
X509Certificate
x509Cert
=
(
X509Certificate
)
certs
[
0
];
String
subject
=
x509Cert
.
getSubjectX500Principal
().
getName
();
if
(!
subject
.
contains
(
hostname
))
{
throw
new
Exception
(
"Not the expected certificate: "
+
subject
);
}
}
}
/*
* =============================================================
* The remainder is just support stuff
*/
private
static
String
tmAlgorithm
;
// trust manager
private
static
String
clientRequestedHostname
;
// server name indication
private
static
void
parseArguments
(
String
[]
args
)
{
tmAlgorithm
=
args
[
0
];
clientRequestedHostname
=
args
[
1
];
}
private
static
SSLContext
generateSSLContext
(
boolean
isClient
)
throws
Exception
{
// generate certificate from cert string
CertificateFactory
cf
=
CertificateFactory
.
getInstance
(
"X.509"
);
// create a key store
KeyStore
ks
=
KeyStore
.
getInstance
(
"JKS"
);
ks
.
load
(
null
,
null
);
// import the trused cert
ByteArrayInputStream
is
=
new
ByteArrayInputStream
(
trustedCertStr
.
getBytes
());
Certificate
trusedCert
=
cf
.
generateCertificate
(
is
);
is
.
close
();
ks
.
setCertificateEntry
(
"RSA Export Signer"
,
trusedCert
);
String
[]
certStrs
=
null
;
String
[]
keyStrs
=
null
;
if
(
isClient
)
{
certStrs
=
clientCerts
;
keyStrs
=
clientKeys
;
}
else
{
certStrs
=
serverCerts
;
keyStrs
=
serverKeys
;
}
for
(
int
i
=
0
;
i
<
certStrs
.
length
;
i
++)
{
// generate the private key.
String
keySpecStr
=
keyStrs
[
i
];
PKCS8EncodedKeySpec
priKeySpec
=
new
PKCS8EncodedKeySpec
(
new
BASE64Decoder
().
decodeBuffer
(
keySpecStr
));
KeyFactory
kf
=
KeyFactory
.
getInstance
(
"RSA"
);
RSAPrivateKey
priKey
=
(
RSAPrivateKey
)
kf
.
generatePrivate
(
priKeySpec
);
// generate certificate chain
String
keyCertStr
=
certStrs
[
i
];
is
=
new
ByteArrayInputStream
(
keyCertStr
.
getBytes
());
Certificate
keyCert
=
cf
.
generateCertificate
(
is
);
is
.
close
();
Certificate
[]
chain
=
new
Certificate
[
2
];
chain
[
0
]
=
keyCert
;
chain
[
1
]
=
trusedCert
;
// import the key entry.
ks
.
setKeyEntry
(
"key-entry-"
+
i
,
priKey
,
passphrase
,
chain
);
}
// create SSL context
TrustManagerFactory
tmf
=
TrustManagerFactory
.
getInstance
(
tmAlgorithm
);
tmf
.
init
(
ks
);
SSLContext
ctx
=
SSLContext
.
getInstance
(
"TLS"
);
KeyManagerFactory
kmf
=
KeyManagerFactory
.
getInstance
(
"NewSunX509"
);
kmf
.
init
(
ks
,
passphrase
);
ctx
.
init
(
kmf
.
getKeyManagers
(),
tmf
.
getTrustManagers
(),
null
);
ks
=
null
;
return
ctx
;
}
// use any free port by default
volatile
int
serverPort
=
0
;
volatile
Exception
serverException
=
null
;
volatile
Exception
clientException
=
null
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
if
(
debug
)
System
.
setProperty
(
"javax.net.debug"
,
"all"
);
/*
* Get the customized arguments.
*/
parseArguments
(
args
);
/*
* Start the tests.
*/
new
SSLSocketSNISensitive
();
}
Thread
clientThread
=
null
;
Thread
serverThread
=
null
;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
SSLSocketSNISensitive
()
throws
Exception
{
try
{
if
(
separateServerThread
)
{
startServer
(
true
);
startClient
(
false
);
}
else
{
startClient
(
true
);
startServer
(
false
);
}
}
catch
(
Exception
e
)
{
// swallow for now. Show later
}
/*
* Wait for other side to close down.
*/
if
(
separateServerThread
)
{
serverThread
.
join
();
}
else
{
clientThread
.
join
();
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception
local
;
Exception
remote
;
String
whichRemote
;
if
(
separateServerThread
)
{
remote
=
serverException
;
local
=
clientException
;
whichRemote
=
"server"
;
}
else
{
remote
=
clientException
;
local
=
serverException
;
whichRemote
=
"client"
;
}
/*
* If both failed, return the curthread's exception, but also
* print the remote side Exception
*/
if
((
local
!=
null
)
&&
(
remote
!=
null
))
{
System
.
out
.
println
(
whichRemote
+
" also threw:"
);
remote
.
printStackTrace
();
System
.
out
.
println
();
throw
local
;
}
if
(
remote
!=
null
)
{
throw
remote
;
}
if
(
local
!=
null
)
{
throw
local
;
}
}
void
startServer
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
serverThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System
.
err
.
println
(
"Server died..."
);
serverReady
=
true
;
serverException
=
e
;
}
}
};
serverThread
.
start
();
}
else
{
try
{
doServerSide
();
}
catch
(
Exception
e
)
{
serverException
=
e
;
}
finally
{
serverReady
=
true
;
}
}
}
void
startClient
(
boolean
newThread
)
throws
Exception
{
if
(
newThread
)
{
clientThread
=
new
Thread
()
{
public
void
run
()
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
/*
* Our client thread just died.
*/
System
.
err
.
println
(
"Client died..."
);
clientException
=
e
;
}
}
};
clientThread
.
start
();
}
else
{
try
{
doClientSide
();
}
catch
(
Exception
e
)
{
clientException
=
e
;
}
}
}
}
test/sun/security/ssl/templates/SSLCapabilities.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
import
java.util.List
;
import
javax.net.ssl.SNIServerName
;
/**
* Encapsulates the security capabilities of an SSL/TLS connection.
* <P>
* The security capabilities are the list of ciphersuites to be accepted in
* an SSL/TLS handshake, the record version, the hello version, and server
* name indication, etc., of an SSL/TLS connection.
* <P>
* <code>SSLCapabilities</code> can be retrieved by exploring the network
* data of an SSL/TLS connection via {@link SSLExplorer#explore(ByteBuffer)}
* or {@link SSLExplorer#explore(byte[], int, int)}.
*
* @see SSLExplorer
*/
public
abstract
class
SSLCapabilities
{
/**
* Returns the record version of an SSL/TLS connection
*
* @return a non-null record version
*/
public
abstract
String
getRecordVersion
();
/**
* Returns the hello version of an SSL/TLS connection
*
* @return a non-null hello version
*/
public
abstract
String
getHelloVersion
();
/**
* Returns a <code>List</code> containing all {@link SNIServerName}s
* of the server name indication.
*
* @return a non-null immutable list of {@link SNIServerName}s
* of the server name indication parameter, may be empty
* if no server name indication.
*
* @see SNIServerName
*/
public
abstract
List
<
SNIServerName
>
getServerNames
();
}
test/sun/security/ssl/templates/SSLExplorer.java
0 → 100644
浏览文件 @
b80ffe55
/*
* Copyright (c) 2012, 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.
*/
import
java.nio.ByteBuffer
;
import
java.nio.BufferUnderflowException
;
import
java.io.IOException
;
import
javax.net.ssl.*
;
import
java.util.*
;
import
sun.misc.HexDumpEncoder
;
/**
* Instances of this class acts as an explorer of the network data of an
* SSL/TLS connection.
*/
public
final
class
SSLExplorer
{
// Private constructor prevents construction outside this class.
private
SSLExplorer
()
{
}
/**
* The header size of TLS/SSL records.
* <P>
* The value of this constant is {@value}.
*/
public
final
static
int
RECORD_HEADER_SIZE
=
0x05
;
/**
* Returns the required number of bytes in the {@code source}
* {@link ByteBuffer} necessary to explore SSL/TLS connection.
* <P>
* This method tries to parse as few bytes as possible from
* {@code source} byte buffer to get the length of an
* SSL/TLS record.
* <P>
* This method accesses the {@code source} parameter in read-only
* mode, and does not update the buffer's properties such as capacity,
* limit, position, and mark values.
*
* @param source
* a {@link ByteBuffer} containing
* inbound or outbound network data for an SSL/TLS connection.
* @throws BufferUnderflowException if less than {@code RECORD_HEADER_SIZE}
* bytes remaining in {@code source}
* @return the required size in byte to explore an SSL/TLS connection
*/
public
final
static
int
getRequiredSize
(
ByteBuffer
source
)
{
ByteBuffer
input
=
source
.
duplicate
();
// Do we have a complete header?
if
(
input
.
remaining
()
<
RECORD_HEADER_SIZE
)
{
throw
new
BufferUnderflowException
();
}
// Is it a handshake message?
byte
firstByte
=
input
.
get
();
byte
secondByte
=
input
.
get
();
byte
thirdByte
=
input
.
get
();
if
((
firstByte
&
0x80
)
!=
0
&&
thirdByte
==
0x01
)
{
// looks like a V2ClientHello
// return (((firstByte & 0x7F) << 8) | (secondByte & 0xFF)) + 2;
return
RECORD_HEADER_SIZE
;
// Only need the header fields
}
else
{
return
(((
input
.
get
()
&
0xFF
)
<<
8
)
|
(
input
.
get
()
&
0xFF
))
+
5
;
}
}
/**
* Returns the required number of bytes in the {@code source} byte array
* necessary to explore SSL/TLS connection.
* <P>
* This method tries to parse as few bytes as possible from
* {@code source} byte array to get the length of an
* SSL/TLS record.
*
* @param source
* a byte array containing inbound or outbound network data for
* an SSL/TLS connection.
* @param offset
* the start offset in array {@code source} at which the
* network data is read from.
* @param length
* the maximum number of bytes to read.
*
* @throws BufferUnderflowException if less than {@code RECORD_HEADER_SIZE}
* bytes remaining in {@code source}
* @return the required size in byte to explore an SSL/TLS connection
*/
public
final
static
int
getRequiredSize
(
byte
[]
source
,
int
offset
,
int
length
)
throws
IOException
{
ByteBuffer
byteBuffer
=
ByteBuffer
.
wrap
(
source
,
offset
,
length
).
asReadOnlyBuffer
();
return
getRequiredSize
(
byteBuffer
);
}
/**
* Launch and explore the security capabilities from byte buffer.
* <P>
* This method tries to parse as few records as possible from
* {@code source} byte buffer to get the {@link SSLCapabilities}
* of an SSL/TLS connection.
* <P>
* Please NOTE that this method must be called before any handshaking
* occurs. The behavior of this method is not defined in this release
* if the handshake has begun, or has completed.
* <P>
* This method accesses the {@code source} parameter in read-only
* mode, and does not update the buffer's properties such as capacity,
* limit, position, and mark values.
*
* @param source
* a {@link ByteBuffer} containing
* inbound or outbound network data for an SSL/TLS connection.
*
* @throws IOException on network data error
* @throws BufferUnderflowException if not enough source bytes available
* to make a complete exploration.
*
* @return the explored {@link SSLCapabilities} of the SSL/TLS
* connection
*/
public
final
static
SSLCapabilities
explore
(
ByteBuffer
source
)
throws
IOException
{
ByteBuffer
input
=
source
.
duplicate
();
// Do we have a complete header?
if
(
input
.
remaining
()
<
RECORD_HEADER_SIZE
)
{
throw
new
BufferUnderflowException
();
}
// Is it a handshake message?
byte
firstByte
=
input
.
get
();
byte
secondByte
=
input
.
get
();
byte
thirdByte
=
input
.
get
();
if
((
firstByte
&
0x80
)
!=
0
&&
thirdByte
==
0x01
)
{
// looks like a V2ClientHello
return
exploreV2HelloRecord
(
input
,
firstByte
,
secondByte
,
thirdByte
);
}
else
if
(
firstByte
==
22
)
{
// 22: handshake record
return
exploreTLSRecord
(
input
,
firstByte
,
secondByte
,
thirdByte
);
}
else
{
throw
new
SSLException
(
"Not handshake record"
);
}
}
/**
* Launch and explore the security capabilities from byte array.
* <P>
* Please NOTE that this method must be called before any handshaking
* occurs. The behavior of this method is not defined in this release
* if the handshake has begun, or has completed. Once handshake has
* begun, or has completed, the security capabilities can not and
* should not be launched with this method.
*
* @param source
* a byte array containing inbound or outbound network data for
* an SSL/TLS connection.
* @param offset
* the start offset in array {@code source} at which the
* network data is read from.
* @param length
* the maximum number of bytes to read.
*
* @throws IOException on network data error
* @throws BufferUnderflowException if not enough source bytes available
* to make a complete exploration.
* @return the explored {@link SSLCapabilities} of the SSL/TLS
* connection
*
* @see #explore(ByteBuffer)
*/
public
final
static
SSLCapabilities
explore
(
byte
[]
source
,
int
offset
,
int
length
)
throws
IOException
{
ByteBuffer
byteBuffer
=
ByteBuffer
.
wrap
(
source
,
offset
,
length
).
asReadOnlyBuffer
();
return
explore
(
byteBuffer
);
}
/*
* uint8 V2CipherSpec[3];
* struct {
* uint16 msg_length; // The highest bit MUST be 1;
* // the remaining bits contain the length
* // of the following data in bytes.
* uint8 msg_type; // MUST be 1
* Version version;
* uint16 cipher_spec_length; // It cannot be zero and MUST be a
* // multiple of the V2CipherSpec length.
* uint16 session_id_length; // This field MUST be empty.
* uint16 challenge_length; // SHOULD use a 32-byte challenge
* V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];
* opaque session_id[V2ClientHello.session_id_length];
* opaque challenge[V2ClientHello.challenge_length;
* } V2ClientHello;
*/
private
static
SSLCapabilities
exploreV2HelloRecord
(
ByteBuffer
input
,
byte
firstByte
,
byte
secondByte
,
byte
thirdByte
)
throws
IOException
{
// We only need the header. We have already had enough source bytes.
// int recordLength = (firstByte & 0x7F) << 8) | (secondByte & 0xFF);
try
{
// Is it a V2ClientHello?
if
(
thirdByte
!=
0x01
)
{
throw
new
SSLException
(
"Unsupported or Unrecognized SSL record"
);
}
// What's the hello version?
byte
helloVersionMajor
=
input
.
get
();
byte
helloVersionMinor
=
input
.
get
();
// 0x00: major version of SSLv20
// 0x02: minor version of SSLv20
//
// SNIServerName is an extension, SSLv20 doesn't support extension.
return
new
SSLCapabilitiesImpl
((
byte
)
0x00
,
(
byte
)
0x02
,
helloVersionMajor
,
helloVersionMinor
,
Collections
.<
SNIServerName
>
emptyList
());
}
catch
(
BufferUnderflowException
bufe
)
{
throw
new
SSLProtocolException
(
"Invalid handshake record"
);
}
}
/*
* struct {
* uint8 major;
* uint8 minor;
* } ProtocolVersion;
*
* enum {
* change_cipher_spec(20), alert(21), handshake(22),
* application_data(23), (255)
* } ContentType;
*
* struct {
* ContentType type;
* ProtocolVersion version;
* uint16 length;
* opaque fragment[TLSPlaintext.length];
* } TLSPlaintext;
*/
private
static
SSLCapabilities
exploreTLSRecord
(
ByteBuffer
input
,
byte
firstByte
,
byte
secondByte
,
byte
thirdByte
)
throws
IOException
{
// Is it a handshake message?
if
(
firstByte
!=
22
)
{
// 22: handshake record
throw
new
SSLException
(
"Not handshake record"
);
}
// We need the record version to construct SSLCapabilities.
byte
recordMajorVersion
=
secondByte
;
byte
recordMinorVersion
=
thirdByte
;
// Is there enough data for a full record?
int
recordLength
=
getInt16
(
input
);
if
(
recordLength
>
input
.
remaining
())
{
throw
new
BufferUnderflowException
();
}
// We have already had enough source bytes.
try
{
return
exploreHandshake
(
input
,
recordMajorVersion
,
recordMinorVersion
,
recordLength
);
}
catch
(
BufferUnderflowException
bufe
)
{
throw
new
SSLProtocolException
(
"Invalid handshake record"
);
}
}
/*
* enum {
* hello_request(0), client_hello(1), server_hello(2),
* certificate(11), server_key_exchange (12),
* certificate_request(13), server_hello_done(14),
* certificate_verify(15), client_key_exchange(16),
* finished(20)
* (255)
* } HandshakeType;
*
* struct {
* HandshakeType msg_type;
* uint24 length;
* select (HandshakeType) {
* case hello_request: HelloRequest;
* case client_hello: ClientHello;
* case server_hello: ServerHello;
* case certificate: Certificate;
* case server_key_exchange: ServerKeyExchange;
* case certificate_request: CertificateRequest;
* case server_hello_done: ServerHelloDone;
* case certificate_verify: CertificateVerify;
* case client_key_exchange: ClientKeyExchange;
* case finished: Finished;
* } body;
* } Handshake;
*/
private
static
SSLCapabilities
exploreHandshake
(
ByteBuffer
input
,
byte
recordMajorVersion
,
byte
recordMinorVersion
,
int
recordLength
)
throws
IOException
{
// What is the handshake type?
byte
handshakeType
=
input
.
get
();
if
(
handshakeType
!=
0x01
)
{
// 0x01: client_hello message
throw
new
IllegalStateException
(
"Not initial handshaking"
);
}
// What is the handshake body length?
int
handshakeLength
=
getInt24
(
input
);
// Theoretically, a single handshake message might span multiple
// records, but in practice this does not occur.
if
(
handshakeLength
>
(
recordLength
-
4
))
{
// 4: handshake header size
throw
new
SSLException
(
"Handshake message spans multiple records"
);
}
input
=
input
.
duplicate
();
input
.
limit
(
handshakeLength
+
input
.
position
());
return
exploreClientHello
(
input
,
recordMajorVersion
,
recordMinorVersion
);
}
/*
* struct {
* uint32 gmt_unix_time;
* opaque random_bytes[28];
* } Random;
*
* opaque SessionID<0..32>;
*
* uint8 CipherSuite[2];
*
* enum { null(0), (255) } CompressionMethod;
*
* struct {
* ProtocolVersion client_version;
* Random random;
* SessionID session_id;
* CipherSuite cipher_suites<2..2^16-2>;
* CompressionMethod compression_methods<1..2^8-1>;
* select (extensions_present) {
* case false:
* struct {};
* case true:
* Extension extensions<0..2^16-1>;
* };
* } ClientHello;
*/
private
static
SSLCapabilities
exploreClientHello
(
ByteBuffer
input
,
byte
recordMajorVersion
,
byte
recordMinorVersion
)
throws
IOException
{
List
<
SNIServerName
>
snList
=
Collections
.<
SNIServerName
>
emptyList
();
// client version
byte
helloMajorVersion
=
input
.
get
();
byte
helloMinorVersion
=
input
.
get
();
// ignore random
int
position
=
input
.
position
();
input
.
position
(
position
+
32
);
// 32: the length of Random
// ignore session id
ignoreByteVector8
(
input
);
// ignore cipher_suites
ignoreByteVector16
(
input
);
// ignore compression methods
ignoreByteVector8
(
input
);
if
(
input
.
remaining
()
>
0
)
{
snList
=
exploreExtensions
(
input
);
}
return
new
SSLCapabilitiesImpl
(
recordMajorVersion
,
recordMinorVersion
,
helloMajorVersion
,
helloMinorVersion
,
snList
);
}
/*
* struct {
* ExtensionType extension_type;
* opaque extension_data<0..2^16-1>;
* } Extension;
*
* enum {
* server_name(0), max_fragment_length(1),
* client_certificate_url(2), trusted_ca_keys(3),
* truncated_hmac(4), status_request(5), (65535)
* } ExtensionType;
*/
private
static
List
<
SNIServerName
>
exploreExtensions
(
ByteBuffer
input
)
throws
IOException
{
int
length
=
getInt16
(
input
);
// length of extensions
while
(
length
>
0
)
{
int
extType
=
getInt16
(
input
);
// extenson type
int
extLen
=
getInt16
(
input
);
// length of extension data
if
(
extType
==
0x00
)
{
// 0x00: type of server name indication
return
exploreSNIExt
(
input
,
extLen
);
}
else
{
// ignore other extensions
ignoreByteVector
(
input
,
extLen
);
}
length
-=
extLen
+
4
;
}
return
Collections
.<
SNIServerName
>
emptyList
();
}
/*
* struct {
* NameType name_type;
* select (name_type) {
* case host_name: HostName;
* } name;
* } ServerName;
*
* enum {
* host_name(0), (255)
* } NameType;
*
* opaque HostName<1..2^16-1>;
*
* struct {
* ServerName server_name_list<1..2^16-1>
* } ServerNameList;
*/
private
static
List
<
SNIServerName
>
exploreSNIExt
(
ByteBuffer
input
,
int
extLen
)
throws
IOException
{
Map
<
Integer
,
SNIServerName
>
sniMap
=
new
LinkedHashMap
<>();
int
remains
=
extLen
;
if
(
extLen
>=
2
)
{
// "server_name" extension in ClientHello
int
listLen
=
getInt16
(
input
);
// length of server_name_list
if
(
listLen
==
0
||
listLen
+
2
!=
extLen
)
{
throw
new
SSLProtocolException
(
"Invalid server name indication extension"
);
}
remains
-=
2
;
// 0x02: the length field of server_name_list
while
(
remains
>
0
)
{
int
code
=
getInt8
(
input
);
// name_type
int
snLen
=
getInt16
(
input
);
// length field of server name
if
(
snLen
>
remains
)
{
throw
new
SSLProtocolException
(
"Not enough data to fill declared vector size"
);
}
byte
[]
encoded
=
new
byte
[
snLen
];
input
.
get
(
encoded
);
SNIServerName
serverName
;
switch
(
code
)
{
case
StandardConstants
.
SNI_HOST_NAME
:
if
(
encoded
.
length
==
0
)
{
throw
new
SSLProtocolException
(
"Empty HostName in server name indication"
);
}
serverName
=
new
SNIHostName
(
encoded
);
break
;
default
:
serverName
=
new
UnknownServerName
(
code
,
encoded
);
}
// check for duplicated server name type
if
(
sniMap
.
put
(
serverName
.
getType
(),
serverName
)
!=
null
)
{
throw
new
SSLProtocolException
(
"Duplicated server name of type "
+
serverName
.
getType
());
}
remains
-=
encoded
.
length
+
3
;
// NameType: 1 byte
// HostName length: 2 bytes
}
}
else
if
(
extLen
==
0
)
{
// "server_name" extension in ServerHello
throw
new
SSLProtocolException
(
"Not server name indication extension in client"
);
}
if
(
remains
!=
0
)
{
throw
new
SSLProtocolException
(
"Invalid server name indication extension"
);
}
return
Collections
.<
SNIServerName
>
unmodifiableList
(
new
ArrayList
<>(
sniMap
.
values
()));
}
private
static
int
getInt8
(
ByteBuffer
input
)
{
return
input
.
get
();
}
private
static
int
getInt16
(
ByteBuffer
input
)
{
return
((
input
.
get
()
&
0xFF
)
<<
8
)
|
(
input
.
get
()
&
0xFF
);
}
private
static
int
getInt24
(
ByteBuffer
input
)
{
return
((
input
.
get
()
&
0xFF
)
<<
16
)
|
((
input
.
get
()
&
0xFF
)
<<
8
)
|
(
input
.
get
()
&
0xFF
);
}
private
static
void
ignoreByteVector8
(
ByteBuffer
input
)
{
ignoreByteVector
(
input
,
getInt8
(
input
));
}
private
static
void
ignoreByteVector16
(
ByteBuffer
input
)
{
ignoreByteVector
(
input
,
getInt16
(
input
));
}
private
static
void
ignoreByteVector24
(
ByteBuffer
input
)
{
ignoreByteVector
(
input
,
getInt24
(
input
));
}
private
static
void
ignoreByteVector
(
ByteBuffer
input
,
int
length
)
{
if
(
length
!=
0
)
{
int
position
=
input
.
position
();
input
.
position
(
position
+
length
);
}
}
private
static
class
UnknownServerName
extends
SNIServerName
{
UnknownServerName
(
int
code
,
byte
[]
encoded
)
{
super
(
code
,
encoded
);
}
}
private
static
final
class
SSLCapabilitiesImpl
extends
SSLCapabilities
{
private
final
static
Map
<
Integer
,
String
>
versionMap
=
new
HashMap
<>(
5
);
private
final
String
recordVersion
;
private
final
String
helloVersion
;
List
<
SNIServerName
>
sniNames
;
static
{
versionMap
.
put
(
0x0002
,
"SSLv2Hello"
);
versionMap
.
put
(
0x0300
,
"SSLv3"
);
versionMap
.
put
(
0x0301
,
"TLSv1"
);
versionMap
.
put
(
0x0302
,
"TLSv1.1"
);
versionMap
.
put
(
0x0303
,
"TLSv1.2"
);
}
SSLCapabilitiesImpl
(
byte
recordMajorVersion
,
byte
recordMinorVersion
,
byte
helloMajorVersion
,
byte
helloMinorVersion
,
List
<
SNIServerName
>
sniNames
)
{
int
version
=
(
recordMajorVersion
<<
8
)
|
recordMinorVersion
;
this
.
recordVersion
=
versionMap
.
get
(
version
)
!=
null
?
versionMap
.
get
(
version
)
:
unknownVersion
(
recordMajorVersion
,
recordMinorVersion
);
version
=
(
helloMajorVersion
<<
8
)
|
helloMinorVersion
;
this
.
helloVersion
=
versionMap
.
get
(
version
)
!=
null
?
versionMap
.
get
(
version
)
:
unknownVersion
(
helloMajorVersion
,
helloMinorVersion
);
this
.
sniNames
=
sniNames
;
}
@Override
public
String
getRecordVersion
()
{
return
recordVersion
;
}
@Override
public
String
getHelloVersion
()
{
return
helloVersion
;
}
@Override
public
List
<
SNIServerName
>
getServerNames
()
{
if
(!
sniNames
.
isEmpty
())
{
return
Collections
.<
SNIServerName
>
unmodifiableList
(
sniNames
);
}
return
sniNames
;
}
private
static
String
unknownVersion
(
byte
major
,
byte
minor
)
{
return
"Unknown-"
+
((
int
)
major
)
+
"."
+
((
int
)
minor
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录