Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
1c14b0a7
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看板
提交
1c14b0a7
编写于
6月 21, 2013
作者:
W
weijun
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8001326: Improve Kerberos caching
Reviewed-by: valeriep
上级
11d0f16c
变更
21
隐藏空白更改
内联
并排
Showing
21 changed file
with
2004 addition
and
149 deletion
+2004
-149
src/share/classes/sun/security/jgss/krb5/AcceptSecContextToken.java
...classes/sun/security/jgss/krb5/AcceptSecContextToken.java
+12
-15
src/share/classes/sun/security/krb5/EncryptionKey.java
src/share/classes/sun/security/krb5/EncryptionKey.java
+4
-2
src/share/classes/sun/security/krb5/KrbApRep.java
src/share/classes/sun/security/krb5/KrbApRep.java
+3
-5
src/share/classes/sun/security/krb5/KrbApReq.java
src/share/classes/sun/security/krb5/KrbApReq.java
+32
-14
src/share/classes/sun/security/krb5/internal/ReplayCache.java
...share/classes/sun/security/krb5/internal/ReplayCache.java
+72
-0
src/share/classes/sun/security/krb5/internal/rcache/AuthList.java
...e/classes/sun/security/krb5/internal/rcache/AuthList.java
+144
-0
src/share/classes/sun/security/krb5/internal/rcache/AuthTime.java
...e/classes/sun/security/krb5/internal/rcache/AuthTime.java
+102
-29
src/share/classes/sun/security/krb5/internal/rcache/AuthTimeWithHash.java
...s/sun/security/krb5/internal/rcache/AuthTimeWithHash.java
+124
-0
src/share/classes/sun/security/krb5/internal/rcache/DflCache.java
...e/classes/sun/security/krb5/internal/rcache/DflCache.java
+365
-0
src/share/classes/sun/security/krb5/internal/rcache/MemoryCache.java
...lasses/sun/security/krb5/internal/rcache/MemoryCache.java
+32
-38
test/java/security/testlibrary/Proc.java
test/java/security/testlibrary/Proc.java
+325
-0
test/sun/security/krb5/auto/AcceptorSubKey.java
test/sun/security/krb5/auto/AcceptorSubKey.java
+10
-4
test/sun/security/krb5/auto/BasicProc.java
test/sun/security/krb5/auto/BasicProc.java
+192
-0
test/sun/security/krb5/auto/Context.java
test/sun/security/krb5/auto/Context.java
+5
-3
test/sun/security/krb5/auto/KDC.java
test/sun/security/krb5/auto/KDC.java
+1
-1
test/sun/security/krb5/auto/NoneReplayCacheTest.java
test/sun/security/krb5/auto/NoneReplayCacheTest.java
+70
-0
test/sun/security/krb5/auto/ReplayCacheExpunge.java
test/sun/security/krb5/auto/ReplayCacheExpunge.java
+79
-0
test/sun/security/krb5/auto/ReplayCachePrecise.java
test/sun/security/krb5/auto/ReplayCachePrecise.java
+84
-0
test/sun/security/krb5/auto/ReplayCacheTest.java
test/sun/security/krb5/auto/ReplayCacheTest.java
+17
-8
test/sun/security/krb5/auto/ReplayCacheTestProc.java
test/sun/security/krb5/auto/ReplayCacheTestProc.java
+327
-0
test/sun/security/krb5/ccache/EmptyCC.java
test/sun/security/krb5/ccache/EmptyCC.java
+4
-30
未找到文件。
src/share/classes/sun/security/jgss/krb5/AcceptSecContextToken.java
浏览文件 @
1c14b0a7
...
...
@@ -27,9 +27,10 @@ package sun.security.jgss.krb5;
import
org.ietf.jgss.*
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.io.IOException
;
import
java.io.ByteArrayInputStream
;
import
java.security.AccessController
;
import
sun.security.action.GetBooleanAction
;
import
sun.security.krb5.*
;
class
AcceptSecContextToken
extends
InitialToken
{
...
...
@@ -42,23 +43,19 @@ class AcceptSecContextToken extends InitialToken {
*/
public
AcceptSecContextToken
(
Krb5Context
context
,
KrbApReq
apReq
)
throws
KrbException
,
IOException
{
throws
KrbException
,
IOException
,
GSSException
{
/*
* RFC 1964, section 1.2 states:
* (1) context key: uses Kerberos session key (or subkey, if
* present in authenticator emitted by context initiator) directly
*
* This does not mention context acceptor. Hence we will not
* generate a subkey on the acceptor side. Note: Our initiator will
* still allow another acceptor to generate a subkey, even though
* our acceptor does not do so.
*/
boolean
useSubkey
=
false
;
boolean
useSubkey
=
AccessController
.
doPrivileged
(
new
GetBooleanAction
(
"sun.security.krb5.acceptor.subkey"
));
boolean
useSequenceNumber
=
true
;
apRep
=
new
KrbApRep
(
apReq
,
useSequenceNumber
,
useSubkey
);
EncryptionKey
subKey
=
null
;
if
(
useSubkey
)
{
subKey
=
new
EncryptionKey
(
apReq
.
getCreds
().
getSessionKey
());
context
.
setKey
(
Krb5Context
.
ACCEPTOR_SUBKEY
,
subKey
);
}
apRep
=
new
KrbApRep
(
apReq
,
useSequenceNumber
,
subKey
);
context
.
resetMySequenceNumber
(
apRep
.
getSeqNumber
().
intValue
());
...
...
src/share/classes/sun/security/krb5/EncryptionKey.java
浏览文件 @
1c14b0a7
...
...
@@ -297,9 +297,11 @@ public class EncryptionKey
/**
* Generates a sub-sessionkey from a given session key.
*
* Used in AcceptSecContextToken and KrbApReq by acceptor- and initiator-
* side respectively.
*/
// Used in KrbApRep, KrbApReq
EncryptionKey
(
EncryptionKey
key
)
throws
KrbCryptoException
{
public
EncryptionKey
(
EncryptionKey
key
)
throws
KrbCryptoException
{
// generate random sub-session key
keyValue
=
Confounder
.
bytes
(
key
.
keyValue
.
length
);
for
(
int
i
=
0
;
i
<
keyValue
.
length
;
i
++)
{
...
...
src/share/classes/sun/security/krb5/KrbApRep.java
浏览文件 @
1c14b0a7
...
...
@@ -53,12 +53,10 @@ public class KrbApRep {
*/
// Used in AcceptSecContextToken
public
KrbApRep
(
KrbApReq
incomingReq
,
boolean
useSeqNumber
,
boolean
useSubKey
)
throws
KrbException
,
IOException
{
boolean
useSeqNumber
,
EncryptionKey
subKey
)
throws
KrbException
,
IOException
{
EncryptionKey
subKey
=
(
useSubKey
?
new
EncryptionKey
(
incomingReq
.
getCreds
().
getSessionKey
()):
null
);
SeqNumber
seqNum
=
new
LocalSeqNumber
();
init
(
incomingReq
,
subKey
,
seqNum
);
...
...
src/share/classes/sun/security/krb5/KrbApReq.java
浏览文件 @
1c14b0a7
...
...
@@ -33,12 +33,14 @@ package sun.security.krb5;
import
sun.security.krb5.internal.*
;
import
sun.security.krb5.internal.crypto.*
;
import
sun.security.krb5.internal.rcache.*
;
import
sun.security.jgss.krb5.Krb5AcceptCredential
;
import
java.net.InetAddress
;
import
sun.security.util.*
;
import
java.io.IOException
;
import
java.util.Arrays
;
import
java.security.MessageDigest
;
import
java.security.NoSuchAlgorithmException
;
import
sun.security.krb5.internal.rcache.AuthTimeWithHash
;
/**
* This class encapsulates a KRB-AP-REQ that a client sends to a
...
...
@@ -53,11 +55,23 @@ public class KrbApReq {
private
Credentials
creds
;
private
APReq
apReqMessg
;
private
static
CacheTable
table
=
new
CacheTable
();
// Used by acceptor side
private
static
ReplayCache
rcache
=
ReplayCache
.
getInstance
();
private
static
boolean
DEBUG
=
Krb5
.
DEBUG
;
private
static
final
char
[]
hexConst
=
"0123456789ABCDEF"
.
toCharArray
();
private
static
final
MessageDigest
md
;
static
{
try
{
md
=
MessageDigest
.
getInstance
(
"MD5"
);
}
catch
(
NoSuchAlgorithmException
ex
)
{
throw
new
RuntimeException
(
"Impossible"
);
}
}
/**
* Con
tructs a
AP-REQ message to send to the peer.
* Con
structs an
AP-REQ message to send to the peer.
* @param tgsCred the <code>Credentials</code> to be used to construct the
* AP Request protocol message.
* @param mutualRequired Whether mutual authentication is required
...
...
@@ -81,7 +95,7 @@ public class KrbApReq {
*/
/**
* Con
tructs a
AP-REQ message to send to the peer.
* Con
structs an
AP-REQ message to send to the peer.
* @param tgsCred the <code>Credentials</code> to be used to construct the
* AP Request protocol message.
* @param mutualRequired Whether mutual authentication is required
...
...
@@ -125,7 +139,7 @@ public class KrbApReq {
}
/**
* Con
tructs a
AP-REQ message from the bytes received from the
* Con
structs an
AP-REQ message from the bytes received from the
* peer.
* @param message The message received from the peer
* @param keys <code>EncrtyptionKey</code>s to decrypt the message;
...
...
@@ -146,7 +160,7 @@ public class KrbApReq {
}
/**
* Con
tructs a
AP-REQ message from the bytes received from the
* Con
structs an
AP-REQ message from the bytes received from the
* peer.
* @param value The <code>DerValue</code> that contains the
* DER enoded AP-REQ protocol message
...
...
@@ -297,15 +311,19 @@ public class KrbApReq {
if
(!
authenticator
.
ctime
.
inClockSkew
())
throw
new
KrbApErrException
(
Krb5
.
KRB_AP_ERR_SKEW
);
// start to check if it is a replay attack.
AuthTime
time
=
new
AuthTime
(
authenticator
.
ctime
.
getTime
(),
authenticator
.
cusec
);
String
client
=
authenticator
.
cname
.
toString
();
if
(
table
.
get
(
time
,
authenticator
.
cname
.
toString
())
!=
null
)
{
throw
new
KrbApErrException
(
Krb5
.
KRB_AP_ERR_REPEAT
);
}
else
{
table
.
put
(
client
,
time
,
System
.
currentTimeMillis
());
byte
[]
hash
=
md
.
digest
(
apReqMessg
.
authenticator
.
cipher
);
char
[]
h
=
new
char
[
hash
.
length
*
2
];
for
(
int
i
=
0
;
i
<
hash
.
length
;
i
++)
{
h
[
2
*
i
]
=
hexConst
[(
hash
[
i
]&
0xff
)>>
4
];
h
[
2
*
i
+
1
]
=
hexConst
[
hash
[
i
]&
0xf
];
}
AuthTimeWithHash
time
=
new
AuthTimeWithHash
(
authenticator
.
cname
.
toString
(),
apReqMessg
.
ticket
.
sname
.
toString
(),
authenticator
.
ctime
.
getSeconds
(),
authenticator
.
cusec
,
new
String
(
h
));
rcache
.
checkAndStore
(
KerberosTime
.
now
(),
time
);
if
(
initiator
!=
null
)
{
// sender host address
...
...
src/share/classes/sun/security/krb5/internal/ReplayCache.java
0 → 100644
浏览文件 @
1c14b0a7
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.krb5.internal
;
import
sun.security.action.GetPropertyAction
;
import
sun.security.krb5.internal.rcache.AuthTimeWithHash
;
import
sun.security.krb5.internal.rcache.MemoryCache
;
import
sun.security.krb5.internal.rcache.DflCache
;
import
java.security.AccessController
;
/**
* Models the replay cache of an acceptor as described in
* RFC 4120 3.2.3.
* @since 1.8
*/
public
abstract
class
ReplayCache
{
public
static
ReplayCache
getInstance
(
String
type
)
{
if
(
type
==
null
)
{
return
new
MemoryCache
();
}
else
if
(
type
.
equals
(
"dfl"
)
||
type
.
startsWith
(
"dfl:"
))
{
return
new
DflCache
(
type
);
}
else
if
(
type
.
equals
(
"none"
))
{
return
new
ReplayCache
()
{
@Override
public
void
checkAndStore
(
KerberosTime
currTime
,
AuthTimeWithHash
time
)
throws
KrbApErrException
{
// no check at all
}
};
}
else
{
throw
new
IllegalArgumentException
(
"Unknown type: "
+
type
);
}
}
public
static
ReplayCache
getInstance
()
{
String
type
=
AccessController
.
doPrivileged
(
new
GetPropertyAction
(
"sun.security.krb5.rcache"
));
return
getInstance
(
type
);
}
/**
* Accepts or rejects an AuthTime.
* @param currTime the current time
* @param time AuthTimeWithHash object calculated from authenticator
* @throws KrbApErrException if the authenticator is a replay
*/
public
abstract
void
checkAndStore
(
KerberosTime
currTime
,
AuthTimeWithHash
time
)
throws
KrbApErrException
;
}
src/share/classes/sun/security/krb5/internal/rcache/
ReplayCache
.java
→
src/share/classes/sun/security/krb5/internal/rcache/
AuthList
.java
浏览文件 @
1c14b0a7
...
...
@@ -32,112 +32,113 @@
package
sun.security.krb5.internal.rcache
;
import
sun.security.krb5.internal.Krb5
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
java.util.ListIterator
;
import
sun.security.krb5.internal.KerberosTime
;
import
sun.security.krb5.internal.KrbApErrException
;
/**
* This class provides an efficient caching mechanism to store the timestamp of client authenticators.
* The cache minimizes the memory usage by doing self-cleanup of expired items in the cache.
* This class provides an efficient caching mechanism to store AuthTimeWithHash
* from client authenticators. The cache minimizes the memory usage by doing
* self-cleanup of expired items in the cache.
*
* AuthTimeWithHash objects inside a cache are always sorted from big (new) to
* small (old) as determined by {@see AuthTimeWithHash#compareTo}. In the most
* common case a newcomer should be newer than the first element.
*
* @author Yanni Zhang
*/
public
class
ReplayCache
extends
LinkedList
<
AuthTime
>
{
private
static
final
long
serialVersionUID
=
2997933194993803994L
;
// These 3 fields are now useless, keep for serialization compatibility
private
String
principal
;
private
CacheTable
table
;
private
int
nap
=
10
*
60
*
1000
;
//10 minutes break
public
class
AuthList
{
private
boolean
DEBUG
=
Krb5
.
DEBUG
;
private
final
LinkedList
<
AuthTimeWithHash
>
entries
;
private
final
int
lifespan
;
/**
* Constructs a ReplayCache for a client principal in specified <code>CacheTable</code>.
* @param p client principal name.
* @param ct CacheTable.
* Constructs a AuthList.
*/
public
ReplayCache
(
String
p
,
CacheTable
ct
)
{
principal
=
p
;
table
=
ct
;
public
AuthList
(
int
lifespan
)
{
this
.
lifespan
=
lifespan
;
entries
=
new
LinkedList
<>()
;
}
/**
* Puts the authenticator timestamp into the cache in descending order
.
*
@param t <code>AuthTime</code>
* Puts the authenticator timestamp into the cache in descending order
,
*
and throw an exception if it's already there.
*/
public
synchronized
void
put
(
AuthTime
t
,
long
currentTime
)
{
public
void
put
(
AuthTimeWithHash
t
,
KerberosTime
currentTime
)
throws
KrbApErrException
{
if
(
this
.
size
()
==
0
)
{
addFirst
(
t
);
}
else
{
AuthTime
temp
=
getFirst
();
if
(
temp
.
kerberosTime
<
t
.
kerberosTime
)
{
// in most cases, newly received authenticator has
// larger timestamp.
addFirst
(
t
);
}
else
if
(
temp
.
kerberosTime
==
t
.
kerberosTime
)
{
if
(
temp
.
cusec
<
t
.
cusec
)
{
addFirst
(
t
);
}
}
else
{
if
(
entries
.
isEmpty
())
{
entries
.
addFirst
(
t
);
}
else
{
AuthTimeWithHash
temp
=
entries
.
getFirst
();
int
cmp
=
temp
.
compareTo
(
t
);
if
(
cmp
<
0
)
{
// This is the most common case, newly received authenticator
// has larger timestamp.
entries
.
addFirst
(
t
);
}
else
if
(
cmp
==
0
)
{
throw
new
KrbApErrException
(
Krb5
.
KRB_AP_ERR_REPEAT
);
}
else
{
//unless client clock being re-adjusted.
ListIterator
<
AuthTime
>
it
=
listIterator
(
1
);
ListIterator
<
AuthTimeWithHash
>
it
=
entries
.
listIterator
(
1
);
boolean
found
=
false
;
while
(
it
.
hasNext
())
{
temp
=
it
.
next
();
if
(
temp
.
kerberosTime
<
t
.
kerberosTime
)
{
add
(
indexOf
(
temp
),
t
);
cmp
=
temp
.
compareTo
(
t
);
if
(
cmp
<
0
)
{
// Find an older one, put in front of it
entries
.
add
(
entries
.
indexOf
(
temp
),
t
);
found
=
true
;
break
;
//we always put the bigger timestamp at the front.
}
else
if
(
temp
.
kerberosTime
==
t
.
kerberosTime
)
{
if
(
temp
.
cusec
<
t
.
cusec
)
{
add
(
indexOf
(
temp
),
t
);
break
;
}
}
else
if
(
cmp
==
0
)
{
throw
new
KrbApErrException
(
Krb5
.
KRB_AP_ERR_REPEAT
);
}
}
if
(!
found
)
{
// All is newer than the newcomer. Sigh.
entries
.
addLast
(
t
);
}
}
}
// let us cleanup while we are here
long
timeLimit
=
currentTime
-
KerberosTime
.
getDefaultSkew
()
*
1000L
;
ListIterator
<
AuthTime
>
it
=
listIterator
(
0
);
AuthTime
temp
=
null
;
long
timeLimit
=
currentTime
.
getSeconds
()
-
lifespan
;
ListIterator
<
AuthTime
WithHash
>
it
=
entries
.
listIterator
(
0
);
AuthTime
WithHash
temp
=
null
;
int
index
=
-
1
;
while
(
it
.
hasNext
())
{
//search expired timestamps.
//
search expired timestamps.
temp
=
it
.
next
();
if
(
temp
.
kerberosT
ime
<
timeLimit
)
{
index
=
indexOf
(
temp
);
if
(
temp
.
ct
ime
<
timeLimit
)
{
index
=
entries
.
indexOf
(
temp
);
break
;
}
}
// It would be nice if LinkedList has a method called truncate(index).
if
(
index
>
-
1
)
{
do
{
//remove expired timestamps from the list.
removeLast
();
}
while
(
size
()
>
index
);
}
if
(
DEBUG
)
{
printList
();
// remove expired timestamps from the list.
entries
.
removeLast
();
}
while
(
entries
.
size
()
>
index
);
}
}
public
boolean
isEmpty
()
{
return
entries
.
isEmpty
();
}
/**
* Prints out the debug message.
*/
private
void
printList
()
{
Object
[]
total
=
toArray
();
for
(
int
i
=
0
;
i
<
total
.
length
;
i
++)
{
System
.
out
.
println
(
"object "
+
i
+
": "
+
((
AuthTime
)
total
[
i
]).
kerberosTime
+
"/"
+
((
AuthTime
)
total
[
i
]).
cusec
);
public
String
toString
()
{
StringBuilder
sb
=
new
StringBuilder
();
Iterator
<
AuthTimeWithHash
>
iter
=
entries
.
descendingIterator
();
int
pos
=
entries
.
size
();
while
(
iter
.
hasNext
())
{
AuthTimeWithHash
at
=
iter
.
next
();
sb
.
append
(
'#'
).
append
(
pos
--).
append
(
": "
)
.
append
(
at
.
toString
()).
append
(
'\n'
);
}
return
sb
.
toString
();
}
}
src/share/classes/sun/security/krb5/internal/rcache/AuthTime.java
浏览文件 @
1c14b0a7
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -30,54 +31,126 @@
package
sun.security.krb5.internal.rcache
;
import
sun.security.krb5.internal.KerberosTime
;
import
java.io.IOException
;
import
java.nio.BufferUnderflowException
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
import
java.nio.channels.SeekableByteChannel
;
import
java.nio.charset.StandardCharsets
;
import
java.util.StringTokenizer
;
/**
* The class represents the timestamp in authenticator.
* The class represents an old style replay cache entry. It is only used in
* a dfl file.
*
* @author Sun/Oracle
* @author Yanni Zhang
*/
public
class
AuthTime
{
long
kerberosTime
;
int
cusec
;
final
int
ctime
;
final
int
cusec
;
final
String
client
;
final
String
server
;
/**
* Constructs a new <code>AuthTime</code>.
* @param time time from the <code>Authenticator</code>.
* @param cusec microsecond field from the <code>Authenticator</code>.
* Constructs an <code>AuthTime</code>.
*/
public
AuthTime
(
long
time
,
int
c
)
{
kerberosTime
=
time
;
cusec
=
c
;
public
AuthTime
(
String
client
,
String
server
,
int
ctime
,
int
cusec
)
{
this
.
ctime
=
ctime
;
this
.
cusec
=
cusec
;
this
.
client
=
client
;
this
.
server
=
server
;
}
@Override
public
String
toString
()
{
return
String
.
format
(
"%d/%06d/----/%s"
,
ctime
,
cusec
,
client
);
}
// Methods used when saved in a dfl file. See DflCache.java
/**
* Compares if an object equals to an <code>AuthTime</code> object.
* @param o an object.
* @return true if two objects are equivalent, otherwise, return false.
* Reads an LC style string from a channel, which is a int32 length
* plus a UTF-8 encoded string possibly ends with \0.
* @throws IOException if there is a format error
* @throws BufferUnderflowException if goes beyond the end
*/
public
boolean
equals
(
Object
o
)
{
if
(
o
instanceof
AuthTime
)
{
if
((((
AuthTime
)
o
).
kerberosTime
==
kerberosTime
)
&&
(((
AuthTime
)
o
).
cusec
==
cusec
))
{
return
true
;
}
private
static
String
readStringWithLength
(
SeekableByteChannel
chan
)
throws
IOException
{
ByteBuffer
bb
=
ByteBuffer
.
allocate
(
4
);
bb
.
order
(
ByteOrder
.
nativeOrder
());
chan
.
read
(
bb
);
bb
.
flip
();
int
len
=
bb
.
getInt
();
if
(
len
>
1024
)
{
// Memory attack? The string should be fairly short.
throw
new
IOException
(
"Invalid string length"
);
}
return
false
;
bb
=
ByteBuffer
.
allocate
(
len
);
if
(
chan
.
read
(
bb
)
!=
len
)
{
throw
new
IOException
(
"Not enough string"
);
}
byte
[]
data
=
bb
.
array
();
return
(
data
[
len
-
1
]
==
0
)?
new
String
(
data
,
0
,
len
-
1
,
StandardCharsets
.
UTF_8
):
new
String
(
data
,
StandardCharsets
.
UTF_8
);
}
/**
* Re
turns a hash code for this <code>AuthTime</code> object
.
*
* @
return a <code>hash code</code> value for this object.
* Re
ads an AuthTime or AuthTimeWithHash object from a channel
.
*
@throws IOException if there is a format error
* @
throws BufferUnderflowException if goes beyond the end
*/
public
int
hashCode
()
{
int
result
=
17
;
result
=
37
*
result
+
(
int
)(
kerberosTime
^
(
kerberosTime
>>>
32
));
result
=
37
*
result
+
cusec
;
public
static
AuthTime
readFrom
(
SeekableByteChannel
chan
)
throws
IOException
{
String
client
=
readStringWithLength
(
chan
);
String
server
=
readStringWithLength
(
chan
);
ByteBuffer
bb
=
ByteBuffer
.
allocate
(
8
);
chan
.
read
(
bb
);
bb
.
order
(
ByteOrder
.
nativeOrder
());
int
cusec
=
bb
.
getInt
(
0
);
int
ctime
=
bb
.
getInt
(
4
);
if
(
client
.
isEmpty
())
{
StringTokenizer
st
=
new
StringTokenizer
(
server
,
" :"
);
if
(
st
.
countTokens
()
!=
6
)
{
throw
new
IOException
(
"Incorrect rcache style"
);
}
st
.
nextToken
();
String
hash
=
st
.
nextToken
();
st
.
nextToken
();
client
=
st
.
nextToken
();
st
.
nextToken
();
server
=
st
.
nextToken
();
return
new
AuthTimeWithHash
(
client
,
server
,
ctime
,
cusec
,
hash
);
}
else
{
return
new
AuthTime
(
client
,
server
,
ctime
,
cusec
);
}
}
return
result
;
/**
* Encodes to be used in a dfl file
*/
protected
byte
[]
encode0
(
String
cstring
,
String
sstring
)
{
byte
[]
c
=
cstring
.
getBytes
(
StandardCharsets
.
UTF_8
);;
byte
[]
s
=
sstring
.
getBytes
(
StandardCharsets
.
UTF_8
);;
byte
[]
zero
=
new
byte
[
1
];
int
len
=
4
+
c
.
length
+
1
+
4
+
s
.
length
+
1
+
4
+
4
;
ByteBuffer
bb
=
ByteBuffer
.
allocate
(
len
)
.
order
(
ByteOrder
.
nativeOrder
());
bb
.
putInt
(
c
.
length
+
1
).
put
(
c
).
put
(
zero
)
.
putInt
(
s
.
length
+
1
).
put
(
s
).
put
(
zero
)
.
putInt
(
cusec
).
putInt
(
ctime
);
return
bb
.
array
();
}
/**
* Encodes to be used in a dfl file
* @param withHash useless here
*/
public
byte
[]
encode
(
boolean
withHash
)
{
return
encode0
(
client
,
server
);
}
}
src/share/classes/sun/security/krb5/internal/rcache/AuthTimeWithHash.java
0 → 100644
浏览文件 @
1c14b0a7
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.krb5.internal.rcache
;
import
java.util.Objects
;
/**
* The class represents a new style replay cache entry. It can be either used
* inside memory or in a dfl file.
*/
public
class
AuthTimeWithHash
extends
AuthTime
implements
Comparable
<
AuthTimeWithHash
>
{
final
String
hash
;
/**
* Constructs a new <code>AuthTimeWithHash</code>.
*/
public
AuthTimeWithHash
(
String
client
,
String
server
,
int
ctime
,
int
cusec
,
String
hash
)
{
super
(
client
,
server
,
ctime
,
cusec
);
this
.
hash
=
hash
;
}
/**
* Compares if an object equals to an <code>AuthTimeWithHash</code> object.
* @param o an object.
* @return true if two objects are equivalent, otherwise, return false.
*/
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
return
true
;
if
(!(
o
instanceof
AuthTimeWithHash
))
return
false
;
AuthTimeWithHash
that
=
(
AuthTimeWithHash
)
o
;
return
Objects
.
equals
(
hash
,
that
.
hash
)
&&
Objects
.
equals
(
client
,
that
.
client
)
&&
Objects
.
equals
(
server
,
that
.
server
)
&&
ctime
==
that
.
ctime
&&
cusec
==
that
.
cusec
;
}
/**
* Returns a hash code for this <code>AuthTimeWithHash</code> object.
*/
@Override
public
int
hashCode
()
{
return
Objects
.
hash
(
hash
);
}
@Override
public
String
toString
()
{
return
String
.
format
(
"%d/%06d/%s/%s"
,
ctime
,
cusec
,
hash
,
client
);
}
@Override
public
int
compareTo
(
AuthTimeWithHash
other
)
{
int
cmp
=
0
;
if
(
ctime
!=
other
.
ctime
)
{
cmp
=
Integer
.
compare
(
ctime
,
other
.
ctime
);
}
else
if
(
cusec
!=
other
.
cusec
)
{
cmp
=
Integer
.
compare
(
cusec
,
other
.
cusec
);
}
else
{
cmp
=
hash
.
compareTo
(
other
.
hash
);
}
return
cmp
;
}
/**
* Compares with a possibly old style object. Used
* in DflCache$Storage#loadAndCheck.
* @return true if all AuthTime fields are the same
*/
public
boolean
isSameIgnoresHash
(
AuthTime
old
)
{
return
client
.
equals
(
old
.
client
)
&&
server
.
equals
(
old
.
server
)
&&
ctime
==
old
.
ctime
&&
cusec
==
old
.
cusec
;
}
// Methods used when saved in a dfl file. See DflCache.java
/**
* Encodes to be used in a dfl file
* @param withHash write new style if true
*/
@Override
public
byte
[]
encode
(
boolean
withHash
)
{
String
cstring
;
String
sstring
;
if
(
withHash
)
{
cstring
=
""
;
sstring
=
String
.
format
(
"HASH:%s %d:%s %d:%s"
,
hash
,
client
.
length
(),
client
,
server
.
length
(),
server
);
}
else
{
cstring
=
client
;
sstring
=
server
;
}
return
encode0
(
cstring
,
sstring
);
}
}
src/share/classes/sun/security/krb5/internal/rcache/DflCache.java
0 → 100644
浏览文件 @
1c14b0a7
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.krb5.internal.rcache
;
import
java.io.*
;
import
java.nio.BufferUnderflowException
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
import
java.nio.channels.SeekableByteChannel
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.StandardCopyOption
;
import
java.nio.file.StandardOpenOption
;
import
java.nio.file.attribute.PosixFilePermission
;
import
java.security.AccessController
;
import
java.util.*
;
import
sun.security.action.GetPropertyAction
;
import
sun.security.krb5.internal.KerberosTime
;
import
sun.security.krb5.internal.Krb5
;
import
sun.security.krb5.internal.KrbApErrException
;
import
sun.security.krb5.internal.ReplayCache
;
/**
* A dfl file is used to sustores AuthTime entries when the system property
* sun.security.krb5.rcache is set to
*
* dfl(|:path/|:path/name|:name)
*
* The file will be path/name. If path is not given, it will be
*
* System.getProperty("java.io.tmpdir")
*
* If name is not given, it will be
*
* service_euid
*
* Java does not have a method to get euid, so uid is used instead. This
* should normally to be since a Java program is seldom used as a setuid app.
*
* The file has a header:
*
* i16 0x0501 (KRB5_RC_VNO) in network order
* i32 number of seconds for lifespan (in native order, same below)
*
* followed by cache entries concatenated, which can be encoded in
* 2 styles:
*
* The traditional style is:
*
* LC of client principal
* LC of server principal
* i32 cusec of Authenticator
* i32 ctime of Authenticator
*
* The new style has a hash:
*
* LC of ""
* LC of "HASH:%s %lu:%s %lu:%s" of (hash, clientlen, client, serverlen,
* server) where msghash is 32 char (lower case) text mode md5sum
* of the ciphertext of authenticator.
* i32 cusec of Authenticator
* i32 ctime of Authenticator
*
* where LC of a string means
*
* i32 strlen(string) + 1
* octets of string, with the \0x00 ending
*
* The old style block is always created by MIT krb5 used even if a new style
* is available, which means there can be 2 entries for a single Authenticator.
* Java also does this way.
*
* See src/lib/krb5/rcache/rc_io.c and src/lib/krb5/rcache/rc_dfl.c.
*/
public
class
DflCache
extends
ReplayCache
{
private
static
final
int
KRB5_RV_VNO
=
0x501
;
private
static
final
int
EXCESSREPS
=
30
;
// if missed-hit>this, recreate
private
final
String
source
;
private
static
int
uid
;
static
{
try
{
// Available on Solaris, Linux and Mac. Otherwise, no _euid suffix
Class
<?>
clazz
=
Class
.
forName
(
"com.sun.security.auth.module.UnixSystem"
);
uid
=
(
int
)(
long
)(
Long
)
clazz
.
getMethod
(
"getUid"
).
invoke
(
clazz
.
newInstance
());
}
catch
(
Exception
e
)
{
uid
=
-
1
;
}
}
public
DflCache
(
String
source
)
{
this
.
source
=
source
;
}
private
static
String
defaultPath
()
{
return
AccessController
.
doPrivileged
(
new
GetPropertyAction
(
"java.io.tmpdir"
));
}
private
static
String
defaultFile
(
String
server
)
{
// service/host@REALM -> service
int
slash
=
server
.
indexOf
(
'/'
);
if
(
slash
==
-
1
)
{
// A normal principal? say, dummy@REALM
slash
=
server
.
indexOf
(
'@'
);
}
if
(
slash
!=
-
1
)
{
// Should not happen, but be careful
server
=
server
.
substring
(
0
,
slash
);
}
if
(
uid
!=
-
1
)
{
server
+=
"_"
+
uid
;
}
return
server
;
}
private
static
Path
getFileName
(
String
source
,
String
server
)
{
String
path
,
file
;
if
(
source
.
equals
(
"dfl"
))
{
path
=
defaultPath
();
file
=
defaultFile
(
server
);
}
else
if
(
source
.
startsWith
(
"dfl:"
))
{
source
=
source
.
substring
(
4
);
int
pos
=
source
.
lastIndexOf
(
'/'
);
int
pos1
=
source
.
lastIndexOf
(
'\\'
);
if
(
pos1
>
pos
)
pos
=
pos1
;
if
(
pos
==
-
1
)
{
// Only file name
path
=
defaultPath
();
file
=
source
;
}
else
if
(
new
File
(
source
).
isDirectory
())
{
// Only path
path
=
source
;
file
=
defaultFile
(
server
);
}
else
{
// Full pathname
path
=
null
;
file
=
source
;
}
}
else
{
throw
new
IllegalArgumentException
();
}
return
new
File
(
path
,
file
).
toPath
();
}
@Override
public
void
checkAndStore
(
KerberosTime
currTime
,
AuthTimeWithHash
time
)
throws
KrbApErrException
{
try
{
checkAndStore0
(
currTime
,
time
);
}
catch
(
IOException
ioe
)
{
KrbApErrException
ke
=
new
KrbApErrException
(
Krb5
.
KRB_ERR_GENERIC
);
ke
.
initCause
(
ioe
);
throw
ke
;
}
}
private
synchronized
void
checkAndStore0
(
KerberosTime
currTime
,
AuthTimeWithHash
time
)
throws
IOException
,
KrbApErrException
{
Path
p
=
getFileName
(
source
,
time
.
server
);
int
missed
=
0
;
try
(
Storage
s
=
new
Storage
())
{
try
{
missed
=
s
.
loadAndCheck
(
p
,
time
,
currTime
);
}
catch
(
IOException
ioe
)
{
// Non-existing or invalid file
Storage
.
create
(
p
);
missed
=
s
.
loadAndCheck
(
p
,
time
,
currTime
);
}
s
.
append
(
time
);
}
if
(
missed
>
EXCESSREPS
)
{
Storage
.
expunge
(
p
,
currTime
);
}
}
private
static
class
Storage
implements
Closeable
{
// Static methods
@SuppressWarnings
(
"try"
)
private
static
void
create
(
Path
p
)
throws
IOException
{
try
(
SeekableByteChannel
newChan
=
createNoClose
(
p
))
{
// Do nothing, wait for close
}
makeMine
(
p
);
}
private
static
void
makeMine
(
Path
p
)
throws
IOException
{
// chmod to owner-rw only, otherwise MIT krb5 rejects
try
{
Set
<
PosixFilePermission
>
attrs
=
new
HashSet
<>();
attrs
.
add
(
PosixFilePermission
.
OWNER_READ
);
attrs
.
add
(
PosixFilePermission
.
OWNER_WRITE
);
Files
.
setPosixFilePermissions
(
p
,
attrs
);
}
catch
(
UnsupportedOperationException
uoe
)
{
// No POSIX permission. That's OK.
}
}
private
static
SeekableByteChannel
createNoClose
(
Path
p
)
throws
IOException
{
SeekableByteChannel
newChan
=
Files
.
newByteChannel
(
p
,
StandardOpenOption
.
CREATE
,
StandardOpenOption
.
TRUNCATE_EXISTING
,
StandardOpenOption
.
WRITE
);
ByteBuffer
buffer
=
ByteBuffer
.
allocate
(
6
);
buffer
.
putShort
((
short
)
KRB5_RV_VNO
);
buffer
.
order
(
ByteOrder
.
nativeOrder
());
buffer
.
putInt
(
KerberosTime
.
getDefaultSkew
());
buffer
.
flip
();
newChan
.
write
(
buffer
);
return
newChan
;
}
private
static
void
expunge
(
Path
p
,
KerberosTime
currTime
)
throws
IOException
{
Path
p2
=
Files
.
createTempFile
(
p
.
getParent
(),
"rcache"
,
null
);
try
(
SeekableByteChannel
oldChan
=
Files
.
newByteChannel
(
p
);
SeekableByteChannel
newChan
=
createNoClose
(
p2
))
{
long
timeLimit
=
currTime
.
getSeconds
()
-
readHeader
(
oldChan
);
while
(
true
)
{
try
{
AuthTime
at
=
AuthTime
.
readFrom
(
oldChan
);
if
(
at
.
ctime
>
timeLimit
)
{
ByteBuffer
bb
=
ByteBuffer
.
wrap
(
at
.
encode
(
true
));
newChan
.
write
(
bb
);
}
}
catch
(
BufferUnderflowException
e
)
{
break
;
}
}
}
makeMine
(
p2
);
Files
.
move
(
p2
,
p
,
StandardCopyOption
.
REPLACE_EXISTING
,
StandardCopyOption
.
ATOMIC_MOVE
);
}
// Instance methods
SeekableByteChannel
chan
;
private
int
loadAndCheck
(
Path
p
,
AuthTimeWithHash
time
,
KerberosTime
currTime
)
throws
IOException
,
KrbApErrException
{
int
missed
=
0
;
if
(
Files
.
isSymbolicLink
(
p
))
{
throw
new
IOException
(
"Symlink not accepted"
);
}
try
{
Set
<
PosixFilePermission
>
perms
=
Files
.
getPosixFilePermissions
(
p
);
if
(
uid
!=
-
1
&&
(
Integer
)
Files
.
getAttribute
(
p
,
"unix:uid"
)
!=
uid
)
{
throw
new
IOException
(
"Not mine"
);
}
if
(
perms
.
contains
(
PosixFilePermission
.
GROUP_READ
)
||
perms
.
contains
(
PosixFilePermission
.
GROUP_WRITE
)
||
perms
.
contains
(
PosixFilePermission
.
GROUP_EXECUTE
)
||
perms
.
contains
(
PosixFilePermission
.
OTHERS_READ
)
||
perms
.
contains
(
PosixFilePermission
.
OTHERS_WRITE
)
||
perms
.
contains
(
PosixFilePermission
.
OTHERS_EXECUTE
))
{
throw
new
IOException
(
"Accessible by someone else"
);
}
}
catch
(
UnsupportedOperationException
uoe
)
{
// No POSIX permissions? Ignore it.
}
chan
=
Files
.
newByteChannel
(
p
,
StandardOpenOption
.
WRITE
,
StandardOpenOption
.
READ
);
long
timeLimit
=
currTime
.
getSeconds
()
-
readHeader
(
chan
);
long
pos
=
0
;
boolean
seeNewButNotSame
=
false
;
while
(
true
)
{
try
{
pos
=
chan
.
position
();
AuthTime
a
=
AuthTime
.
readFrom
(
chan
);
if
(
a
instanceof
AuthTimeWithHash
)
{
if
(
time
.
equals
(
a
))
{
// Exact match, must be a replay
throw
new
KrbApErrException
(
Krb5
.
KRB_AP_ERR_REPEAT
);
}
else
if
(
time
.
isSameIgnoresHash
(
a
))
{
// Two different authenticators in the same second.
// Remember it
seeNewButNotSame
=
true
;
}
}
else
{
if
(
time
.
isSameIgnoresHash
(
a
))
{
// Two authenticators in the same second. Considered
// same if we haven't seen a new style version of it
if
(!
seeNewButNotSame
)
{
throw
new
KrbApErrException
(
Krb5
.
KRB_AP_ERR_REPEAT
);
}
}
}
if
(
a
.
ctime
<
timeLimit
)
{
missed
++;
}
else
{
missed
--;
}
}
catch
(
BufferUnderflowException
e
)
{
// Half-written file?
chan
.
position
(
pos
);
break
;
}
}
return
missed
;
}
private
static
int
readHeader
(
SeekableByteChannel
chan
)
throws
IOException
{
ByteBuffer
bb
=
ByteBuffer
.
allocate
(
6
);
chan
.
read
(
bb
);
if
(
bb
.
getShort
(
0
)
!=
KRB5_RV_VNO
)
{
throw
new
IOException
(
"Not correct rcache version"
);
}
bb
.
order
(
ByteOrder
.
nativeOrder
());
return
bb
.
getInt
(
2
);
}
private
void
append
(
AuthTimeWithHash
at
)
throws
IOException
{
// Write an entry with hash, to be followed by one without it,
// for the benefit of old implementations.
ByteBuffer
bb
;
bb
=
ByteBuffer
.
wrap
(
at
.
encode
(
true
));
chan
.
write
(
bb
);
bb
=
ByteBuffer
.
wrap
(
at
.
encode
(
false
));
chan
.
write
(
bb
);
}
@Override
public
void
close
()
throws
IOException
{
if
(
chan
!=
null
)
chan
.
close
();
chan
=
null
;
}
}
}
src/share/classes/sun/security/krb5/internal/rcache/
CacheTabl
e.java
→
src/share/classes/sun/security/krb5/internal/rcache/
MemoryCach
e.java
浏览文件 @
1c14b0a7
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -30,62 +31,55 @@
package
sun.security.krb5.internal.rcache
;
import
java.util.Hashtable
;
import
java.util.*
;
import
sun.security.krb5.internal.KerberosTime
;
import
sun.security.krb5.internal.KrbApErrException
;
import
sun.security.krb5.internal.ReplayCache
;
/**
* This class implements Hashtable to store the replay caches.
* This class stores replay caches. AuthTimeWithHash objects are categorized
* into AuthLists keyed by the names of client and server.
*
* @author Yanni Zhang
*/
public
class
CacheTable
extends
Hashtable
<
String
,
ReplayCache
>
{
public
class
MemoryCache
extends
ReplayCache
{
private
static
final
long
serialVersionUID
=
-
4695501354546664910L
;
// TODO: One day we'll need to read dynamic krb5.conf.
private
static
final
int
lifespan
=
KerberosTime
.
getDefaultSkew
();
private
static
final
boolean
DEBUG
=
sun
.
security
.
krb5
.
internal
.
Krb5
.
DEBUG
;
private
boolean
DEBUG
=
sun
.
security
.
krb5
.
internal
.
Krb5
.
DEBUG
;
public
CacheTable
()
{
}
private
final
Map
<
String
,
AuthList
>
content
=
new
HashMap
<>();
/**
* Puts the client timestamp in replay cache.
* @params principal the client's principal name.
* @params time authenticator timestamp.
*/
public
synchronized
void
put
(
String
principal
,
AuthTime
time
,
long
currTime
)
{
ReplayCache
rc
=
super
.
get
(
principal
);
@Override
public
synchronized
void
checkAndStore
(
KerberosTime
currTime
,
AuthTimeWithHash
time
)
throws
KrbApErrException
{
String
key
=
time
.
client
+
"|"
+
time
.
server
;
AuthList
rc
=
content
.
get
(
key
);
if
(
DEBUG
)
{
System
.
out
.
println
(
"MemoryCache: add "
+
time
+
" to "
+
key
);
}
if
(
rc
==
null
)
{
if
(
DEBUG
)
{
System
.
out
.
println
(
"replay cache for "
+
principal
+
" is null."
);
}
rc
=
new
ReplayCache
(
principal
,
this
);
rc
=
new
AuthList
(
lifespan
);
rc
.
put
(
time
,
currTime
);
if
(!
rc
.
isEmpty
())
{
super
.
put
(
principal
,
rc
);
content
.
put
(
key
,
rc
);
}
}
else
{
if
(
DEBUG
)
{
System
.
out
.
println
(
"MemoryCache: Existing AuthList:\n"
+
rc
);
}
}
else
{
rc
.
put
(
time
,
currTime
);
if
(
rc
.
isEmpty
())
{
super
.
remove
(
rc
);
}
if
(
DEBUG
)
{
System
.
out
.
println
(
"replay cache found."
);
content
.
remove
(
key
);
}
}
}
/**
* This method tests if replay cache keeps a record of the authenticator's time stamp.
* If there is a record (replay attack detected), the server should reject the client request.
* @params principal the client's principal name.
* @params time authenticator timestamp.
* @return null if no record found, else return an <code>AuthTime</code> object.
*/
public
Object
get
(
AuthTime
time
,
String
principal
)
{
ReplayCache
rc
=
super
.
get
(
principal
);
if
((
rc
!=
null
)
&&
(
rc
.
contains
(
time
)))
{
return
time
;
public
String
toString
()
{
StringBuilder
sb
=
new
StringBuilder
();
for
(
AuthList
rc:
content
.
values
())
{
sb
.
append
(
rc
.
toString
());
}
return
null
;
return
sb
.
toString
()
;
}
}
test/java/security/testlibrary/Proc.java
0 → 100644
浏览文件 @
1c14b0a7
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.net.URL
;
import
java.net.URLClassLoader
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.security.Permission
;
import
java.util.ArrayList
;
import
java.util.Base64
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
/**
* This is a test library that makes writing a Java test that spawns multiple
* Java processes easily.
*
* Usage:
*
* Proc.create("Clazz") // The class to launch
* .args("x") // with args
* .env("env", "value") // and an environment variable
* .prop("key","value") // and a system property
* .perm(perm) // with granted permissions
* .start(); // and start
*
* create/start must be called, args/env/prop/perm can be called zero or
* multiple times between create and start.
*
* The controller can call inheritIO to share its I/O to the process.
* Otherwise, it can send data into a proc's stdin with write/println, and
* read its stdout with readLine. stderr is always redirected to DFILE
* unless nodump() is called. A protocol is designed to make
* data exchange among the controller and the processes super easy, in which
* useful data are always printed with a special prefix ("PROCISFUN:").
* If the data is binary, make it BASE64.
*
* For example:
*
* - A producer Proc calls Proc.binOut() or Proc.textOut() to send out data.
* This method would prints to the stdout something like
*
* PROCISFUN:[raw text or base64 binary]
*
* - The controller calls producer.readData() to get the content. This method
* ignores all other output and only reads lines starting with "PROCISFUN:".
*
* - The controller does not care if the context is text or base64, it simply
* feeds the data to a consumer Proc by calling consumer.println(data).
* This will be printed into System.in of the consumer process.
*
* - The consumer Proc calls Proc.binIn() or Proc.textIn() to read the data.
* The first method de-base64 the input and return a byte[] block.
*
* Please note only plain ASCII is supported in raw text at the moment.
*
* As the Proc objects are hidden so deeply, two static methods, d(String) and
* d(Throwable) are provided to output info into stderr, where they will
* normally be appended messages to DFILE (unless nodump() is called).
* Developers can view the messages in real time by calling
*
* tail -f proc.debug
*
* TODO:
*
* . launch java tools, say, keytool
* . launch another version of java
* . start in another directory
* . start and finish using one method
*
* This is not a test, but is the core of
* JDK-8009977: A test library to launch multiple Java processes
*/
public
class
Proc
{
private
Process
p
;
private
BufferedReader
br
;
// the stdout of a process
private
String
launcher
;
// Optional: the java program
private
List
<
Permission
>
perms
=
new
ArrayList
<>();
private
List
<
String
>
args
=
new
ArrayList
<>();
private
Map
<
String
,
String
>
env
=
new
HashMap
<>();
private
Map
<
String
,
String
>
prop
=
new
HashMap
();
private
boolean
inheritIO
=
false
;
private
boolean
noDump
=
false
;
private
String
clazz
;
// Class to launch
private
String
debug
;
// debug flag, controller will show data
// transfer between procs
final
private
static
String
PREFIX
=
"PROCISFUN:"
;
final
private
static
String
DFILE
=
"proc.debug"
;
// The following methods are called by controllers
// Creates a Proc by the Java class name, launcher is an optional
// argument to specify the java program
public
static
Proc
create
(
String
clazz
,
String
...
launcher
)
{
Proc
pc
=
new
Proc
();
pc
.
clazz
=
clazz
;
if
(
launcher
.
length
>
0
)
{
pc
.
launcher
=
launcher
[
0
];
}
return
pc
;
}
// Sets inheritIO flag to proc. If set, proc will same I/O channels as
// teh controller. Otherwise, its stdin/stdout is untouched, and its
// stderr is redirected to DFILE.
public
Proc
inheritIO
()
{
inheritIO
=
true
;
return
this
;
}
// When called, stderr inherits parent stderr, otherwise, append to a file
public
Proc
nodump
()
{
noDump
=
true
;
return
this
;
}
// Specifies some args. Can be called multiple times.
public
Proc
args
(
String
...
args
)
{
for
(
String
c:
args
)
{
this
.
args
.
add
(
c
);
}
return
this
;
}
// Returns debug prefix
public
String
debug
()
{
return
debug
;
}
// Enables debug with prefix
public
Proc
debug
(
String
title
)
{
debug
=
title
;
return
this
;
}
// Specifies an env var. Can be called multiple times.
public
Proc
env
(
String
a
,
String
b
)
{
env
.
put
(
a
,
b
);
return
this
;
}
// Specifies a Java system property. Can be called multiple times.
public
Proc
prop
(
String
a
,
String
b
)
{
prop
.
put
(
a
,
b
);
return
this
;
}
// Adds a perm to policy. Can be called multiple times. In order to make it
// effective, please also call prop("java.security.manager", "").
public
Proc
perm
(
Permission
p
)
{
perms
.
add
(
p
);
return
this
;
}
// Starts the proc
public
Proc
start
()
throws
IOException
{
List
<
String
>
cmd
=
new
ArrayList
<>();
if
(
launcher
!=
null
)
{
cmd
.
add
(
launcher
);
}
else
{
cmd
.
add
(
new
File
(
new
File
(
System
.
getProperty
(
"java.home"
),
"bin"
),
"java"
).
getPath
());
}
cmd
.
add
(
"-cp"
);
StringBuilder
cp
=
new
StringBuilder
();
for
(
URL
url:
((
URLClassLoader
)
Proc
.
class
.
getClassLoader
()).
getURLs
())
{
if
(
cp
.
length
()
!=
0
)
{
cp
.
append
(
File
.
pathSeparatorChar
);
}
cp
.
append
(
url
.
getFile
());
}
cmd
.
add
(
cp
.
toString
());
for
(
Entry
<
String
,
String
>
e:
prop
.
entrySet
())
{
cmd
.
add
(
"-D"
+
e
.
getKey
()
+
"="
+
e
.
getValue
());
}
if
(!
perms
.
isEmpty
())
{
Path
p
=
Files
.
createTempFile
(
Paths
.
get
(
"."
).
toAbsolutePath
(),
"policy"
,
null
);
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
"grant {\n"
);
for
(
Permission
perm:
perms
)
{
// Sometimes a permission has no name or actions.
// but it's safe to use an empty string.
String
s
=
String
.
format
(
"%s \"%s\", \"%s\""
,
perm
.
getClass
().
getCanonicalName
(),
perm
.
getName
()
.
replace
(
"\\"
,
"\\\\"
).
replace
(
"\""
,
"\\\""
),
perm
.
getActions
());
sb
.
append
(
" permission "
).
append
(
s
).
append
(
";\n"
);
}
sb
.
append
(
"};\n"
);
Files
.
write
(
p
,
sb
.
toString
().
getBytes
());
cmd
.
add
(
"-Djava.security.policy="
+
p
.
toString
());
}
cmd
.
add
(
clazz
);
for
(
String
s:
args
)
{
cmd
.
add
(
s
);
}
if
(
debug
!=
null
)
{
System
.
out
.
println
(
"PROC: "
+
debug
+
" cmdline: "
+
cmd
);
}
ProcessBuilder
pb
=
new
ProcessBuilder
(
cmd
);
for
(
Entry
<
String
,
String
>
e:
env
.
entrySet
())
{
pb
.
environment
().
put
(
e
.
getKey
(),
e
.
getValue
());
}
if
(
inheritIO
)
{
pb
.
inheritIO
();
}
else
if
(
noDump
)
{
pb
.
redirectError
(
ProcessBuilder
.
Redirect
.
INHERIT
);
}
else
{
pb
.
redirectError
(
ProcessBuilder
.
Redirect
.
appendTo
(
new
File
(
DFILE
)));
}
p
=
pb
.
start
();
br
=
new
BufferedReader
(
new
InputStreamReader
(
p
.
getInputStream
()));
return
this
;
}
// Reads a line from stdout of proc
public
String
readLine
()
throws
IOException
{
String
s
=
br
.
readLine
();
if
(
debug
!=
null
)
{
System
.
out
.
println
(
"PROC: "
+
debug
+
" readline: "
+
(
s
==
null
?
"<EOF>"
:
s
));
}
return
s
;
}
// Reads a special line from stdout of proc
public
String
readData
()
throws
Exception
{
while
(
true
)
{
String
s
=
readLine
();
if
(
s
==
null
)
{
if
(
p
.
waitFor
()
!=
0
)
{
throw
new
Exception
(
"Proc abnormal end"
);
}
else
{
return
s
;
}
}
if
(
s
.
startsWith
(
PREFIX
))
{
return
s
.
substring
(
PREFIX
.
length
());
}
}
}
// Writes text into stdin of proc
public
void
println
(
String
s
)
throws
IOException
{
if
(
debug
!=
null
)
{
System
.
out
.
println
(
"PROC: "
+
debug
+
" println: "
+
s
);
}
write
((
s
+
"\n"
).
getBytes
());
}
// Writes data into stdin of proc
public
void
write
(
byte
[]
b
)
throws
IOException
{
p
.
getOutputStream
().
write
(
b
);
p
.
getOutputStream
().
flush
();
}
// Reads all output and wait for process end
public
int
waitFor
()
throws
Exception
{
while
(
true
)
{
String
s
=
readLine
();
if
(
s
==
null
)
{
break
;
}
}
return
p
.
waitFor
();
}
// The following methods are used inside a proc
// Writes out a BASE64 binary with a prefix
public
static
void
binOut
(
byte
[]
data
)
{
System
.
out
.
println
(
PREFIX
+
Base64
.
getEncoder
().
encodeToString
(
data
));
}
// Reads in a line of BASE64 binary
public
static
byte
[]
binIn
()
throws
Exception
{
return
Base64
.
getDecoder
().
decode
(
textIn
());
}
// Writes out a text with a prefix
public
static
void
textOut
(
String
data
)
{
System
.
out
.
println
(
PREFIX
+
data
);
}
// Reads in a line of text
public
static
String
textIn
()
throws
Exception
{
StringBuilder
sb
=
new
StringBuilder
();
boolean
isEmpty
=
true
;
while
(
true
)
{
int
i
=
System
.
in
.
read
();
if
(
i
==
-
1
)
break
;
isEmpty
=
false
;
if
(
i
==
'\n'
)
break
;
if
(
i
!=
13
)
{
// Force it to a char, so only simple ASCII works.
sb
.
append
((
char
)
i
);
}
}
return
isEmpty
?
null
:
sb
.
toString
();
}
// Sends string to stderr. If inheritIO is not called, they will
// be collected into DFILE
public
static
void
d
(
String
s
)
throws
IOException
{
System
.
err
.
println
(
s
);
}
// Sends an exception to stderr
public
static
void
d
(
Throwable
e
)
throws
IOException
{
e
.
printStackTrace
();
}
}
test/sun/security/krb5/auto/AcceptorSubKey.java
浏览文件 @
1c14b0a7
...
...
@@ -26,10 +26,10 @@
* @bug 7077646
* @summary gssapi wrap for CFX per-message tokens always set FLAG_ACCEPTOR_SUBKEY
* @compile -XDignore.symbol.file AcceptorSubKey.java
* @run main/othervm AcceptorSubKey
* @run main/othervm AcceptorSubKey 0
* @run main/othervm AcceptorSubKey 4
*/
import
java.util.Arrays
;
import
sun.security.jgss.GSSUtil
;
// The basic krb5 test skeleton you can copy from
...
...
@@ -37,8 +37,14 @@ public class AcceptorSubKey {
public
static
void
main
(
String
[]
args
)
throws
Exception
{
int
expected
=
Integer
.
parseInt
(
args
[
0
]);
new
OneKDC
(
null
).
writeJAASConf
();
if
(
expected
!=
0
)
{
System
.
setProperty
(
"sun.security.krb5.acceptor.subkey"
,
"true"
);
}
Context
c
,
s
;
c
=
Context
.
fromJAAS
(
"client"
);
s
=
Context
.
fromJAAS
(
"server"
);
...
...
@@ -53,8 +59,8 @@ public class AcceptorSubKey {
// FLAG_ACCEPTOR_SUBKEY is 4
int
flagOn
=
wrapped
[
2
]
&
4
;
if
(
flagOn
!=
0
)
{
throw
new
Exception
(
"
Java GSS should not have set acceptor subkey
"
);
if
(
flagOn
!=
expected
)
{
throw
new
Exception
(
"
not expected
"
);
}
s
.
dispose
();
...
...
test/sun/security/krb5/auto/BasicProc.java
0 → 100644
浏览文件 @
1c14b0a7
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8009977
* @summary A test library to launch multiple Java processes
* @library ../../../../java/security/testlibrary/
* @compile -XDignore.symbol.file BasicProc.java
* @run main/othervm BasicProc
*/
import
java.io.File
;
import
org.ietf.jgss.Oid
;
import
javax.security.auth.PrivateCredentialPermission
;
public
class
BasicProc
{
static
String
CONF
=
"krb5.conf"
;
static
String
KTAB
=
"ktab"
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
HOST
=
"localhost"
;
String
SERVER
=
"server/"
+
HOST
;
String
BACKEND
=
"backend/"
+
HOST
;
String
USER
=
"user"
;
char
[]
PASS
=
"password"
.
toCharArray
();
String
REALM
=
"REALM"
;
Oid
oid
=
new
Oid
(
"1.2.840.113554.1.2.2"
);
if
(
args
.
length
==
0
)
{
System
.
setProperty
(
"java.security.krb5.conf"
,
CONF
);
KDC
kdc
=
KDC
.
create
(
REALM
,
HOST
,
0
,
true
);
kdc
.
addPrincipal
(
USER
,
PASS
);
kdc
.
addPrincipalRandKey
(
"krbtgt/"
+
REALM
);
kdc
.
addPrincipalRandKey
(
SERVER
);
kdc
.
addPrincipalRandKey
(
BACKEND
);
String
cwd
=
System
.
getProperty
(
"user.dir"
);
kdc
.
writeKtab
(
KTAB
);
KDC
.
saveConfig
(
CONF
,
kdc
,
"forwardable = true"
);
Proc
pc
=
Proc
.
create
(
"BasicProc"
)
.
args
(
"client"
)
.
prop
(
"java.security.krb5.conf"
,
CONF
)
.
prop
(
"java.security.manager"
,
""
)
.
perm
(
new
java
.
util
.
PropertyPermission
(
"sun.security.krb5.principal"
,
"read"
))
.
perm
(
new
javax
.
security
.
auth
.
AuthPermission
(
"modifyPrincipals"
))
.
perm
(
new
javax
.
security
.
auth
.
AuthPermission
(
"modifyPrivateCredentials"
))
.
perm
(
new
javax
.
security
.
auth
.
AuthPermission
(
"doAs"
))
.
perm
(
new
javax
.
security
.
auth
.
kerberos
.
ServicePermission
(
"krbtgt/"
+
REALM
+
"@"
+
REALM
,
"initiate"
))
.
perm
(
new
javax
.
security
.
auth
.
kerberos
.
ServicePermission
(
"server/localhost@"
+
REALM
,
"initiate"
))
.
perm
(
new
javax
.
security
.
auth
.
kerberos
.
DelegationPermission
(
"\"server/localhost@"
+
REALM
+
"\" "
+
"\"krbtgt/"
+
REALM
+
"@"
+
REALM
+
"\""
))
.
debug
(
"C"
)
.
start
();
Proc
ps
=
Proc
.
create
(
"BasicProc"
)
.
args
(
"server"
)
.
prop
(
"java.security.krb5.conf"
,
CONF
)
.
prop
(
"java.security.manager"
,
""
)
.
perm
(
new
java
.
util
.
PropertyPermission
(
"sun.security.krb5.principal"
,
"read"
))
.
perm
(
new
javax
.
security
.
auth
.
AuthPermission
(
"modifyPrincipals"
))
.
perm
(
new
javax
.
security
.
auth
.
AuthPermission
(
"modifyPrivateCredentials"
))
.
perm
(
new
javax
.
security
.
auth
.
AuthPermission
(
"doAs"
))
.
perm
(
new
PrivateCredentialPermission
(
"javax.security.auth.kerberos.KeyTab * \"*\""
,
"read"
))
.
perm
(
new
javax
.
security
.
auth
.
kerberos
.
ServicePermission
(
"server/localhost@"
+
REALM
,
"accept"
))
.
perm
(
new
java
.
io
.
FilePermission
(
cwd
+
File
.
separator
+
KTAB
,
"read"
))
.
perm
(
new
javax
.
security
.
auth
.
kerberos
.
ServicePermission
(
"backend/localhost@"
+
REALM
,
"initiate"
))
.
debug
(
"S"
)
.
start
();
Proc
pb
=
Proc
.
create
(
"BasicProc"
)
.
args
(
"backend"
)
.
prop
(
"java.security.krb5.conf"
,
CONF
)
.
prop
(
"java.security.manager"
,
""
)
.
perm
(
new
java
.
util
.
PropertyPermission
(
"sun.security.krb5.principal"
,
"read"
))
.
perm
(
new
javax
.
security
.
auth
.
AuthPermission
(
"modifyPrincipals"
))
.
perm
(
new
javax
.
security
.
auth
.
AuthPermission
(
"modifyPrivateCredentials"
))
.
perm
(
new
javax
.
security
.
auth
.
AuthPermission
(
"doAs"
))
.
perm
(
new
PrivateCredentialPermission
(
"javax.security.auth.kerberos.KeyTab * \"*\""
,
"read"
))
.
perm
(
new
javax
.
security
.
auth
.
kerberos
.
ServicePermission
(
"backend/localhost@"
+
REALM
,
"accept"
))
.
perm
(
new
java
.
io
.
FilePermission
(
cwd
+
File
.
separator
+
KTAB
,
"read"
))
.
debug
(
"B"
)
.
start
();
// Client and server handshake
String
token
=
pc
.
readData
();
ps
.
println
(
token
);
token
=
ps
.
readData
();
pc
.
println
(
token
);
// Server and backend handshake
token
=
ps
.
readData
();
pb
.
println
(
token
);
token
=
pb
.
readData
();
ps
.
println
(
token
);
// wrap/unwrap/getMic/verifyMic and plain text
token
=
ps
.
readData
();
pb
.
println
(
token
);
token
=
pb
.
readData
();
ps
.
println
(
token
);
token
=
pb
.
readData
();
ps
.
println
(
token
);
if
((
pc
.
waitFor
()
|
ps
.
waitFor
()
|
pb
.
waitFor
())
!=
0
)
{
throw
new
Exception
();
}
}
else
if
(
args
[
0
].
equals
(
"client"
))
{
Context
c
=
Context
.
fromUserPass
(
USER
,
PASS
,
false
);
c
.
startAsClient
(
SERVER
,
oid
);
c
.
x
().
requestCredDeleg
(
true
);
Proc
.
binOut
(
c
.
take
(
new
byte
[
0
]));
byte
[]
token
=
Proc
.
binIn
();
c
.
take
(
token
);
}
else
if
(
args
[
0
].
equals
(
"server"
))
{
Context
s
=
Context
.
fromUserKtab
(
SERVER
,
KTAB
,
true
);
s
.
startAsServer
(
oid
);
byte
[]
token
=
Proc
.
binIn
();
token
=
s
.
take
(
token
);
Proc
.
binOut
(
token
);
Context
s2
=
s
.
delegated
();
s2
.
startAsClient
(
BACKEND
,
oid
);
Proc
.
binOut
(
s2
.
take
(
new
byte
[
0
]));
token
=
Proc
.
binIn
();
s2
.
take
(
token
);
byte
[]
msg
=
"Hello"
.
getBytes
();
Proc
.
binOut
(
s2
.
wrap
(
msg
,
true
));
s2
.
verifyMic
(
Proc
.
binIn
(),
msg
);
String
in
=
Proc
.
textIn
();
if
(!
in
.
equals
(
"Hello"
))
{
throw
new
Exception
();
}
}
else
if
(
args
[
0
].
equals
(
"backend"
))
{
Context
b
=
Context
.
fromUserKtab
(
BACKEND
,
KTAB
,
true
);
b
.
startAsServer
(
oid
);
byte
[]
token
=
Proc
.
binIn
();
Proc
.
binOut
(
b
.
take
(
token
));
byte
[]
msg
=
b
.
unwrap
(
Proc
.
binIn
(),
true
);
Proc
.
binOut
(
b
.
getMic
(
msg
));
Proc
.
textOut
(
new
String
(
msg
));
}
}
// create a native server
private
static
Proc
ns
(
Proc
p
)
throws
Exception
{
return
p
.
env
(
"KRB5_CONFIG"
,
CONF
)
.
env
(
"KRB5_KTNAME"
,
KTAB
)
.
prop
(
"sun.security.jgss.native"
,
"true"
)
.
prop
(
"javax.security.auth.useSubjectCredsOnly"
,
"false"
)
.
prop
(
"sun.security.nativegss.debug"
,
"true"
);
}
}
test/sun/security/krb5/auto/Context.java
浏览文件 @
1c14b0a7
...
...
@@ -195,6 +195,7 @@ public class Context {
Krb5LoginModule
krb5
=
new
Krb5LoginModule
();
Map
<
String
,
String
>
map
=
new
HashMap
<>();
map
.
put
(
"isInitiator"
,
"false"
);
map
.
put
(
"doNotPrompt"
,
"true"
);
map
.
put
(
"useTicketCache"
,
"false"
);
map
.
put
(
"useKeyTab"
,
"true"
);
...
...
@@ -616,9 +617,10 @@ public class Context {
*/
static
public
void
handshake
(
final
Context
c
,
final
Context
s
)
throws
Exception
{
byte
[]
t
=
new
byte
[
0
];
while
(!
c
.
x
.
isEstablished
()
||
!
s
.
x
.
isEstablished
())
{
t
=
c
.
take
(
t
);
t
=
s
.
take
(
t
);
while
(
true
)
{
if
(
t
!=
null
||
!
c
.
x
.
isEstablished
())
t
=
c
.
take
(
t
);
if
(
t
!=
null
||
!
s
.
x
.
isEstablished
())
t
=
s
.
take
(
t
);
if
(
c
.
x
.
isEstablished
()
&&
s
.
x
.
isEstablished
())
break
;
}
}
}
test/sun/security/krb5/auto/KDC.java
浏览文件 @
1c14b0a7
...
...
@@ -1137,7 +1137,7 @@ public class KDC {
* @return REALM.NAME = { kdc = host:port }
*/
private
static
String
realmLineForKDC
(
KDC
kdc
)
{
return
String
.
format
(
"
%s = {\n kdc = %s:%d\n
}\n"
,
return
String
.
format
(
"
%s = {\n kdc = %s:%d\n
}\n"
,
kdc
.
realm
,
kdc
.
kdc
,
kdc
.
port
);
...
...
test/sun/security/krb5/auto/NoneReplayCacheTest.java
0 → 100644
浏览文件 @
1c14b0a7
/*
* Copyright 2013 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 8001326
* @run main/othervm NoneReplayCacheTest
* @summary the replaycache type none cannot stop an authenticator replay,
* but it can stop a message replay when s.s.k.acceptor.subkey is true.
* You should not really use none in production environment. This test merely
* shows there can be other protections when replay cache is not working fine.
*/
import
org.ietf.jgss.GSSException
;
import
sun.security.jgss.GSSUtil
;
public
class
NoneReplayCacheTest
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
OneKDC
(
null
);
System
.
setProperty
(
"sun.security.krb5.rcache"
,
"none"
);
System
.
setProperty
(
"sun.security.krb5.acceptor.subkey"
,
"true"
);
Context
c
,
s
;
c
=
Context
.
fromUserPass
(
OneKDC
.
USER
,
OneKDC
.
PASS
,
false
);
s
=
Context
.
fromUserKtab
(
OneKDC
.
SERVER
,
OneKDC
.
KTAB
,
true
);
c
.
startAsClient
(
OneKDC
.
SERVER
,
GSSUtil
.
GSS_KRB5_MECH_OID
);
s
.
startAsServer
(
GSSUtil
.
GSS_KRB5_MECH_OID
);
byte
[]
first
=
c
.
take
(
new
byte
[
0
]);
c
.
take
(
s
.
take
(
first
));
byte
[]
msg
=
c
.
wrap
(
"hello"
.
getBytes
(),
true
);
s
.
unwrap
(
msg
,
true
);
s
.
startAsServer
(
GSSUtil
.
GSS_KRB5_MECH_OID
);
s
.
take
(
first
);
// apreq replay not detectable
try
{
s
.
unwrap
(
msg
,
true
);
// msg replay detectable
throw
new
Exception
(
"This method should fail"
);
}
catch
(
GSSException
gsse
)
{
gsse
.
printStackTrace
();
}
}
}
test/sun/security/krb5/auto/ReplayCacheExpunge.java
0 → 100644
浏览文件 @
1c14b0a7
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8001326
* @run main/othervm ReplayCacheExpunge 16
* @run main/othervm/fail ReplayCacheExpunge 15
* @summary when number of expired entries minus number of good entries
* is more than 30, expunge occurs, and expired entries are forgotten.
*/
import
java.util.Random
;
import
sun.security.krb5.internal.KerberosTime
;
import
sun.security.krb5.internal.ReplayCache
;
import
sun.security.krb5.internal.rcache.AuthTimeWithHash
;
public
class
ReplayCacheExpunge
{
static
final
String
client
=
"dummy@REALM"
;
static
final
String
server
=
"server/localhost@REALM"
;
static
final
Random
rand
=
new
Random
();
public
static
void
main
(
String
[]
args
)
throws
Exception
{
int
count
=
Integer
.
parseInt
(
args
[
0
]);
ReplayCache
cache
=
ReplayCache
.
getInstance
(
"dfl:./"
);
AuthTimeWithHash
a1
=
new
AuthTimeWithHash
(
client
,
server
,
time
(-
400
),
0
,
hash
(
"1"
));
AuthTimeWithHash
a2
=
new
AuthTimeWithHash
(
client
,
server
,
time
(
0
),
0
,
hash
(
"4"
));
KerberosTime
now
=
new
KerberosTime
(
time
(
0
)*
1000L
);
KerberosTime
then
=
new
KerberosTime
(
time
(-
300
)*
1000L
);
// Once upon a time, we added a lot of events
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
a1
=
new
AuthTimeWithHash
(
client
,
server
,
time
(-
400
),
0
,
hash
(
""
));
cache
.
checkAndStore
(
then
,
a1
);
}
// Now, we add a new one. If some conditions hold, the old ones
// will be expunged.
cache
.
checkAndStore
(
now
,
a2
);
// and adding an old one will not trigger any error
cache
.
checkAndStore
(
now
,
a1
);
}
private
static
String
hash
(
String
s
)
{
char
[]
data
=
new
char
[
16
];
for
(
int
i
=
0
;
i
<
16
;
i
++)
{
if
(
i
<
s
.
length
())
data
[
i
]
=
s
.
charAt
(
i
);
else
data
[
i
]
=
(
char
)(
'0'
+
rand
.
nextInt
(
10
));
}
return
new
String
(
data
);
}
private
static
int
time
(
int
x
)
{
return
(
int
)(
System
.
currentTimeMillis
()/
1000
)
+
x
;
}
}
test/sun/security/krb5/auto/ReplayCachePrecise.java
0 → 100644
浏览文件 @
1c14b0a7
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8001326
* @run main/othervm ReplayCachePrecise
* @summary when there are 2 two AuthTime with the same time but different hash,
* it's not a replay.
*/
import
java.nio.ByteBuffer
;
import
java.nio.channels.SeekableByteChannel
;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.nio.file.StandardOpenOption
;
import
java.util.Random
;
import
sun.security.krb5.KrbException
;
import
sun.security.krb5.internal.KerberosTime
;
import
sun.security.krb5.internal.ReplayCache
;
import
sun.security.krb5.internal.rcache.AuthTimeWithHash
;
public
class
ReplayCachePrecise
{
static
final
String
client
=
"dummy@REALM"
;
static
final
String
server
=
"server/localhost@REALM"
;
static
final
Random
rand
=
new
Random
();
public
static
void
main
(
String
[]
args
)
throws
Exception
{
AuthTimeWithHash
a1
=
new
AuthTimeWithHash
(
client
,
server
,
time
(
0
),
0
,
"1111111111111111"
);
AuthTimeWithHash
a2
=
new
AuthTimeWithHash
(
client
,
server
,
time
(
0
),
0
,
"2222222222222222"
);
KerberosTime
now
=
new
KerberosTime
(
time
(
0
)*
1000L
);
// When all new styles, must exact match
ReplayCache
cache
=
ReplayCache
.
getInstance
(
"dfl:./c1"
);
cache
.
checkAndStore
(
now
,
a1
);
cache
.
checkAndStore
(
now
,
a2
);
// When only old style in cache, partial match
cache
=
ReplayCache
.
getInstance
(
"dfl:./c2"
);
cache
.
checkAndStore
(
now
,
a1
);
// A small surgery to remove the new style from the cache file
SeekableByteChannel
ch
=
Files
.
newByteChannel
(
Paths
.
get
(
"c2"
),
StandardOpenOption
.
WRITE
,
StandardOpenOption
.
READ
);
ch
.
position
(
6
);
ch
.
write
(
ByteBuffer
.
wrap
(
a1
.
encode
(
false
)));
ch
.
truncate
(
ch
.
position
());
ch
.
close
();
try
{
cache
.
checkAndStore
(
now
,
a2
);
throw
new
Exception
();
}
catch
(
KrbException
ke
)
{
// Correct
System
.
out
.
println
(
ke
);
}
}
private
static
int
time
(
int
x
)
{
return
(
int
)(
System
.
currentTimeMillis
()/
1000
)
+
x
;
}
}
test/sun/security/krb5/auto/ReplayCache.java
→
test/sun/security/krb5/auto/ReplayCache
Test
.java
浏览文件 @
1c14b0a7
...
...
@@ -23,38 +23,47 @@
/*
* @test
* @bug 7118809
* @run main/othervm ReplayCache
* @bug 7118809 8001326
* @run main/othervm ReplayCacheTest jvm
* @run main/othervm ReplayCacheTest dfl
* @summary rcache deadlock
*/
import
java.io.File
;
import
org.ietf.jgss.GSSException
;
import
sun.security.jgss.GSSUtil
;
import
sun.security.krb5.KrbException
;
import
sun.security.krb5.internal.Krb5
;
public
class
ReplayCache
{
public
class
ReplayCache
Test
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
OneKDC
(
null
).
writeJAASConf
();
new
OneKDC
(
null
);
if
(
args
[
0
].
equals
(
"dfl"
))
{
// Store file in scratch directory
args
[
0
]
=
"dfl:"
+
System
.
getProperty
(
"user.dir"
)
+
File
.
separator
;
System
.
setProperty
(
"sun.security.krb5.rcache"
,
args
[
0
]);
}
Context
c
,
s
;
c
=
Context
.
from
JAAS
(
"client"
);
s
=
Context
.
from
JAAS
(
"server"
);
c
=
Context
.
from
UserPass
(
OneKDC
.
USER
,
OneKDC
.
PASS
,
false
);
s
=
Context
.
from
UserKtab
(
OneKDC
.
SERVER
,
OneKDC
.
KTAB
,
true
);
c
.
startAsClient
(
OneKDC
.
SERVER
,
GSSUtil
.
GSS_KRB5_MECH_OID
);
s
.
startAsServer
(
GSSUtil
.
GSS_KRB5_MECH_OID
);
byte
[]
first
=
c
.
take
(
new
byte
[
0
]);
s
.
take
(
first
);
c
.
take
(
s
.
take
(
first
)
);
s
.
startAsServer
(
GSSUtil
.
GSS_KRB5_MECH_OID
);
try
{
s
.
take
(
first
);
// Replay the last
token
sent
s
.
take
(
first
);
// Replay the last
apreq
sent
throw
new
Exception
(
"This method should fail"
);
}
catch
(
GSSException
gsse
)
{
gsse
.
printStackTrace
();
KrbException
ke
=
(
KrbException
)
gsse
.
getCause
();
if
(
ke
.
returnCode
()
!=
Krb5
.
KRB_AP_ERR_REPEAT
)
{
throw
gsse
;
...
...
test/sun/security/krb5/auto/ReplayCacheTestProc.java
0 → 100644
浏览文件 @
1c14b0a7
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 7152176
* @summary More krb5 tests
* @library ../../../../java/security/testlibrary/
* @compile -XDignore.symbol.file ReplayCacheTestProc.java
* @run main/othervm/timeout=100 ReplayCacheTestProc
*/
import
java.io.*
;
import
java.nio.BufferUnderflowException
;
import
java.nio.channels.SeekableByteChannel
;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.nio.file.StandardCopyOption
;
import
java.nio.file.StandardOpenOption
;
import
java.security.MessageDigest
;
import
java.util.*
;
import
sun.security.jgss.GSSUtil
;
import
sun.security.krb5.internal.APReq
;
import
sun.security.krb5.internal.rcache.AuthTime
;
// This test runs multiple acceptor Procs to mimin AP-REQ replays.
public
class
ReplayCacheTestProc
{
private
static
Proc
[]
ps
;
private
static
Proc
pc
;
private
static
List
<
Req
>
reqs
=
new
ArrayList
<>();
private
static
String
HOST
=
"localhost"
;
// Where should the rcache be saved. It seems KRB5RCACHEDIR is not
// recognized on Solaris. Maybe version too low? I see 1.6.
private
static
String
cwd
=
System
.
getProperty
(
"os.name"
).
startsWith
(
"SunOS"
)
?
"/var/krb5/rcache/"
:
System
.
getProperty
(
"user.dir"
);
private
static
int
uid
;
public
static
void
main0
(
String
[]
args
)
throws
Exception
{
System
.
setProperty
(
"java.security.krb5.conf"
,
OneKDC
.
KRB5_CONF
);
if
(
args
.
length
==
0
)
{
// The controller
int
ns
=
5
;
// number of servers
int
nu
=
5
;
// number of users
int
nx
=
50
;
// number of experiments
int
np
=
5
;
// number of peers (services)
int
mode
=
0
;
// native(1), random(0), java(-1)
boolean
random
=
true
;
// random experiments choreograph
try
{
Class
<?>
clazz
=
Class
.
forName
(
"com.sun.security.auth.module.UnixSystem"
);
uid
=
(
int
)(
long
)(
Long
)
clazz
.
getMethod
(
"getUid"
).
invoke
(
clazz
.
newInstance
());
}
catch
(
Exception
e
)
{
uid
=
-
1
;
}
KDC
kdc
=
KDC
.
create
(
OneKDC
.
REALM
,
HOST
,
0
,
true
);
for
(
int
i
=
0
;
i
<
nu
;
i
++)
{
kdc
.
addPrincipal
(
user
(
i
),
OneKDC
.
PASS
);
}
kdc
.
addPrincipalRandKey
(
"krbtgt/"
+
OneKDC
.
REALM
);
for
(
int
i
=
0
;
i
<
np
;
i
++)
{
kdc
.
addPrincipalRandKey
(
peer
(
i
));
}
kdc
.
writeKtab
(
OneKDC
.
KTAB
);
KDC
.
saveConfig
(
OneKDC
.
KRB5_CONF
,
kdc
);
pc
=
Proc
.
create
(
"ReplayCacheTestProc"
).
debug
(
"C"
)
.
args
(
"client"
)
.
start
();
ps
=
new
Proc
[
ns
];
Ex
[]
result
=
new
Ex
[
nx
];
if
(!
random
)
{
// 2 experiments, 2 server, 1 peer, 1 user
nx
=
2
;
ns
=
2
;
np
=
1
;
nu
=
1
;
// Creates reqs from user# to peer#
req
(
0
,
0
);
// Creates server#
ps
[
0
]
=
ns
(
0
);
ps
[
1
]
=
js
(
1
);
// Runs ex# using req# to server# with expected result
result
[
0
]
=
round
(
0
,
0
,
0
,
true
);
result
[
1
]
=
round
(
1
,
0
,
1
,
false
);
}
else
{
Random
r
=
new
Random
();
for
(
int
i
=
0
;
i
<
ns
;
i
++)
{
boolean
useNative
=
(
mode
==
1
)
?
true
:
(
mode
==
-
1
?
false
:
r
.
nextBoolean
());
ps
[
i
]
=
useNative
?
ns
(
i
):
js
(
i
);
}
for
(
int
i
=
0
;
i
<
nx
;
i
++)
{
result
[
i
]
=
new
Ex
();
int
old
;
// which req to send
boolean
expected
;
if
(
reqs
.
isEmpty
()
||
r
.
nextBoolean
())
{
Proc
.
d
(
"Console get new AP-REQ"
);
old
=
req
(
r
.
nextInt
(
nu
),
r
.
nextInt
(
np
));
expected
=
true
;
}
else
{
Proc
.
d
(
"Console resue old"
);
old
=
r
.
nextInt
(
reqs
.
size
());
expected
=
false
;
}
int
s
=
r
.
nextInt
(
ns
);
Proc
.
d
(
"Console send to "
+
s
);
result
[
i
]
=
round
(
i
,
old
,
s
,
expected
);
Proc
.
d
(
"Console sees "
+
result
[
i
].
actual
);
}
}
pc
.
println
(
"END"
);
for
(
int
i
=
0
;
i
<
ns
;
i
++)
{
ps
[
i
].
println
(
"END"
);
}
System
.
out
.
println
(
"Result\n======"
);
boolean
finalOut
=
true
;
for
(
int
i
=
0
;
i
<
nx
;
i
++)
{
boolean
out
=
result
[
i
].
expected
==
result
[
i
].
actual
;
finalOut
&=
out
;
System
.
out
.
printf
(
"%3d: %s (%2d): u%d h%d %s %s %s %2d\n"
,
i
,
result
[
i
].
expected
?
"----"
:
" "
,
result
[
i
].
old
,
result
[
i
].
user
,
result
[
i
].
peer
,
result
[
i
].
server
,
result
[
i
].
actual
?
"Good"
:
"Bad "
,
out
?
" "
:
"xxx"
,
result
[
i
].
csize
);
}
if
(!
finalOut
)
throw
new
Exception
();
}
else
if
(
args
[
0
].
equals
(
"client"
))
{
while
(
true
)
{
String
title
=
Proc
.
textIn
();
Proc
.
d
(
"Client see "
+
title
);
if
(
title
.
equals
(
"END"
))
break
;
String
[]
cas
=
title
.
split
(
" "
);
Context
c
=
Context
.
fromUserPass
(
cas
[
0
],
OneKDC
.
PASS
,
false
);
c
.
startAsClient
(
cas
[
1
],
GSSUtil
.
GSS_KRB5_MECH_OID
);
c
.
x
().
requestCredDeleg
(
true
);
byte
[]
token
=
c
.
take
(
new
byte
[
0
]);
Proc
.
d
(
"Client AP-REQ generated"
);
Proc
.
binOut
(
token
);
}
}
else
{
Proc
.
d
(
"Server start"
);
Context
s
=
Context
.
fromUserKtab
(
"*"
,
OneKDC
.
KTAB
,
true
);
Proc
.
d
(
"Server login"
);
while
(
true
)
{
String
title
=
Proc
.
textIn
();
Proc
.
d
(
"Server "
+
args
[
0
]
+
" sees "
+
title
);
if
(
title
.
equals
(
"END"
))
break
;
s
.
startAsServer
(
GSSUtil
.
GSS_KRB5_MECH_OID
);
byte
[]
token
=
Proc
.
binIn
();
try
{
s
.
take
(
token
);
Proc
.
textOut
(
"true"
);
Proc
.
d
(
args
[
0
]
+
" Good"
);
}
catch
(
Exception
e
)
{
Proc
.
textOut
(
"false"
);
Proc
.
d
(
args
[
0
]
+
" Bad"
);
}
}
}
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
try
{
main0
(
args
);
}
catch
(
Exception
e
)
{
Proc
.
d
(
e
);
throw
e
;
}
}
// returns the user name
private
static
String
user
(
int
p
)
{
return
"USER"
+
p
;
}
// returns the peer name
private
static
String
peer
(
int
p
)
{
return
"host"
+
p
+
"/"
+
HOST
;
}
// returns the dfl name for a host
private
static
String
dfl
(
int
p
)
{
return
cwd
+
"host"
+
p
+
(
uid
==
-
1
?
""
:
(
"_"
+
uid
));
}
// generates an ap-req and save into reqs, returns the index
private
static
int
req
(
int
user
,
int
peer
)
throws
Exception
{
pc
.
println
(
user
(
user
)
+
" "
+
peer
(
peer
));
Req
req
=
new
Req
(
user
,
peer
,
pc
.
readData
());
reqs
.
add
(
req
);
return
reqs
.
size
()
-
1
;
}
// carries out a round of experiment
// i: ex#, old: which req, server: which server, expected: result?
private
static
Ex
round
(
int
i
,
int
old
,
int
server
,
boolean
expected
)
throws
Exception
{
ps
[
server
].
println
(
"TEST"
);
ps
[
server
].
println
(
reqs
.
get
(
old
).
msg
);
String
reply
=
ps
[
server
].
readData
();
Ex
result
=
new
Ex
();
result
.
i
=
i
;
result
.
expected
=
expected
;
result
.
server
=
ps
[
server
].
debug
();
result
.
actual
=
Boolean
.
valueOf
(
reply
);
result
.
user
=
reqs
.
get
(
old
).
user
;
result
.
peer
=
reqs
.
get
(
old
).
peer
;
result
.
old
=
old
;
result
.
csize
=
csize
(
result
.
peer
);
result
.
hash
=
hash
(
reqs
.
get
(
old
).
msg
);
if
(
new
File
(
dfl
(
result
.
peer
)).
exists
())
{
Files
.
copy
(
Paths
.
get
(
dfl
(
result
.
peer
)),
Paths
.
get
(
String
.
format
(
"%03d-USER%d-host%d-%s-%s"
,
i
,
result
.
user
,
result
.
peer
,
result
.
server
,
result
.
actual
)
+
"-"
+
result
.
hash
),
StandardCopyOption
.
COPY_ATTRIBUTES
);
}
return
result
;
}
// create a native server
private
static
Proc
ns
(
int
i
)
throws
Exception
{
return
Proc
.
create
(
"ReplayCacheTestProc"
)
.
args
(
"N"
+
i
)
.
env
(
"KRB5_CONFIG"
,
OneKDC
.
KRB5_CONF
)
.
env
(
"KRB5_KTNAME"
,
OneKDC
.
KTAB
)
.
env
(
"KRB5RCACHEDIR"
,
cwd
)
.
prop
(
"sun.security.jgss.native"
,
"true"
)
.
prop
(
"javax.security.auth.useSubjectCredsOnly"
,
"false"
)
.
prop
(
"sun.security.nativegss.debug"
,
"true"
)
.
debug
(
"N"
+
i
)
.
start
();
}
// creates a java server
private
static
Proc
js
(
int
i
)
throws
Exception
{
return
Proc
.
create
(
"ReplayCacheTestProc"
)
.
debug
(
"S"
+
i
)
.
args
(
"S"
+
i
)
.
prop
(
"sun.security.krb5.rcache"
,
"dfl"
)
.
prop
(
"java.io.tmpdir"
,
cwd
)
.
start
();
}
// generates hash of authenticator inside ap-req inside initsectoken
private
static
String
hash
(
String
req
)
throws
Exception
{
byte
[]
data
=
Base64
.
getDecoder
().
decode
(
req
);
data
=
Arrays
.
copyOfRange
(
data
,
17
,
data
.
length
);
byte
[]
hash
=
MessageDigest
.
getInstance
(
"MD5"
).
digest
(
new
APReq
(
data
).
authenticator
.
getBytes
());
char
[]
h
=
new
char
[
hash
.
length
*
2
];
char
[]
hexConst
=
"0123456789ABCDEF"
.
toCharArray
();
for
(
int
i
=
0
;
i
<
hash
.
length
;
i
++)
{
h
[
2
*
i
]
=
hexConst
[(
hash
[
i
]&
0xff
)>>
4
];
h
[
2
*
i
+
1
]
=
hexConst
[
hash
[
i
]&
0xf
];
}
return
new
String
(
h
);
}
// return size of dfl file, excluding the null hash ones
private
static
int
csize
(
int
p
)
throws
Exception
{
try
(
SeekableByteChannel
chan
=
Files
.
newByteChannel
(
Paths
.
get
(
dfl
(
p
)),
StandardOpenOption
.
READ
))
{
chan
.
position
(
6
);
int
cc
=
0
;
while
(
true
)
{
try
{
if
(
AuthTime
.
readFrom
(
chan
)
!=
null
)
cc
++;
}
catch
(
BufferUnderflowException
e
)
{
break
;
}
}
return
cc
;
}
catch
(
IOException
ioe
)
{
return
0
;
}
}
// models an experiement
private
static
class
Ex
{
int
i
;
// #
boolean
expected
;
// expected result
boolean
actual
;
// actual output
int
old
;
// which ap-req to send
String
server
;
// which server to send to
String
hash
;
// the hash of req
int
user
;
// which initiator
int
peer
;
// which acceptor
int
csize
;
// size of rcache after test
}
// models a saved ap-req msg
private
static
class
Req
{
String
msg
;
// based64-ed req
int
user
;
// which initiator
int
peer
;
// which accceptor
Req
(
int
user
,
int
peer
,
String
msg
)
{
this
.
msg
=
msg
;
this
.
user
=
user
;
this
.
peer
=
peer
;
}
}
}
test/sun/security/krb5/ccache/EmptyCC.java
浏览文件 @
1c14b0a7
...
...
@@ -26,15 +26,12 @@
* @bug 7158329
* @bug 8001208
* @summary NPE in sun.security.krb5.Credentials.acquireDefaultCreds()
* @library ../../../../java/security/testlibrary/
* @compile -XDignore.symbol.file EmptyCC.java
* @run main EmptyCC tmpcc
* @run main EmptyCC FILE:tmpcc
*/
import
java.io.File
;
import
java.io.InputStream
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
sun.security.krb5.Credentials
;
import
sun.security.krb5.PrincipalName
;
import
sun.security.krb5.internal.ccache.CredentialsCache
;
...
...
@@ -48,32 +45,9 @@ public class EmptyCC {
// Main process, write the ccache and launch sub process
CredentialsCache
cache
=
CredentialsCache
.
create
(
pn
,
ccache
);
cache
.
save
();
// java -cp $test.classes EmptyCC readcc
ProcessBuilder
pb
=
new
ProcessBuilder
(
new
File
(
new
File
(
System
.
getProperty
(
"java.home"
),
"bin"
),
"java"
).
getPath
(),
"-cp"
,
System
.
getProperty
(
"test.classes"
),
"EmptyCC"
,
ccache
,
"readcc"
);
pb
.
environment
().
put
(
"KRB5CCNAME"
,
ccache
);
pb
.
redirectErrorStream
(
true
);
Process
p
=
pb
.
start
();
try
(
InputStream
ins
=
p
.
getInputStream
())
{
byte
[]
buf
=
new
byte
[
8192
];
int
n
;
while
((
n
=
ins
.
read
(
buf
))
>
0
)
{
System
.
out
.
write
(
buf
,
0
,
n
);
}
}
if
(
p
.
waitFor
()
!=
0
)
{
throw
new
Exception
(
"Test failed"
);
}
Proc
p
=
Proc
.
create
(
"EmptyCC"
).
args
(
ccache
,
"readcc"
)
.
env
(
"KRB5CCNAME"
,
ccache
).
start
();
p
.
waitFor
();
}
else
{
// Sub process, read the ccache
String
cc
=
System
.
getenv
(
"KRB5CCNAME"
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录