Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
e4266aa0
提交
e4266aa0
authored
3月 01, 2016
作者:
Noel Grandin
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'fix-anon-ssl' of
https://github.com/tomasp8/h2database
into tomasp8-fix-anon-ssl
上级
c4009062
d4dcb65f
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
463 行增加
和
134 行删除
+463
-134
changelog.html
h2/src/docsrc/html/changelog.html
+2
-0
CipherFactory.java
h2/src/main/org/h2/security/CipherFactory.java
+120
-5
NetUtils.java
h2/src/main/org/h2/util/NetUtils.java
+6
-1
TestNetUtils.java
h2/src/test/org/h2/test/unit/TestNetUtils.java
+133
-2
TestSecurity.java
h2/src/test/org/h2/test/unit/TestSecurity.java
+42
-0
TestTools.java
h2/src/test/org/h2/test/unit/TestTools.java
+160
-126
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
e4266aa0
...
...
@@ -21,6 +21,8 @@ Change Log
<h2>
Next Version (unreleased)
</h2>
<ul>
<li>
Issue #235: Anonymous SSL connections fail in many situations
</li>
<li>
Fix race condition in FILE_LOCK=SOCKET, which could result in the watchdog thread not running
</li>
<li>
Experimental support for datatype TIMESTAMP WITH TIMEZONE
...
...
h2/src/main/org/h2/security/CipherFactory.java
浏览文件 @
e4266aa0
...
...
@@ -17,13 +17,18 @@ import java.net.Socket;
import
java.security.KeyFactory
;
import
java.security.KeyStore
;
import
java.security.PrivateKey
;
import
java.security.Security
;
import
java.security.cert.Certificate
;
import
java.security.cert.CertificateFactory
;
import
java.security.spec.PKCS8EncodedKeySpec
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.LinkedHashSet
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Properties
;
import
javax.net.ServerSocketFactory
;
import
javax.net.ssl.SSLServerSocket
;
import
javax.net.ssl.SSLServerSocketFactory
;
...
...
@@ -47,6 +52,18 @@ public class CipherFactory {
*/
public
static
final
String
KEYSTORE_PASSWORD
=
"h2pass"
;
/**
* The security property which can prevent anonymous TLS connections.
* Introduced into Java 6,7,8 in updates from July 2015.
*/
public
static
final
String
LEGACY_ALGORITHMS_SECURITY_KEY
=
"jdk.tls.legacyAlgorithms"
;
/**
* The value of {@value #LEGACY_ALGORITHMS_SECURITY_KEY} security
* property at the time of class initialization.
* Null if it is not set.
*/
public
static
final
String
DEFAULT_LEGACY_ALGORITHMS
=
getLegacyAlgoritmsSilently
();
private
static
final
String
KEYSTORE
=
"~/.h2.keystore"
;
...
...
@@ -55,6 +72,7 @@ public class CipherFactory {
private
static
final
String
KEYSTORE_PASSWORD_KEY
=
"javax.net.ssl.keyStorePassword"
;
private
CipherFactory
()
{
// utility class
}
...
...
@@ -105,8 +123,13 @@ public class CipherFactory {
}
/**
* Create a secure server socket. If a bind address is specified, the socket
* is only bound to this address.
* Create a secure server socket. If a bind address is specified, the
* socket is only bound to this address.
* If h2.enableAnonymousTLS is true, an attempt is made to modify
* the security property jdk.tls.legacyAlgorithms (in newer JVMs) to allow
* anonymous TLS. This system change is effectively permanent for the
* lifetime of the JVM.
* @see #removeAnonFromLegacyAlgorithms()
*
* @param port the port to listen on
* @param bindAddress the address to bind to, or null to bind to all
...
...
@@ -116,6 +139,9 @@ public class CipherFactory {
public
static
ServerSocket
createServerSocket
(
int
port
,
InetAddress
bindAddress
)
throws
IOException
{
ServerSocket
socket
=
null
;
if
(
SysProperties
.
ENABLE_ANONYMOUS_TLS
)
{
removeAnonFromLegacyAlgorithms
();
}
setKeystore
();
ServerSocketFactory
f
=
SSLServerSocketFactory
.
getDefault
();
SSLServerSocket
secureSocket
;
...
...
@@ -137,6 +163,95 @@ public class CipherFactory {
return
socket
;
}
/**
* Removes DH_anon and ECDH_anon from a comma separated list of ciphers.
* Only the first occurrence is removed.
* If there is nothing to remove, returns the reference to the argument.
* @param commaSepList a list of names separated by commas (and spaces)
* @return a new string without DH_anon and ECDH_anon items,
* or the original if none were found
*/
public
static
String
removeDhAnonFromCommaSepList
(
String
commaSepList
)
{
if
(
commaSepList
==
null
)
{
return
commaSepList
;
}
List
<
String
>
algos
=
new
LinkedList
<
String
>(
Arrays
.
asList
(
commaSepList
.
split
(
"\\s*,\\s*"
)));
boolean
dhAnonRemoved
=
algos
.
remove
(
"DH_anon"
);
boolean
ecdhAnonRemoved
=
algos
.
remove
(
"ECDH_anon"
);
if
(
dhAnonRemoved
||
ecdhAnonRemoved
)
{
String
algosStr
=
Arrays
.
toString
(
algos
.
toArray
(
new
String
[
algos
.
size
()]));
return
(
algos
.
size
()
>
0
)
?
algosStr
.
substring
(
1
,
algosStr
.
length
()
-
1
):
""
;
}
else
{
return
commaSepList
;
}
}
/**
* Attempts to weaken the security properties to allow anonymous TLS.
* New JREs would not choose an anonymous cipher suite in a TLS handshake
* if server-side security property
* {@value #LEGACY_ALGORITHMS_SECURITY_KEY}
* were not modified from the default value.
* <p>
* NOTE: In current (as of 2016) default implementations of JSSE which use
* this security property, the value is permanently cached inside the
* ServerHandshake class upon its first use.
* Therefore the modification accomplished by this method has to be done
* before the first use of a server SSL socket.
* Later changes to this property will not have any effect on server socket
* behavior.
*/
public
static
synchronized
void
removeAnonFromLegacyAlgorithms
()
{
String
legacyAlgosOrig
=
getLegacyAlgoritmsSilently
();
if
(
legacyAlgosOrig
==
null
)
{
return
;
}
String
legacyAlgosNew
=
removeDhAnonFromCommaSepList
(
legacyAlgosOrig
);
if
(!
legacyAlgosOrig
.
equals
(
legacyAlgosNew
))
{
setLegacyAlgorithmsSilently
(
legacyAlgosNew
);
}
}
/**
* Attempts to resets the security property to the default value.
* The default value of {@value #LEGACY_ALGORITHMS_SECURITY_KEY} was
* obtained at time of class initialization.
* <p>
* NOTE: Resetting the property might not have any effect on server
* socket behavior.
* @see #removeAnonFromLegacyAlgorithms()
*/
public
static
synchronized
void
resetDefaultLegacyAlgorithms
()
{
setLegacyAlgorithmsSilently
(
DEFAULT_LEGACY_ALGORITHMS
);
}
/**
* Returns the security property {@value #LEGACY_ALGORITHMS_SECURITY_KEY}.
* Ignores security exceptions.
* @return the value of the security property, or null if not set
* or not accessible
*/
public
static
String
getLegacyAlgoritmsSilently
()
{
String
defaultLegacyAlgorithms
=
null
;
try
{
defaultLegacyAlgorithms
=
Security
.
getProperty
(
LEGACY_ALGORITHMS_SECURITY_KEY
);
}
catch
(
SecurityException
e
)
{
// ignore
}
return
defaultLegacyAlgorithms
;
}
private
static
void
setLegacyAlgorithmsSilently
(
String
legacyAlgos
)
{
if
(
legacyAlgos
==
null
)
{
return
;
}
try
{
Security
.
setProperty
(
LEGACY_ALGORITHMS_SECURITY_KEY
,
legacyAlgos
);
}
catch
(
SecurityException
e
)
{
// ignore
}
}
private
static
byte
[]
getKeyStoreBytes
(
KeyStore
store
,
String
password
)
throws
IOException
{
ByteArrayOutputStream
bout
=
new
ByteArrayOutputStream
();
...
...
@@ -270,16 +385,16 @@ public class CipherFactory {
}
private
static
String
[]
enableAnonymous
(
String
[]
enabled
,
String
[]
supported
)
{
HashSet
<
String
>
set
=
new
HashSet
<
String
>();
Collections
.
addAll
(
set
,
enabled
);
LinkedHashSet
<
String
>
set
=
new
LinkedHashSet
<
String
>();
for
(
String
x
:
supported
)
{
if
(!
x
.
startsWith
(
"SSL"
)
&&
x
.
indexOf
(
"_anon_"
)
>=
0
&&
x
.
indexOf
(
"_AES_"
)
>=
0
&&
(
x
.
indexOf
(
"_AES_"
)
>=
0
||
x
.
indexOf
(
"_3DES_"
)
>=
0
)
&&
x
.
indexOf
(
"_SHA"
)
>=
0
)
{
set
.
add
(
x
);
}
}
Collections
.
addAll
(
set
,
enabled
);
return
set
.
toArray
(
new
String
[
0
]);
}
...
...
h2/src/main/org/h2/util/NetUtils.java
浏览文件 @
e4266aa0
...
...
@@ -146,7 +146,12 @@ public class NetUtils {
/**
* Create a server socket. The system property h2.bindAddress is used if
* set.
* set. If SSL is used and h2.enableAnonymousTLS is true, an attempt is
* made to modify the security property jdk.tls.legacyAlgorithms
* (in newer JVMs) to allow anonymous TLS.
* <p>
* This system change is effectively permanent for the lifetime of the JVM.
* @see CipherFactory#removeAnonFromLegacyAlgorithms()
*
* @param port the port to listen on
* @param ssl if SSL should be used
...
...
h2/src/test/org/h2/test/unit/TestNetUtils.java
浏览文件 @
e4266aa0
...
...
@@ -11,19 +11,30 @@ import java.net.Socket;
import
java.util.HashSet
;
import
java.util.Set
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.SSLServerSocket
;
import
javax.net.ssl.SSLSession
;
import
javax.net.ssl.SSLSocket
;
import
org.h2.engine.SysProperties
;
import
org.h2.test.TestBase
;
import
org.h2.util.NetUtils
;
import
org.h2.util.Task
;
/**
* Test the network utilities.
* Test the network utilities
from {@link NetUtils}
.
*
* @author Sergi Vladykin
* @author Tomas Pospichal
*/
public
class
TestNetUtils
extends
TestBase
{
private
static
final
int
WORKER_COUNT
=
10
;
private
static
final
int
PORT
=
9111
;
private
static
final
int
WAIT_MILLIS
=
100
;
private
static
final
int
WAIT_LONGER_MILLIS
=
2
*
WAIT_MILLIS
;
private
static
final
String
TASK_PREFIX
=
"ServerSocketThread-"
;
/**
* Run just this test.
...
...
@@ -36,10 +47,130 @@ public class TestNetUtils extends TestBase {
@Override
public
void
test
()
throws
Exception
{
testAnonymousTlsSession
();
testTlsSessionWithServerSideAnonymousDisabled
();
testFrequentConnections
(
true
,
100
);
testFrequentConnections
(
false
,
1000
);
}
/**
* With default settings, H2 client SSL socket should be able to connect
* to an H2 server SSL socket using an anonymous cipher suite
* (no SSL certificate is needed).
* @throws Exception
*/
private
void
testAnonymousTlsSession
()
throws
Exception
{
assertTrue
(
"Failed assumption: the default value of ENABLE_ANONYMOUS_TLS"
+
" property should be true"
,
SysProperties
.
ENABLE_ANONYMOUS_TLS
);
boolean
ssl
=
true
;
Task
task
=
null
;
ServerSocket
serverSocket
=
null
;
Socket
socket
=
null
;
try
{
serverSocket
=
NetUtils
.
createServerSocket
(
PORT
,
ssl
);
serverSocket
.
setSoTimeout
(
WAIT_LONGER_MILLIS
);
task
=
createServerSocketTask
(
serverSocket
);
task
.
execute
(
TASK_PREFIX
+
"AnonEnabled"
);
Thread
.
sleep
(
WAIT_MILLIS
);
socket
=
NetUtils
.
createLoopbackSocket
(
PORT
,
ssl
);
assertTrue
(
"loopback anon socket should be connected"
,
socket
.
isConnected
());
SSLSession
session
=
((
SSLSocket
)
socket
).
getSession
();
assertTrue
(
"TLS session should be valid when anonymous TLS is enabled"
,
session
.
isValid
());
// in case of handshake failure:
// the cipher suite is the pre-handshake SSL_NULL_WITH_NULL_NULL
assertContains
(
session
.
getCipherSuite
(),
"_anon_"
);
}
finally
{
closeSilently
(
socket
);
closeSilently
(
serverSocket
);
if
(
task
!=
null
)
{
// SSL server socket should succeed using an anonymous cipher
// suite, and not throw javax.net.ssl.SSLHandshakeException
assertNull
(
task
.
getException
());
task
.
join
();
}
}
}
/**
* TLS connections (without trusted certificates) should fail if the server
* does not allow anonymous TLS.
* The global property ENABLE_ANONYMOUS_TLS cannot be modified for the test;
* instead, the server socket is altered.
* @throws Exception
*/
private
void
testTlsSessionWithServerSideAnonymousDisabled
()
throws
Exception
{
boolean
ssl
=
true
;
Task
task
=
null
;
ServerSocket
serverSocket
=
null
;
Socket
socket
=
null
;
try
{
serverSocket
=
NetUtils
.
createServerSocket
(
PORT
,
ssl
);
serverSocket
.
setSoTimeout
(
WAIT_LONGER_MILLIS
);
// emulate the situation ENABLE_ANONYMOUS_TLS=false on server side
String
[]
defaultCipherSuites
=
SSLContext
.
getDefault
().
getServerSocketFactory
()
.
getDefaultCipherSuites
();
((
SSLServerSocket
)
serverSocket
).
setEnabledCipherSuites
(
defaultCipherSuites
);
task
=
createServerSocketTask
(
serverSocket
);
task
.
execute
(
TASK_PREFIX
+
"AnonDisabled"
);
Thread
.
sleep
(
WAIT_MILLIS
);
socket
=
NetUtils
.
createLoopbackSocket
(
PORT
,
ssl
);
assertTrue
(
"loopback socket should be connected"
,
socket
.
isConnected
());
// Java 6 API does not have getHandshakeSession() which could
// reveal the actual cipher selected in the attempted handshake
SSLSession
session
=
((
SSLSocket
)
socket
).
getSession
();
assertFalse
(
"TLS session should be invalid when the server"
+
"disables anonymous TLS"
,
session
.
isValid
());
// the SSL handshake should fail, because non-anon ciphers require
// a trusted certificate
assertEquals
(
"SSL_NULL_WITH_NULL_NULL"
,
session
.
getCipherSuite
());
}
finally
{
closeSilently
(
socket
);
closeSilently
(
serverSocket
);
if
(
task
!=
null
)
{
assertTrue
(
task
.
getException
()
!=
null
);
assertEquals
(
javax
.
net
.
ssl
.
SSLHandshakeException
.
class
.
getName
(),
task
.
getException
().
getClass
().
getName
());
assertContains
(
task
.
getException
().
getMessage
(),
"certificate_unknown"
);
task
.
join
();
}
}
}
private
Task
createServerSocketTask
(
final
ServerSocket
serverSocket
)
{
Task
task
=
new
Task
()
{
@Override
public
void
call
()
throws
Exception
{
Socket
ss
=
null
;
try
{
ss
=
serverSocket
.
accept
();
ss
.
getOutputStream
().
write
(
123
);
}
finally
{
closeSilently
(
ss
);
}
}
};
return
task
;
}
private
void
closeSilently
(
Socket
socket
)
{
try
{
socket
.
close
();
}
catch
(
Exception
e
)
{
// ignore
}
}
private
void
closeSilently
(
ServerSocket
socket
)
{
try
{
socket
.
close
();
}
catch
(
Exception
e
)
{
// ignore
}
}
private
void
testFrequentConnections
(
boolean
ssl
,
int
count
)
throws
Exception
{
final
ServerSocket
serverSocket
=
NetUtils
.
createServerSocket
(
PORT
,
ssl
);
final
AtomicInteger
counter
=
new
AtomicInteger
(
count
);
...
...
@@ -96,7 +227,7 @@ public class TestNetUtils extends TestBase {
private
final
AtomicInteger
counter
;
private
Exception
exception
;
public
ConnectWorker
(
boolean
ssl
,
AtomicInteger
counter
)
{
ConnectWorker
(
boolean
ssl
,
AtomicInteger
counter
)
{
this
.
ssl
=
ssl
;
this
.
counter
=
counter
;
}
...
...
h2/src/test/org/h2/test/unit/TestSecurity.java
浏览文件 @
e4266aa0
...
...
@@ -9,6 +9,7 @@ import java.sql.Connection;
import
java.sql.DriverManager
;
import
java.sql.SQLException
;
import
java.util.Arrays
;
import
org.h2.security.BlockCipher
;
import
org.h2.security.CipherFactory
;
import
org.h2.security.SHA256
;
...
...
@@ -35,6 +36,8 @@ public class TestSecurity extends TestBase {
testSHA
();
testAES
();
testBlockCiphers
();
testRemoveAnonFromLegacyAlgos
();
//testResetLegacyAlgos();
}
private
static
void
testConnectWithHash
()
throws
SQLException
{
...
...
@@ -251,4 +254,43 @@ public class TestSecurity extends TestBase {
return
len
*
r
<
len
*
120
;
}
private
void
testRemoveAnonFromLegacyAlgos
()
{
String
legacyAlgos
=
"K_NULL, C_NULL, M_NULL, DHE_DSS_EXPORT"
+
", DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, DH_RSA_EXPORT, RSA_EXPORT"
+
", DH_anon, ECDH_anon, RC4_128, RC4_40, DES_CBC, DES40_CBC"
;
String
expectedLegacyAlgosWithoutDhAnon
=
"K_NULL, C_NULL, M_NULL, DHE_DSS_EXPORT"
+
", DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, DH_RSA_EXPORT, RSA_EXPORT"
+
", RC4_128, RC4_40, DES_CBC, DES40_CBC"
;
assertEquals
(
expectedLegacyAlgosWithoutDhAnon
,
CipherFactory
.
removeDhAnonFromCommaSepList
(
legacyAlgos
));
legacyAlgos
=
"ECDH_anon, DH_anon_EXPORT, DH_anon"
;
expectedLegacyAlgosWithoutDhAnon
=
"DH_anon_EXPORT"
;
assertEquals
(
expectedLegacyAlgosWithoutDhAnon
,
CipherFactory
.
removeDhAnonFromCommaSepList
(
legacyAlgos
));
legacyAlgos
=
null
;
assertNull
(
CipherFactory
.
removeDhAnonFromCommaSepList
(
legacyAlgos
));
}
/**
* This test is meaningful when run in isolation. However, tests of server
* sockets or ssl connections may modify the global state given by the
* jdk.tls.legacyAlgorithms security property (for a good reason).
* It is best to avoid running it in test suites, as it could itself lead
* to a modification of the global state with hard-to-track consequences.
*/
@SuppressWarnings
(
"unused"
)
private
void
testResetLegacyAlgos
()
{
String
legacyAlgorithmsBefore
=
CipherFactory
.
getLegacyAlgoritmsSilently
();
assertEquals
(
"Failed assumption: jdk.tls.legacyAlgorithms"
+
" has been modified from its initial setting"
,
CipherFactory
.
DEFAULT_LEGACY_ALGORITHMS
,
legacyAlgorithmsBefore
);
CipherFactory
.
removeAnonFromLegacyAlgorithms
();
CipherFactory
.
resetDefaultLegacyAlgorithms
();
String
legacyAlgorithmsAfter
=
CipherFactory
.
getLegacyAlgoritmsSilently
();
assertEquals
(
CipherFactory
.
DEFAULT_LEGACY_ALGORITHMS
,
legacyAlgorithmsAfter
);
}
}
h2/src/test/org/h2/test/unit/TestTools.java
浏览文件 @
e4266aa0
...
...
@@ -33,6 +33,7 @@ import java.sql.Time;
import
java.sql.Timestamp
;
import
java.sql.Types
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Random
;
import
org.h2.api.ErrorCode
;
...
...
@@ -64,6 +65,7 @@ public class TestTools extends TestBase {
private
static
String
lastUrl
;
private
Server
server
;
private
List
<
Server
>
remainingServers
=
new
ArrayList
<
Server
>(
3
);
/**
* Run just this test.
...
...
@@ -171,7 +173,6 @@ public class TestTools extends TestBase {
assertThrows
(
ErrorCode
.
EXCEPTION_OPENING_PORT_2
,
c
).
runTool
(
"-web"
,
"-webPort"
,
"9002"
,
"-tcp"
,
"-tcpPort"
,
"9002"
);
c
.
runTool
(
"-web"
,
"-webPort"
,
"9002"
);
c
.
shutdown
();
}
finally
{
if
(
old
!=
null
)
{
...
...
@@ -179,6 +180,7 @@ public class TestTools extends TestBase {
}
else
{
System
.
clearProperty
(
SysProperties
.
H2_BROWSER
);
}
c
.
shutdown
();
}
}
...
...
@@ -486,16 +488,19 @@ public class TestTools extends TestBase {
}
}
};
task
.
execute
();
Thread
.
sleep
(
100
);
try
{
getConnection
(
"jdbc:h2:tcp://localhost:9001/test"
);
fail
();
}
catch
(
SQLException
e
)
{
assertEquals
(
ErrorCode
.
CONNECTION_BROKEN_1
,
e
.
getErrorCode
());
task
.
execute
();
Thread
.
sleep
(
100
);
try
{
getConnection
(
"jdbc:h2:tcp://localhost:9001/test"
);
fail
();
}
catch
(
SQLException
e
)
{
assertEquals
(
ErrorCode
.
CONNECTION_BROKEN_1
,
e
.
getErrorCode
());
}
}
finally
{
serverSocket
.
close
();
task
.
getException
();
}
serverSocket
.
close
();
task
.
getException
();
}
private
void
testDeleteFiles
()
throws
SQLException
{
...
...
@@ -527,73 +532,84 @@ public class TestTools extends TestBase {
String
result
;
Connection
conn
;
result
=
runServer
(
0
,
new
String
[]{
"-?"
});
assertTrue
(
result
.
contains
(
"Starts the H2 Console"
));
assertTrue
(
result
.
indexOf
(
"Unknown option"
)
<
0
);
result
=
runServer
(
1
,
new
String
[]{
"-xy"
});
assertTrue
(
result
.
contains
(
"Starts the H2 Console"
));
assertTrue
(
result
.
contains
(
"Feature not supported"
));
result
=
runServer
(
0
,
new
String
[]{
"-tcp"
,
"-tcpPort"
,
"9001"
,
"-tcpPassword"
,
"abc"
});
assertTrue
(
result
.
contains
(
"tcp://"
));
assertTrue
(
result
.
contains
(
":9001"
));
assertTrue
(
result
.
contains
(
"only local"
));
assertTrue
(
result
.
indexOf
(
"Starts the H2 Console"
)
<
0
);
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9001/mem:"
,
"sa"
,
"sa"
);
conn
.
close
();
result
=
runServer
(
0
,
new
String
[]{
"-tcpShutdown"
,
"tcp://localhost:9001"
,
"-tcpPassword"
,
"abc"
,
"-tcpShutdownForce"
});
assertTrue
(
result
.
contains
(
"Shutting down"
));
try
{
result
=
runServer
(
0
,
new
String
[]{
"-?"
});
assertTrue
(
result
.
contains
(
"Starts the H2 Console"
));
assertTrue
(
result
.
indexOf
(
"Unknown option"
)
<
0
);
result
=
runServer
(
1
,
new
String
[]{
"-xy"
});
assertTrue
(
result
.
contains
(
"Starts the H2 Console"
));
assertTrue
(
result
.
contains
(
"Feature not supported"
));
result
=
runServer
(
0
,
new
String
[]{
"-tcp"
,
"-tcpPort"
,
"9001"
,
"-tcpPassword"
,
"abc"
});
assertTrue
(
result
.
contains
(
"tcp://"
));
assertTrue
(
result
.
contains
(
":9001"
));
assertTrue
(
result
.
contains
(
"only local"
));
assertTrue
(
result
.
indexOf
(
"Starts the H2 Console"
)
<
0
);
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9001/mem:"
,
"sa"
,
"sa"
);
conn
.
close
();
result
=
runServer
(
0
,
new
String
[]{
"-tcpShutdown"
,
"tcp://localhost:9001"
,
"-tcpPassword"
,
"abc"
,
"-tcpShutdownForce"
});
assertTrue
(
result
.
contains
(
"Shutting down"
));
}
finally
{
shutdownServers
();
}
}
private
void
testSSL
()
throws
SQLException
{
String
result
;
Connection
conn
;
result
=
runServer
(
0
,
new
String
[]{
"-tcp"
,
"-tcpAllowOthers"
,
"-tcpPort"
,
"9001"
,
"-tcpPassword"
,
"abcdef"
,
"-tcpSSL"
});
assertTrue
(
result
.
contains
(
"ssl://"
));
assertTrue
(
result
.
contains
(
":9001"
));
assertTrue
(
result
.
contains
(
"others can"
));
assertTrue
(
result
.
indexOf
(
"Starts the H2 Console"
)
<
0
);
conn
=
getConnection
(
"jdbc:h2:ssl://localhost:9001/mem:"
,
"sa"
,
"sa"
);
conn
.
close
();
try
{
result
=
runServer
(
0
,
new
String
[]{
"-tcp"
,
"-tcpAllowOthers"
,
"-tcpPort"
,
"9001"
,
"-tcpPassword"
,
"abcdef"
,
"-tcpSSL"
});
assertTrue
(
result
.
contains
(
"ssl://"
));
assertTrue
(
result
.
contains
(
":9001"
));
assertTrue
(
result
.
contains
(
"others can"
));
assertTrue
(
result
.
indexOf
(
"Starts the H2 Console"
)
<
0
);
conn
=
getConnection
(
"jdbc:h2:ssl://localhost:9001/mem:"
,
"sa"
,
"sa"
);
conn
.
close
();
result
=
runServer
(
0
,
new
String
[]{
"-tcpShutdown"
,
"ssl://localhost:9001"
,
"-tcpPassword"
,
"abcdef"
});
assertTrue
(
result
.
contains
(
"Shutting down"
));
assertThrows
(
ErrorCode
.
CONNECTION_BROKEN_1
,
this
).
getConnection
(
"jdbc:h2:ssl://localhost:9001/mem:"
,
"sa"
,
"sa"
);
result
=
runServer
(
0
,
new
String
[]{
"-web"
,
"-webPort"
,
"9002"
,
"-webAllowOthers"
,
"-webSSL"
,
"-pg"
,
"-pgAllowOthers"
,
"-pgPort"
,
"9003"
,
"-tcp"
,
"-tcpAllowOthers"
,
"-tcpPort"
,
"9006"
,
"-tcpPassword"
,
"abc"
});
Server
stop
=
server
;
assertTrue
(
result
.
contains
(
"https://"
));
assertTrue
(
result
.
contains
(
":9002"
));
assertTrue
(
result
.
contains
(
"pg://"
));
assertTrue
(
result
.
contains
(
":9003"
));
assertTrue
(
result
.
contains
(
"others can"
));
assertTrue
(
result
.
indexOf
(
"only local"
)
<
0
);
assertTrue
(
result
.
contains
(
"tcp://"
));
assertTrue
(
result
.
contains
(
":9006"
));
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9006/mem:"
,
"sa"
,
"sa"
);
conn
.
close
();
result
=
runServer
(
0
,
new
String
[]{
"-tcpShutdown"
,
"ssl://localhost:9001"
,
"-tcpPassword"
,
"abcdef"
});
assertTrue
(
result
.
contains
(
"Shutting down"
));
assertThrows
(
ErrorCode
.
CONNECTION_BROKEN_1
,
this
).
getConnection
(
"jdbc:h2:ssl://localhost:9001/mem:"
,
"sa"
,
"sa"
);
result
=
runServer
(
0
,
new
String
[]{
"-web"
,
"-webPort"
,
"9002"
,
"-webAllowOthers"
,
"-webSSL"
,
"-pg"
,
"-pgAllowOthers"
,
"-pgPort"
,
"9003"
,
"-tcp"
,
"-tcpAllowOthers"
,
"-tcpPort"
,
"9006"
,
"-tcpPassword"
,
"abc"
});
Server
stop
=
server
;
assertTrue
(
result
.
contains
(
"https://"
));
assertTrue
(
result
.
contains
(
":9002"
));
assertTrue
(
result
.
contains
(
"pg://"
));
assertTrue
(
result
.
contains
(
":9003"
));
assertTrue
(
result
.
contains
(
"others can"
));
assertTrue
(
result
.
indexOf
(
"only local"
)
<
0
);
assertTrue
(
result
.
contains
(
"tcp://"
));
assertTrue
(
result
.
contains
(
":9006"
));
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9006/mem:"
,
"sa"
,
"sa"
);
conn
.
close
();
result
=
runServer
(
0
,
new
String
[]{
"-tcpShutdown"
,
"tcp://localhost:9006"
,
"-tcpPassword"
,
"abc"
,
"-tcpShutdownForce"
});
assertTrue
(
result
.
contains
(
"Shutting down"
));
stop
.
shutdown
();
assertThrows
(
ErrorCode
.
CONNECTION_BROKEN_1
,
this
).
getConnection
(
"jdbc:h2:tcp://localhost:9006/mem:"
,
"sa"
,
"sa"
);
result
=
runServer
(
0
,
new
String
[]{
"-tcpShutdown"
,
"tcp://localhost:9006"
,
"-tcpPassword"
,
"abc"
,
"-tcpShutdownForce"
});
assertTrue
(
result
.
contains
(
"Shutting down"
));
stop
.
shutdown
();
assertThrows
(
ErrorCode
.
CONNECTION_BROKEN_1
,
this
).
getConnection
(
"jdbc:h2:tcp://localhost:9006/mem:"
,
"sa"
,
"sa"
);
}
finally
{
shutdownServers
();
}
}
private
String
runServer
(
int
exitCode
,
String
...
args
)
{
ByteArrayOutputStream
buff
=
new
ByteArrayOutputStream
();
PrintStream
ps
=
new
PrintStream
(
buff
);
if
(
server
!=
null
)
{
remainingServers
.
add
(
server
);
}
server
=
new
Server
();
server
.
setOut
(
ps
);
int
result
=
0
;
...
...
@@ -609,6 +625,18 @@ public class TestTools extends TestBase {
return
s
;
}
private
void
shutdownServers
()
{
for
(
Server
remainingServer
:
remainingServers
)
{
if
(
remainingServer
!=
null
)
{
remainingServer
.
shutdown
();
}
}
remainingServers
.
clear
();
if
(
server
!=
null
)
{
server
.
shutdown
();
}
}
private
void
testConvertTraceFile
()
throws
Exception
{
deleteDb
(
"toolsConvertTraceFile"
);
org
.
h2
.
Driver
.
load
();
...
...
@@ -1018,71 +1046,77 @@ public class TestTools extends TestBase {
private
void
testServer
()
throws
SQLException
{
Connection
conn
;
deleteDb
(
"test"
);
Server
tcpServer
=
Server
.
createTcpServer
(
"-baseDir"
,
getBaseDir
(),
"-tcpPort"
,
"9192"
,
"-tcpAllowOthers"
).
start
();
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9192/test"
,
"sa"
,
""
);
conn
.
close
();
// must not be able to use a different base dir
new
AssertThrows
(
ErrorCode
.
IO_EXCEPTION_1
)
{
@Override
public
void
test
()
throws
SQLException
{
getConnection
(
"jdbc:h2:tcp://localhost:9192/../test"
,
"sa"
,
""
);
}};
new
AssertThrows
(
ErrorCode
.
IO_EXCEPTION_1
)
{
@Override
public
void
test
()
throws
SQLException
{
getConnection
(
"jdbc:h2:tcp://localhost:9192/../test2/test"
,
"sa"
,
""
);
}};
tcpServer
.
stop
();
Server
.
createTcpServer
(
"-ifExists"
,
"-tcpPassword"
,
"abc"
,
"-baseDir"
,
getBaseDir
(),
"-tcpPort"
,
"9192"
).
start
();
// must not be able to create new db
new
AssertThrows
(
ErrorCode
.
DATABASE_NOT_FOUND_1
)
{
@Override
public
void
test
()
throws
SQLException
{
getConnection
(
"jdbc:h2:tcp://localhost:9192/test2"
,
"sa"
,
""
);
}};
new
AssertThrows
(
ErrorCode
.
DATABASE_NOT_FOUND_1
)
{
@Override
public
void
test
()
throws
SQLException
{
getConnection
(
"jdbc:h2:tcp://localhost:9192/test2;ifexists=false"
,
"sa"
,
""
);
}};
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9192/test"
,
"sa"
,
""
);
conn
.
close
();
new
AssertThrows
(
ErrorCode
.
WRONG_USER_OR_PASSWORD
)
{
@Override
public
void
test
()
throws
SQLException
{
Server
.
shutdownTcpServer
(
"tcp://localhost:9192"
,
""
,
true
,
false
);
}};
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9192/test"
,
"sa"
,
""
);
// conn.close();
Server
.
shutdownTcpServer
(
"tcp://localhost:9192"
,
"abc"
,
true
,
false
);
// check that the database is closed
deleteDb
(
"test"
);
// server must have been closed
assertThrows
(
ErrorCode
.
CONNECTION_BROKEN_1
,
this
).
getConnection
(
"jdbc:h2:tcp://localhost:9192/test"
,
"sa"
,
""
);
JdbcUtils
.
closeSilently
(
conn
);
// Test filesystem prefix and escape from baseDir
deleteDb
(
"testSplit"
);
server
=
Server
.
createTcpServer
(
"-baseDir"
,
getBaseDir
(),
"-tcpPort"
,
"9192"
,
"-tcpAllowOthers"
).
start
();
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9192/split:testSplit"
,
"sa"
,
""
);
conn
.
close
();
try
{
deleteDb
(
"test"
);
Server
tcpServer
=
Server
.
createTcpServer
(
"-baseDir"
,
getBaseDir
(),
"-tcpPort"
,
"9192"
,
"-tcpAllowOthers"
).
start
();
remainingServers
.
add
(
tcpServer
);
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9192/test"
,
"sa"
,
""
);
conn
.
close
();
// must not be able to use a different base dir
new
AssertThrows
(
ErrorCode
.
IO_EXCEPTION_1
)
{
@Override
public
void
test
()
throws
SQLException
{
getConnection
(
"jdbc:h2:tcp://localhost:9192/../test"
,
"sa"
,
""
);
}};
new
AssertThrows
(
ErrorCode
.
IO_EXCEPTION_1
)
{
@Override
public
void
test
()
throws
SQLException
{
getConnection
(
"jdbc:h2:tcp://localhost:9192/../test2/test"
,
"sa"
,
""
);
}};
tcpServer
.
stop
();
Server
tcpServerWithPassword
=
Server
.
createTcpServer
(
"-ifExists"
,
"-tcpPassword"
,
"abc"
,
"-baseDir"
,
getBaseDir
(),
"-tcpPort"
,
"9192"
).
start
();
remainingServers
.
add
(
tcpServerWithPassword
);
// must not be able to create new db
new
AssertThrows
(
ErrorCode
.
DATABASE_NOT_FOUND_1
)
{
@Override
public
void
test
()
throws
SQLException
{
getConnection
(
"jdbc:h2:tcp://localhost:9192/test2"
,
"sa"
,
""
);
}};
new
AssertThrows
(
ErrorCode
.
DATABASE_NOT_FOUND_1
)
{
@Override
public
void
test
()
throws
SQLException
{
getConnection
(
"jdbc:h2:tcp://localhost:9192/test2;ifexists=false"
,
"sa"
,
""
);
}};
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9192/test"
,
"sa"
,
""
);
conn
.
close
();
new
AssertThrows
(
ErrorCode
.
WRONG_USER_OR_PASSWORD
)
{
@Override
public
void
test
()
throws
SQLException
{
Server
.
shutdownTcpServer
(
"tcp://localhost:9192"
,
""
,
true
,
false
);
}};
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9192/test"
,
"sa"
,
""
);
// conn.close();
Server
.
shutdownTcpServer
(
"tcp://localhost:9192"
,
"abc"
,
true
,
false
);
// check that the database is closed
deleteDb
(
"test"
);
// server must have been closed
assertThrows
(
ErrorCode
.
CONNECTION_BROKEN_1
,
this
).
getConnection
(
"jdbc:h2:tcp://localhost:9192/test"
,
"sa"
,
""
);
JdbcUtils
.
closeSilently
(
conn
);
// Test filesystem prefix and escape from baseDir
deleteDb
(
"testSplit"
);
server
=
Server
.
createTcpServer
(
"-baseDir"
,
getBaseDir
(),
"-tcpPort"
,
"9192"
,
"-tcpAllowOthers"
).
start
();
conn
=
getConnection
(
"jdbc:h2:tcp://localhost:9192/split:testSplit"
,
"sa"
,
""
);
conn
.
close
();
assertThrows
(
ErrorCode
.
IO_EXCEPTION_1
,
this
).
getConnection
(
"jdbc:h2:tcp://localhost:9192/../test"
,
"sa"
,
""
);
assertThrows
(
ErrorCode
.
IO_EXCEPTION_1
,
this
).
getConnection
(
"jdbc:h2:tcp://localhost:9192/../test"
,
"sa"
,
""
);
server
.
stop
();
deleteDb
(
"testSplit"
);
server
.
stop
();
deleteDb
(
"testSplit"
);
}
finally
{
shutdownServers
();
}
}
/**
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论