--- a/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java Tue Jan 08 13:06:22 2013 -0800
@@ -86,7 +86,7 @@
* For the context acceptor to call. It reads the bytes out of an
* InputStream and constructs an InitSecContextToken with them.
*/
- InitSecContextToken(Krb5Context context, EncryptionKey[] keys,
+ InitSecContextToken(Krb5Context context, Krb5AcceptCredential cred,
InputStream is)
throws IOException, GSSException, KrbException {
@@ -105,7 +105,7 @@
if (context.getChannelBinding() != null) {
addr = context.getChannelBinding().getInitiatorAddress();
}
- apReq = new KrbApReq(apReqBytes, keys, addr);
+ apReq = new KrbApReq(apReqBytes, cred, addr);
//debug("\nReceived AP-REQ and authenticated it.\n");
EncryptionKey sessionKey = apReq.getCreds().getSessionKey();
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java Tue Jan 08 13:06:22 2013 -0800
@@ -45,13 +45,10 @@
public class Krb5AcceptCredential
implements Krb5CredElement {
- private static final long serialVersionUID = 7714332137352567952L;
-
- private Krb5NameElement name;
+ private final Krb5NameElement name;
+ private final ServiceCreds screds;
- private Krb5Util.ServiceCreds screds;
-
- private Krb5AcceptCredential(Krb5NameElement name, Krb5Util.ServiceCreds creds) {
+ private Krb5AcceptCredential(Krb5NameElement name, ServiceCreds creds) {
/*
* Initialize this instance with the data from the acquired
* KerberosKey. This class needs to be a KerberosKey too
@@ -69,11 +66,11 @@
name.getKrb5PrincipalName().getName());
final AccessControlContext acc = AccessController.getContext();
- Krb5Util.ServiceCreds creds = null;
+ ServiceCreds creds = null;
try {
creds = AccessController.doPrivileged(
- new PrivilegedExceptionAction<Krb5Util.ServiceCreds>() {
- public Krb5Util.ServiceCreds run() throws Exception {
+ new PrivilegedExceptionAction<ServiceCreds>() {
+ public ServiceCreds run() throws Exception {
return Krb5Util.getServiceCreds(
caller == GSSCaller.CALLER_UNKNOWN ? GSSCaller.CALLER_ACCEPT: caller,
serverPrinc, acc);
@@ -92,8 +89,10 @@
if (name == null) {
String fullName = creds.getName();
- name = Krb5NameElement.getInstance(fullName,
+ if (fullName != null) {
+ name = Krb5NameElement.getInstance(fullName,
Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL);
+ }
}
return new Krb5AcceptCredential(name, creds);
@@ -153,8 +152,8 @@
return Krb5MechFactory.PROVIDER;
}
- EncryptionKey[] getKrb5EncryptionKeys() {
- return screds.getEKeys();
+ public EncryptionKey[] getKrb5EncryptionKeys(PrincipalName princ) {
+ return screds.getEKeys(princ);
}
/**
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java Tue Jan 08 13:06:22 2013 -0800
@@ -818,16 +818,23 @@
}
myName = (Krb5NameElement) myCred.getName();
- checkPermission(myName.getKrb5PrincipalName().getName(),
- "accept");
-
- EncryptionKey[] secretKeys =
- ((Krb5AcceptCredential) myCred).getKrb5EncryptionKeys();
+ // If there is already a bound name, check now
+ if (myName != null) {
+ Krb5MechFactory.checkAcceptCredPermission(myName, myName);
+ }
InitSecContextToken token = new InitSecContextToken(this,
- secretKeys, is);
+ (Krb5AcceptCredential) myCred, is);
PrincipalName clientName = token.getKrbApReq().getClient();
peerName = Krb5NameElement.getInstance(clientName);
+
+ // If unbound, check after the bound name is found
+ if (myName == null) {
+ myName = Krb5NameElement.getInstance(
+ token.getKrbApReq().getCreds().getServer());
+ Krb5MechFactory.checkAcceptCredPermission(myName, myName);
+ }
+
if (getMutualAuthState()) {
retVal = new AcceptSecContextToken(this,
token.getKrbApReq()).encode();
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java Tue Jan 08 13:06:22 2013 -0800
@@ -158,7 +158,7 @@
public static void checkAcceptCredPermission(Krb5NameElement name,
GSSNameSpi originalName) {
SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
+ if (sm != null && name != null) {
ServicePermission perm = new ServicePermission
(name.getKrb5PrincipalName().getName(), "accept");
try {
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java Tue Jan 08 13:06:22 2013 -0800
@@ -187,114 +187,6 @@
}
/**
- * Credentials of a service, the private secret to authenticate its
- * identity, which can be:
- * 1. Some KerberosKeys (generated from password)
- * 2. A KeyTab (for a typical service)
- * 3. A TGT (for S4U2proxy extension)
- *
- * Note that some creds can coexist. For example, a user2user service
- * can use its keytab (or keys) if the client can successfully obtain a
- * normal service ticket, otherwise, it can uses the TGT (actually, the
- * session key of the TGT) if the client can only acquire a service ticket
- * of ENC-TKT-IN-SKEY style.
- */
- public static class ServiceCreds {
- private KerberosPrincipal kp;
- private List<KeyTab> ktabs;
- private List<KerberosKey> kk;
- private Subject subj;
- private KerberosTicket tgt;
-
- private static ServiceCreds getInstance(
- Subject subj, String serverPrincipal) {
-
- ServiceCreds sc = new ServiceCreds();
- sc.subj = subj;
-
- for (KerberosPrincipal p: subj.getPrincipals(KerberosPrincipal.class)) {
- if (serverPrincipal == null ||
- p.getName().equals(serverPrincipal)) {
- sc.kp = p;
- serverPrincipal = p.getName();
- break;
- }
- }
- if (sc.kp == null) {
- // Compatibility with old behavior: even when there is no
- // KerberosPrincipal, we can find one from KerberosKeys
- List<KerberosKey> keys = SubjectComber.findMany(
- subj, serverPrincipal, null, KerberosKey.class);
- if (!keys.isEmpty()) {
- sc.kp = keys.get(0).getPrincipal();
- serverPrincipal = sc.kp.getName();
- if (DEBUG) {
- System.out.println(">>> ServiceCreds: no kp?"
- + " find one from kk: " + serverPrincipal);
- }
- } else {
- return null;
- }
- }
- sc.ktabs = SubjectComber.findMany(
- subj, null, null, KeyTab.class);
- sc.kk = SubjectComber.findMany(
- subj, serverPrincipal, null, KerberosKey.class);
- sc.tgt = SubjectComber.find(
- subj, null, serverPrincipal, KerberosTicket.class);
- if (sc.ktabs.isEmpty() && sc.kk.isEmpty() && sc.tgt == null) {
- return null;
- }
- return sc;
- }
-
- public String getName() {
- return kp.getName();
- }
-
- public KerberosKey[] getKKeys() {
- List<KerberosKey> keys = new ArrayList<>();
- for (KerberosKey k: kk) {
- keys.add(k);
- }
- for (KeyTab ktab: ktabs) {
- for (KerberosKey k: ktab.getKeys(kp)) {
- keys.add(k);
- }
- }
- return keys.toArray(new KerberosKey[keys.size()]);
- }
-
- public EncryptionKey[] getEKeys() {
- KerberosKey[] kkeys = getKKeys();
- EncryptionKey[] ekeys = new EncryptionKey[kkeys.length];
- for (int i=0; i<ekeys.length; i++) {
- ekeys[i] = new EncryptionKey(
- kkeys[i].getEncoded(), kkeys[i].getKeyType(),
- new Integer(kkeys[i].getVersionNumber()));
- }
- return ekeys;
- }
-
- public Credentials getInitCred() {
- if (tgt == null) {
- return null;
- }
- try {
- return ticketToCreds(tgt);
- } catch (KrbException | IOException e) {
- return null;
- }
- }
-
- public void destroy() {
- kp = null;
- ktabs = null;
- kk = null;
- tgt = null;
- }
- }
- /**
* Retrieves the ServiceCreds for the specified server principal from
* the Subject in the specified AccessControlContext. If not found, and if
* useSubjectCredsOnly is false, then obtain from a LoginContext.
@@ -361,5 +253,4 @@
return KerberosSecrets.getJavaxSecurityAuthKerberosAccess().
keyTabGetEncryptionKeys(ktab, cname);
}
-
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/ServiceCreds.java Tue Jan 08 13:06:22 2013 -0800
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.jgss.krb5;
+
+import javax.security.auth.kerberos.KerberosTicket;
+import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KeyTab;
+import javax.security.auth.Subject;
+
+import sun.security.krb5.Credentials;
+import sun.security.krb5.EncryptionKey;
+import sun.security.krb5.KrbException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import sun.security.krb5.*;
+import sun.security.krb5.internal.Krb5;
+
+/**
+ * Credentials of a kerberos acceptor. A KerberosPrincipal object (kp) is
+ * the principal. It can be specified as the serverPrincipal argument
+ * in the getInstance() method, or uses only KerberosPrincipal in the subject.
+ * Otherwise, the creds object is unbound and kp is null.
+ *
+ * The class also encapsulates various secrets, which can be:
+ *
+ * 1. Some KerberosKeys (generated from password)
+ * 2. Some KeyTabs (for a typical service based on keytabs)
+ * 3. A TGT (for S4U2proxy extension or user2user)
+ *
+ * Note that some secrets can coexist. For example, a user2user service
+ * can use its keytab (or keys) if the client can successfully obtain a
+ * normal service ticket, or it can use the TGT (actually, the session key
+ * of the TGT) if the client can only acquire a service ticket
+ * of ENC-TKT-IN-SKEY style.
+ *
+ * @since 1.8
+ */
+public final class ServiceCreds {
+ // The principal, or null if unbound
+ private KerberosPrincipal kp;
+
+ // All principals in the subject's princ set
+ private Set<KerberosPrincipal> allPrincs;
+
+ // All private credentials that can be used
+ private List<KeyTab> ktabs;
+ private List<KerberosKey> kk;
+ private KerberosTicket tgt;
+
+ private boolean destroyed;
+
+ private ServiceCreds() {
+ // Make sure this class cannot be instantiated externally.
+ }
+
+ /**
+ * Creates a ServiceCreds object based on info in a Subject for
+ * a given principal name (if specified).
+ * @return the object, or null if there is no private creds for it
+ */
+ public static ServiceCreds getInstance(
+ Subject subj, String serverPrincipal) {
+
+ ServiceCreds sc = new ServiceCreds();
+
+ sc.allPrincs =
+ subj.getPrincipals(KerberosPrincipal.class);
+
+ // Compatibility. A key implies its own principal
+ for (KerberosKey key: SubjectComber.findMany(
+ subj, serverPrincipal, null, KerberosKey.class)) {
+ sc.allPrincs.add(key.getPrincipal());
+ }
+
+ if (serverPrincipal != null) { // A named principal
+ sc.kp = new KerberosPrincipal(serverPrincipal);
+ } else {
+ if (sc.allPrincs.size() == 1) { // choose the only one
+ sc.kp = sc.allPrincs.iterator().next();
+ serverPrincipal = sc.kp.getName();
+ }
+ }
+
+ sc.ktabs = SubjectComber.findMany(
+ subj, serverPrincipal, null, KeyTab.class);
+ sc.kk = SubjectComber.findMany(
+ subj, serverPrincipal, null, KerberosKey.class);
+ sc.tgt = SubjectComber.find(
+ subj, null, serverPrincipal, KerberosTicket.class);
+ if (sc.ktabs.isEmpty() && sc.kk.isEmpty() && sc.tgt == null) {
+ return null;
+ }
+
+ sc.destroyed = false;
+
+ return sc;
+ }
+
+ // can be null
+ public String getName() {
+ if (destroyed) {
+ throw new IllegalStateException("This object is destroyed");
+ }
+ return kp == null ? null : kp.getName();
+ }
+
+ /**
+ * Gets keys for someone unknown.
+ * Used by TLS or as a fallback in getEKeys(). Can still return an
+ * empty array.
+ */
+ public KerberosKey[] getKKeys() {
+ if (destroyed) {
+ throw new IllegalStateException("This object is destroyed");
+ }
+ if (kp != null) {
+ return getKKeys(kp);
+ } else if (!allPrincs.isEmpty()) {
+ return getKKeys(allPrincs.iterator().next());
+ }
+ return new KerberosKey[0];
+ }
+
+ /**
+ * Get kkeys for a principal,
+ * @param princ the target name initiator requests. Not null.
+ * @return keys for the princ, never null, might be empty
+ */
+ private KerberosKey[] getKKeys(KerberosPrincipal princ) {
+ ArrayList<KerberosKey> keys = new ArrayList<>();
+ if (kp != null && !princ.equals(kp)) {
+ return new KerberosKey[0]; // Not me
+ }
+ if (!allPrincs.contains(princ)) {
+ return new KerberosKey[0]; // Not someone I know, This check
+ // is necessary but a KeyTab has
+ // no principal name recorded.
+ }
+ for (KerberosKey k: kk) {
+ if (k.getPrincipal().equals(princ)) {
+ keys.add(k);
+ }
+ }
+ for (KeyTab ktab: ktabs) {
+ for (KerberosKey k: ktab.getKeys(princ)) {
+ keys.add(k);
+ }
+ }
+ return keys.toArray(new KerberosKey[keys.size()]);
+ }
+
+ /**
+ * Gets EKeys for a principal.
+ * @param princ the target name initiator requests. Not null.
+ * @return keys for the princ, never null, might be empty
+ */
+ public EncryptionKey[] getEKeys(PrincipalName princ) {
+ if (destroyed) {
+ throw new IllegalStateException("This object is destroyed");
+ }
+ KerberosKey[] kkeys = getKKeys(new KerberosPrincipal(princ.getName()));
+ if (kkeys.length == 0) {
+ // Note: old JDK does not perform real name checking. If the
+ // acceptor starts by name A but initiator requests for B,
+ // as long as their keys match (i.e. A's keys can decrypt B's
+ // service ticket), the authentication is OK. There are real
+ // customers depending on this to use different names for a
+ // single service.
+ kkeys = getKKeys();
+ }
+ EncryptionKey[] ekeys = new EncryptionKey[kkeys.length];
+ for (int i=0; i<ekeys.length; i++) {
+ ekeys[i] = new EncryptionKey(
+ kkeys[i].getEncoded(), kkeys[i].getKeyType(),
+ new Integer(kkeys[i].getVersionNumber()));
+ }
+ return ekeys;
+ }
+
+ public Credentials getInitCred() {
+ if (destroyed) {
+ throw new IllegalStateException("This object is destroyed");
+ }
+ if (tgt == null) {
+ return null;
+ }
+ try {
+ return Krb5Util.ticketToCreds(tgt);
+ } catch (KrbException | IOException e) {
+ return null;
+ }
+ }
+
+ public void destroy() {
+ // Do not wipe out real keys because they are references to the
+ // priv creds in subject. Just make it useless.
+ destroyed = true;
+ kp = null;
+ ktabs.clear();
+ kk.clear();
+ tgt = null;
+ }
+}
--- a/jdk/src/share/classes/sun/security/jgss/krb5/SubjectComber.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/SubjectComber.java Tue Jan 08 13:06:22 2013 -0800
@@ -33,6 +33,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.kerberos.KeyTab;
/**
@@ -84,19 +85,37 @@
} else {
List<T> answer = (oneOnly ? null : new ArrayList<T>());
- if (credClass == KeyTab.class) { // Principal un-related
- // We are looking for credentials unrelated to serverPrincipal
- Iterator<T> iterator =
- subject.getPrivateCredentials(credClass).iterator();
- while (iterator.hasNext()) {
- T t = iterator.next();
- if (DEBUG) {
- System.out.println("Found " + credClass.getSimpleName());
+ if (credClass == KeyTab.class) {
+ // TODO: There is currently no good way to filter out keytabs
+ // not for serverPrincipal. We can only check the principal
+ // set. If the server is not there, we can be sure none of the
+ // keytabs should be used, otherwise, use all for safety.
+ boolean useAll = false;
+ if (serverPrincipal != null) {
+ for (KerberosPrincipal princ:
+ subject.getPrincipals(KerberosPrincipal.class)) {
+ if (princ.getName().equals(serverPrincipal)) {
+ useAll = true;
+ break;
+ }
}
- if (oneOnly) {
- return t;
- } else {
- answer.add(t);
+ } else {
+ useAll = true;
+ }
+ if (useAll) {
+ Iterator<KeyTab> iterator =
+ subject.getPrivateCredentials(KeyTab.class).iterator();
+ while (iterator.hasNext()) {
+ KeyTab t = iterator.next();
+ if (DEBUG) {
+ System.out.println("Found " + credClass.getSimpleName()
+ + " " + t);
+ }
+ if (oneOnly) {
+ return t;
+ } else {
+ answer.add(credClass.cast(t));
+ }
}
}
} else if (credClass == KerberosKey.class) {
@@ -114,11 +133,6 @@
if (oneOnly) {
return t;
} else {
- if (serverPrincipal == null) {
- // Record name so that keys returned will all
- // belong to the same principal
- serverPrincipal = name;
- }
answer.add(credClass.cast(t));
}
}
--- a/jdk/src/share/classes/sun/security/krb5/KrbApReq.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApReq.java Tue Jan 08 13:06:22 2013 -0800
@@ -34,6 +34,7 @@
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;
@@ -135,13 +136,13 @@
*/
// Used in InitSecContextToken (for AP_REQ and not TGS REQ)
public KrbApReq(byte[] message,
- EncryptionKey[] keys,
+ Krb5AcceptCredential cred,
InetAddress initiator)
throws KrbException, IOException {
obuf = message;
if (apReqMessg == null)
decode();
- authenticate(keys, initiator);
+ authenticate(cred, initiator);
}
/**
@@ -260,10 +261,11 @@
}
}
- private void authenticate(EncryptionKey[] keys, InetAddress initiator)
+ private void authenticate(Krb5AcceptCredential cred, InetAddress initiator)
throws KrbException, IOException {
int encPartKeyType = apReqMessg.ticket.encPart.getEType();
Integer kvno = apReqMessg.ticket.encPart.getKeyVersionNumber();
+ EncryptionKey[] keys = cred.getKrb5EncryptionKeys(apReqMessg.ticket.sname);
EncryptionKey dkey = EncryptionKey.findKey(encPartKeyType, kvno, keys);
if (dkey == null) {
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Tue Jan 08 13:06:22 2013 -0800
@@ -382,9 +382,15 @@
*/
public void addEntry(PrincipalName service, char[] psswd,
int kvno, boolean append) throws KrbException {
+ addEntry(service, service.getSalt(), psswd, kvno, append);
+ }
+
+ // Called by KDC test
+ public void addEntry(PrincipalName service, String salt, char[] psswd,
+ int kvno, boolean append) throws KrbException {
EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys(
- psswd, service.getSalt());
+ psswd, salt);
// There should be only one maximum KVNO value for all etypes, so that
// all added keys can have the same KVNO.
--- a/jdk/src/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java Tue Jan 08 13:06:22 2013 -0800
@@ -36,6 +36,7 @@
import sun.security.jgss.GSSCaller;
import sun.security.jgss.krb5.Krb5Util;
+import sun.security.jgss.krb5.ServiceCreds;
import sun.security.krb5.PrincipalName;
import sun.security.ssl.Krb5Proxy;
@@ -62,7 +63,7 @@
@Override
public SecretKey[] getServerKeys(AccessControlContext acc)
throws LoginException {
- Krb5Util.ServiceCreds serviceCreds =
+ ServiceCreds serviceCreds =
Krb5Util.getServiceCreds(GSSCaller.CALLER_SSL_SERVER, null, acc);
return serviceCreds != null ? serviceCreds.getKKeys() :
new KerberosKey[0];
--- a/jdk/src/windows/classes/sun/nio/ch/PipeImpl.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/src/windows/classes/sun/nio/ch/PipeImpl.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -72,67 +72,97 @@
private final SelectorProvider sp;
+ private IOException ioe = null;
+
private Initializer(SelectorProvider sp) {
this.sp = sp;
}
+ @Override
public Void run() throws IOException {
- ServerSocketChannel ssc = null;
- SocketChannel sc1 = null;
- SocketChannel sc2 = null;
-
- try {
- // loopback address
- InetAddress lb = InetAddress.getByName("127.0.0.1");
- assert(lb.isLoopbackAddress());
-
- // bind ServerSocketChannel to a port on the loopback address
- ssc = ServerSocketChannel.open();
- ssc.socket().bind(new InetSocketAddress(lb, 0));
-
- // Establish connection (assumes connections are eagerly
- // accepted)
- InetSocketAddress sa
- = new InetSocketAddress(lb, ssc.socket().getLocalPort());
- sc1 = SocketChannel.open(sa);
-
- ByteBuffer bb = ByteBuffer.allocate(8);
- long secret = rnd.nextLong();
- bb.putLong(secret).flip();
- sc1.write(bb);
-
- // Get a connection and verify it is legitimate
+ LoopbackConnector connector = new LoopbackConnector();
+ connector.run();
+ if (ioe instanceof ClosedByInterruptException) {
+ ioe = null;
+ Thread connThread = new Thread(connector) {
+ @Override
+ public void interrupt() {}
+ };
+ connThread.start();
for (;;) {
- sc2 = ssc.accept();
- bb.clear();
- sc2.read(bb);
- bb.rewind();
- if (bb.getLong() == secret)
+ try {
+ connThread.join();
break;
- sc2.close();
+ } catch (InterruptedException ex) {}
}
+ Thread.currentThread().interrupt();
+ }
+
+ if (ioe != null)
+ throw new IOException("Unable to establish loopback connection", ioe);
- // Create source and sink channels
- source = new SourceChannelImpl(sp, sc1);
- sink = new SinkChannelImpl(sp, sc2);
- } catch (IOException e) {
+ return null;
+ }
+
+ private class LoopbackConnector implements Runnable {
+
+ @Override
+ public void run() {
+ ServerSocketChannel ssc = null;
+ SocketChannel sc1 = null;
+ SocketChannel sc2 = null;
+
try {
- if (sc1 != null)
- sc1.close();
- if (sc2 != null)
+ // Loopback address
+ InetAddress lb = InetAddress.getByName("127.0.0.1");
+ assert(lb.isLoopbackAddress());
+ InetSocketAddress sa = null;
+ for(;;) {
+ // Bind ServerSocketChannel to a port on the loopback
+ // address
+ if (ssc == null || !ssc.isOpen()) {
+ ssc = ServerSocketChannel.open();
+ ssc.socket().bind(new InetSocketAddress(lb, 0));
+ sa = new InetSocketAddress(lb, ssc.socket().getLocalPort());
+ }
+
+ // Establish connection (assume connections are eagerly
+ // accepted)
+ sc1 = SocketChannel.open(sa);
+ ByteBuffer bb = ByteBuffer.allocate(8);
+ long secret = rnd.nextLong();
+ bb.putLong(secret).flip();
+ sc1.write(bb);
+
+ // Get a connection and verify it is legitimate
+ sc2 = ssc.accept();
+ bb.clear();
+ sc2.read(bb);
+ bb.rewind();
+ if (bb.getLong() == secret)
+ break;
sc2.close();
- } catch (IOException e2) { }
- IOException x = new IOException("Unable to establish"
- + " loopback connection");
- x.initCause(e);
- throw x;
- } finally {
- try {
- if (ssc != null)
- ssc.close();
- } catch (IOException e2) { }
+ sc1.close();
+ }
+
+ // Create source and sink channels
+ source = new SourceChannelImpl(sp, sc1);
+ sink = new SinkChannelImpl(sp, sc2);
+ } catch (IOException e) {
+ try {
+ if (sc1 != null)
+ sc1.close();
+ if (sc2 != null)
+ sc2.close();
+ } catch (IOException e2) {}
+ ioe = e;
+ } finally {
+ try {
+ if (ssc != null)
+ ssc.close();
+ } catch (IOException e2) {}
+ }
}
- return null;
}
}
@@ -144,7 +174,6 @@
}
}
-
public SourceChannel source() {
return source;
}
--- a/jdk/test/ProblemList.txt Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/ProblemList.txt Tue Jan 08 13:06:22 2013 -0800
@@ -1,6 +1,6 @@
###########################################################################
#
-# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 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
@@ -238,9 +238,6 @@
# 7146541
java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java linux-all
-# 7187882
-java/rmi/activation/checkusage/CheckUsage.java generic-all
-
# 7190106
java/rmi/reliability/benchmark/runRmiBench.sh generic-all
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/Pipe/PipeInterrupt.java Tue Jan 08 13:06:22 2013 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8002306
+ * @summary Ensure that a Pipe can open even if its thread has already
+ * been interrupted.
+ * @author Dan Xu
+ */
+
+import java.io.IOException;
+import java.nio.channels.Pipe;
+
+
+public class PipeInterrupt {
+
+ private Exception exc = null;
+
+ public static void main(String[] args) throws Exception {
+ PipeInterrupt instance = new PipeInterrupt();
+ instance.test();
+ }
+
+ public void test() throws Exception {
+
+ Thread tester = new Thread("PipeTester") {
+ private Pipe testPipe = null;
+
+ @Override
+ public void run() {
+ for (;;) {
+ boolean interrupted = this.isInterrupted();
+ try {
+ testPipe = Pipe.open();
+ close();
+ if (interrupted) {
+ if (!this.isInterrupted())
+ exc = new RuntimeException("interrupt status reset");
+ break;
+ }
+ } catch (IOException ioe) {
+ exc = ioe;
+ }
+ }
+ }
+
+ private void close() throws IOException {
+ if (testPipe != null) {
+ testPipe.sink().close();
+ testPipe.source().close();
+ }
+ }
+ };
+
+ tester.start();
+ Thread.sleep(200);
+ tester.interrupt();
+ tester.join();
+
+ if (exc != null)
+ throw exc;
+ }
+}
--- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -168,7 +168,7 @@
registering = null;
// Need to make sure that rmid goes away by itself
- Process rmidProcess = rmid.getVM();
+ JavaVM rmidProcess = rmid;
if (rmidProcess != null) {
try {
Runnable waitThread =
@@ -205,9 +205,9 @@
* class that waits for rmid to exit
*/
private static class ShutdownDetectThread implements Runnable {
- private Process rmidProcess = null;
+ private JavaVM rmidProcess = null;
- ShutdownDetectThread(Process rmidProcess) {
+ ShutdownDetectThread(JavaVM rmidProcess) {
this.rmidProcess = rmidProcess;
}
public void run() {
--- a/jdk/test/java/rmi/activation/checkusage/CheckUsage.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/java/rmi/activation/checkusage/CheckUsage.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -23,6 +23,7 @@
/* @test
* @bug 4259564
+ * @summary RMID's usage message is incomplete and inconsistent with other tools
*
* @library ../../testlibrary
* @build TestLibrary JavaVM
@@ -37,23 +38,16 @@
*/
public class CheckUsage {
public static void main(String[] args) {
-
- System.err.println("\nregression test for 4259564\n");
-
- JavaVM rmidVM = null;
-
try {
- // make sure the registry exits with a proper usage statement
ByteArrayOutputStream berr = new ByteArrayOutputStream();
- // run a VM to start the registry
- rmidVM = new JavaVM("sun.rmi.server.Activation", "", "foo",
- System.out, berr);
+ // create rmid with incorrect command line args
+ JavaVM rmidVM = new JavaVM("sun.rmi.server.Activation", "", "foo",
+ System.out, berr);
System.err.println("starting rmid");
- rmidVM.start();
- // wait for registry exit
- int rmidVMExitStatus = rmidVM.getVM().waitFor();
+ // run the subprocess and wait for it to exit
+ int rmidVMExitStatus = rmidVM.execute();
System.err.println("rmid exited with status: " +
rmidVMExitStatus);
@@ -66,12 +60,8 @@
} else {
System.err.println("test passed");
}
-
} catch (Exception e) {
TestLibrary.bomb(e);
- } finally {
- rmidVM.destroy();
- rmidVM = null;
}
}
}
--- a/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -76,8 +76,7 @@
}
System.err.println("starting " + utilityToStart);
- vm.start();
- vm.getVM().waitFor();
+ vm.execute();
} catch (Exception e) {
TestLibrary.bomb(e);
--- a/jdk/test/java/rmi/registry/checkusage/CheckUsage.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/java/rmi/registry/checkusage/CheckUsage.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -35,34 +35,21 @@
/**
* Make sure that the rmiregistry prints out a correct usage statement
- * when run with an incorrect command line; test written to conform to
- * new tighter bug fix/regression test guidelines.
+ * when run with an incorrect command line.
*/
public class CheckUsage {
public static void main(String[] args) {
- System.err.println("\nregression test for 4151966\n");
-
- JavaVM registryVM = null;
-
try {
- // make sure the registry exits with a proper usage statement
ByteArrayOutputStream berr = new ByteArrayOutputStream();
// run a VM to start the registry
- registryVM = new JavaVM("sun.rmi.registry.RegistryImpl",
- "", "foo",
- System.out, berr);
+ JavaVM registryVM = new JavaVM("sun.rmi.registry.RegistryImpl",
+ "", "foo",
+ System.out, berr);
System.err.println("starting registry");
- registryVM.start();
-
- // wait for registry exit
System.err.println(" registry exited with status: " +
- registryVM.getVM().waitFor());
- try {
- Thread.sleep(7000);
- } catch (InterruptedException ie) {
- }
+ registryVM.execute());
String usage = new String(berr.toByteArray());
@@ -75,9 +62,6 @@
}
} catch (Exception e) {
TestLibrary.bomb(e);
- } finally {
- registryVM.destroy();
- registryVM = null;
}
}
}
--- a/jdk/test/java/rmi/registry/reexport/Reexport.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/java/rmi/registry/reexport/Reexport.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -122,8 +122,7 @@
try {
JavaVM jvm = new JavaVM("RegistryRunner", "", Integer.toString(p));
jvm.start();
- Reexport.subreg = jvm.getVM();
-
+ Reexport.subreg = jvm;
} catch (IOException e) {
// one of these is summarily dropped, can't remember which one
System.out.println ("Test setup failed - cannot run rmiregistry");
@@ -135,7 +134,8 @@
} catch (Exception whatever) {
}
}
- private static Process subreg = null;
+
+ private static JavaVM subreg = null;
public static void killRegistry(int port) {
if (Reexport.subreg != null) {
--- a/jdk/test/java/rmi/testlibrary/JavaVM.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/java/rmi/testlibrary/JavaVM.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -41,6 +41,8 @@
private OutputStream outputStream = System.out;
private OutputStream errorStream = System.err;
private String policyFileName = null;
+ private StreamPipe outPipe;
+ private StreamPipe errPipe;
private static void mesg(Object mesg) {
System.err.println("JAVAVM: " + mesg.toString());
@@ -145,13 +147,12 @@
}
mesg("command = " + Arrays.asList(javaCommand).toString());
- System.err.println("");
vm = Runtime.getRuntime().exec(javaCommand);
/* output from the execed process may optionally be captured. */
- StreamPipe.plugTogether(vm.getInputStream(), this.outputStream);
- StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream);
+ outPipe = StreamPipe.plugTogether(vm.getInputStream(), this.outputStream);
+ errPipe = StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream);
}
public void destroy() {
@@ -161,7 +162,25 @@
vm = null;
}
- protected Process getVM() {
- return vm;
+ /**
+ * Waits for the subprocess to exit, joins the pipe threads to ensure that
+ * all output is collected, and returns its exit status.
+ */
+ public int waitFor() throws InterruptedException {
+ if (vm == null)
+ throw new IllegalStateException("can't wait for JavaVM that hasn't started");
+
+ int status = vm.waitFor();
+ outPipe.join();
+ errPipe.join();
+ return status;
+ }
+
+ /**
+ * Starts the subprocess, waits for it to exit, and returns its exit status.
+ */
+ public int execute() throws IOException, InterruptedException {
+ start();
+ return waitFor();
}
}
--- a/jdk/test/java/rmi/testlibrary/RMID.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/java/rmi/testlibrary/RMID.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -202,8 +202,6 @@
public void start(long waitTime) throws IOException {
- if (getVM() != null) return;
-
// if rmid is already running, then the test will fail with
// a well recognized exception (port already in use...).
--- a/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -114,6 +114,7 @@
equal = "=";
}
+ // create a client to tell checkFQDN what its rmi name is.
JavaVM jvm = new JavaVM("CheckFQDNClient",
propOption + property +
equal +
@@ -125,10 +126,7 @@
propertyBeingTested=property;
propertyBeingTestedValue=propertyValue;
- // create a client to tell checkFQDN what its rmi name is. */
- jvm.start();
-
- if (jvm.getVM().waitFor() != 0 ) {
+ if (jvm.execute() != 0) {
TestLibrary.bomb("Test failed, error in client.");
}
--- a/jdk/test/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -102,9 +102,8 @@
" -Drmi.registry.port=" +
registryPort,
"");
- jvm.start();
- if (jvm.getVM().waitFor() == 1 ) {
+ if (jvm.execute() != 0) {
TestLibrary.bomb("Client process failed");
}
}
--- a/jdk/test/sun/rmi/runtime/Log/4504153/Test4504153.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/sun/rmi/runtime/Log/4504153/Test4504153.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -48,8 +48,7 @@
ByteArrayOutputStream err = new ByteArrayOutputStream();
JavaVM vm = new JavaVM(StartRegistry.class.getName(),
"-Dsun.rmi.transport.logLevel=v", "", out, err);
- vm.start();
- vm.getVM().waitFor();
+ vm.execute();
String errString = err.toString();
--- a/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -65,8 +65,7 @@
JavaVM vm = new JavaVM(DoRMIStuff.class.getName(),
"-Djava.util.logging.config.file=" + loggingPropertiesFile,
"", out, err);
- vm.start();
- vm.getVM().waitFor();
+ vm.execute();
/*
* Verify that the subprocess had no System.out or System.err
--- a/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java Tue Jan 08 13:06:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -104,7 +104,7 @@
JavaVM jvm =
new JavaVM("sun.rmi.registry.RegistryImpl", "", Integer.toString(p));
jvm.start();
- DeadCachedConnection.subreg = jvm.getVM();
+ DeadCachedConnection.subreg = jvm;
} catch (IOException e) {
// one of these is summarily dropped, can't remember which one
@@ -117,7 +117,7 @@
} catch (Exception whatever) {
}
}
- private static Process subreg = null;
+ private static JavaVM subreg = null;
public static void killRegistry() {
if (DeadCachedConnection.subreg != null) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/ServiceCredsCombination.java Tue Jan 08 13:06:22 2013 -0800
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 8005447
+ * @compile -XDignore.symbol.file ServiceCredsCombination.java
+ * @run main ServiceCredsCombination
+ * @summary default principal can act as anyone
+ */
+
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KeyTab;
+import org.ietf.jgss.GSSCredential;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import sun.security.jgss.GSSUtil;
+
+public class ServiceCredsCombination {
+
+ public static void main(String[] args) throws Exception {
+ // pass
+ check("a", "a", princ("a"), key("a"));
+ check(null, "a", princ("a"), key("a"));
+ check("x", "NOCRED", princ("a"), key("a"));
+ // two pass
+ check("a", "a", princ("a"), key("a"), princ("b"), key("b"));
+ check("b", "b", princ("a"), key("a"), princ("b"), key("b"));
+ check(null, null, princ("a"), key("a"), princ("b"), key("b"));
+ check("x", "NOCRED", princ("a"), key("a"), princ("b"), key("b"));
+ // old ktab
+ check("b", "b", princ("b"), oldktab());
+ check("x", "NOCRED", princ("b"), oldktab());
+ check(null, "b", princ("b"), oldktab());
+ // Two old ktab
+ check("a", "a", princ("a"), princ("b"), oldktab(), oldktab());
+ check("b", "b", princ("a"), princ("b"), oldktab(), oldktab());
+ check(null, null, princ("a"), princ("b"), oldktab(), oldktab());
+ check("x", "NOCRED", princ("a"), princ("b"), oldktab(), oldktab());
+ // pass + old ktab
+ check("a", "a", princ("a"), princ("b"), key("a"), oldktab());
+ check("b", "b", princ("a"), princ("b"), key("a"), oldktab());
+ check(null, null, princ("a"), princ("b"), key("a"), oldktab());
+ check("x", "NOCRED", princ("a"), princ("b"), key("a"), oldktab());
+ // Compatibility, automatically add princ for keys
+ check(null, "a", key("a"));
+ check("x", "NOCRED", key("a"));
+ check(null, "a", key("a"), oldktab());
+ check("x", "NOCRED", key("a"), oldktab());
+ // Limitation, "a" has no key, but we don't know oldktab() is for "b"
+ check("a", "a", princ("a"), princ("b"), oldktab());
+ }
+
+ /**
+ * Checks the correct bound
+ * @param a get a creds for this principal, null for default one
+ * @param b expected name, null for still unbound, "NOCRED" for no creds
+ * @param objs princs, keys and keytabs in the subject
+ */
+ private static void check(final String a, String b, Object... objs)
+ throws Exception {
+ Subject subj = new Subject();
+ for (Object obj: objs) {
+ if (obj instanceof KerberosPrincipal) {
+ subj.getPrincipals().add((KerberosPrincipal)obj);
+ } else if (obj instanceof KerberosKey || obj instanceof KeyTab) {
+ subj.getPrivateCredentials().add(obj);
+ }
+ }
+ final GSSManager man = GSSManager.getInstance();
+ try {
+ String result = Subject.doAs(
+ subj, new PrivilegedExceptionAction<String>() {
+ @Override
+ public String run() throws GSSException {
+ GSSCredential cred = man.createCredential(
+ a == null ? null : man.createName(r(a), null),
+ GSSCredential.INDEFINITE_LIFETIME,
+ GSSUtil.GSS_KRB5_MECH_OID,
+ GSSCredential.ACCEPT_ONLY);
+ GSSName name = cred.getName();
+ return name == null ? null : name.toString();
+ }
+ });
+ if (!Objects.equals(result, r(b))) {
+ throw new Exception("Check failed: getInstance(" + a
+ + ") has name " + result + ", not " + b);
+ }
+ } catch (PrivilegedActionException e) {
+ if (!"NOCRED".equals(b)) {
+ throw new Exception("Check failed: getInstance(" + a
+ + ") is null " + ", but not one with name " + b);
+ }
+ }
+ }
+ private static String r(String s) {
+ return s == null ? null : (s+"@REALM");
+ }
+ private static KerberosPrincipal princ(String s) {
+ return new KerberosPrincipal(r(s));
+ }
+ private static KerberosKey key(String s) {
+ return new KerberosKey(princ(s), new byte[0], 0, 0);
+ }
+ private static KeyTab oldktab() {
+ return KeyTab.getInstance();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/AcceptPermissions.java Tue Jan 08 13:06:22 2013 -0800
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 9999999
+ * @summary default principal can act as anyone
+ * @compile -XDignore.symbol.file AcceptPermissions.java
+ * @run main/othervm AcceptPermissions
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.security.Permission;
+import javax.security.auth.kerberos.ServicePermission;
+import sun.security.jgss.GSSUtil;
+import java.util.*;
+
+public class AcceptPermissions extends SecurityManager {
+
+ private static Map<Permission,String> perms = new HashMap<>();
+ @Override
+ public void checkPermission(Permission perm) {
+ if (!(perm instanceof ServicePermission)) {
+ return;
+ }
+ ServicePermission sp = (ServicePermission)perm;
+ if (!sp.getActions().equals("accept")) {
+ return;
+ }
+ // We only care about accept ServicePermission in this test
+ try {
+ super.checkPermission(sp);
+ } catch (SecurityException se) {
+ if (perms.containsKey(sp)) {
+ perms.put(sp, "checked");
+ } else {
+ throw se; // We didn't expect this is needed
+ }
+ }
+ }
+
+ // Fills in permissions we are expecting
+ private static void initPerms(String... names) {
+ perms.clear();
+ for (String name: names) {
+ perms.put(new ServicePermission(
+ name + "@" + OneKDC.REALM, "accept"), "expected");
+ }
+ }
+
+ // Checks if they are all checked
+ private static void checkPerms() {
+ for (Map.Entry<Permission,String> entry: perms.entrySet()) {
+ if (entry.getValue().equals("expected")) {
+ throw new RuntimeException(
+ "Expected but not used: " + entry.getKey());
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.setSecurityManager(new AcceptPermissions());
+ new OneKDC(null).writeJAASConf();
+ String two = "two {\n"
+ + " com.sun.security.auth.module.Krb5LoginModule required"
+ + " principal=\"" + OneKDC.SERVER + "\" useKeyTab=true"
+ + " isInitiator=false storeKey=true;\n"
+ + " com.sun.security.auth.module.Krb5LoginModule required"
+ + " principal=\"" + OneKDC.BACKEND + "\" useKeyTab=true"
+ + " isInitiator=false storeKey=true;\n"
+ + "};\n";
+ Files.write(Paths.get(OneKDC.JAAS_CONF), two.getBytes(),
+ StandardOpenOption.APPEND);
+
+ Context c, s;
+
+ // In all cases, a ServicePermission on the acceptor name is needed
+ // for a handshake. For default principal with no predictable name,
+ // permission not needed (yet) for credentials creation.
+
+ // Named principal
+ initPerms(OneKDC.SERVER);
+ c = Context.fromJAAS("client");
+ s = Context.fromJAAS("server");
+ c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+ s.startAsServer(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+ checkPerms();
+ initPerms(OneKDC.SERVER);
+ Context.handshake(c, s);
+ checkPerms();
+
+ // Named principal (even if there are 2 JAAS modules)
+ initPerms(OneKDC.SERVER);
+ c = Context.fromJAAS("client");
+ s = Context.fromJAAS("two");
+ c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+ s.startAsServer(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+ checkPerms();
+ initPerms(OneKDC.SERVER);
+ Context.handshake(c, s);
+ checkPerms();
+
+ // Default principal with a predictable name
+ initPerms(OneKDC.SERVER);
+ c = Context.fromJAAS("client");
+ s = Context.fromJAAS("server");
+ c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+ s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+ checkPerms();
+ initPerms(OneKDC.SERVER);
+ Context.handshake(c, s);
+ checkPerms();
+
+ // Default principal with no predictable name
+ initPerms(); // permission not needed for cred !!!
+ c = Context.fromJAAS("client");
+ s = Context.fromJAAS("two");
+ c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+ s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+ checkPerms();
+ initPerms(OneKDC.SERVER); // still needed for handshake !!!
+ Context.handshake(c, s);
+ checkPerms();
+ }
+}
--- a/jdk/test/sun/security/krb5/auto/CleanState.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/sun/security/krb5/auto/CleanState.java Tue Jan 08 13:06:22 2013 -0800
@@ -24,6 +24,7 @@
/*
* @test
* @bug 6716534
+ * @compile -XDignore.symbol.file CleanState.java
* @run main/othervm CleanState
* @summary Krb5LoginModule has not cleaned temp info between authentication attempts
*/
--- a/jdk/test/sun/security/krb5/auto/Context.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/sun/security/krb5/auto/Context.java Tue Jan 08 13:06:22 2013 -0800
@@ -131,21 +131,24 @@
return out;
}
+ /**
+ * Logins with username/password as a new Subject
+ */
public static Context fromUserPass(
String user, char[] pass, boolean storeKey) throws Exception {
- return fromUserPass(null, user, pass, storeKey);
+ return fromUserPass(new Subject(), user, pass, storeKey);
}
/**
- * Logins with a username and a password, using Krb5LoginModule directly
- * @param s existing subject, test multiple princ & creds for single subj
- * @param storeKey true if key should be saved, used on acceptor side
+ * Logins with username/password as an existing Subject. The
+ * same subject can be used multiple times to simulate multiple logins.
+ * @param s existing subject
*/
public static Context fromUserPass(Subject s,
String user, char[] pass, boolean storeKey) throws Exception {
Context out = new Context();
out.name = user;
- out.s = s == null ? new Subject() : s;
+ out.s = s;
Krb5LoginModule krb5 = new Krb5LoginModule();
Map<String, String> map = new HashMap<>();
Map<String, Object> shared = new HashMap<>();
@@ -172,14 +175,23 @@
}
/**
- * Logins with a username and a keytab, using Krb5LoginModule directly
- * @param storeKey true if key should be saved, used on acceptor side
+ * Logins with username/keytab as an existing Subject. The
+ * same subject can be used multiple times to simulate multiple logins.
+ * @param s existing subject
*/
- public static Context fromUserKtab(String user, String ktab, boolean storeKey)
- throws Exception {
+ public static Context fromUserKtab(
+ String user, String ktab, boolean storeKey) throws Exception {
+ return fromUserKtab(new Subject(), user, ktab, storeKey);
+ }
+
+ /**
+ * Logins with username/keytab as a new subject,
+ */
+ public static Context fromUserKtab(Subject s,
+ String user, String ktab, boolean storeKey) throws Exception {
Context out = new Context();
out.name = user;
- out.s = new Subject();
+ out.s = s;
Krb5LoginModule krb5 = new Krb5LoginModule();
Map<String, String> map = new HashMap<>();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/DiffNameSameKey.java Tue Jan 08 13:06:22 2013 -0800
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8005447
+ * @summary default principal can act as anyone
+ * @compile -XDignore.symbol.file DiffNameSameKey.java
+ * @run main/othervm/fail DiffNameSameKey a
+ * @run main/othervm DiffNameSameKey b
+ */
+
+import sun.security.jgss.GSSUtil;
+import sun.security.krb5.PrincipalName;
+
+/**
+ * This test confirms the compatibility codes described in
+ * ServiceCreds.getEKeys(). If the acceptor starts as x.us.oracle.com
+ * but client requests for x.us, as long as the KDC supports both names
+ * and the keys are the same, the auth should succeed.
+ */
+public class DiffNameSameKey {
+
+ static final String SERVER2 = "x" + OneKDC.SERVER;
+
+ public static void main(String[] args) throws Exception {
+
+ OneKDC kdc = new KDC2();
+ kdc.addPrincipal(SERVER2, "samepass".toCharArray());
+ kdc.addPrincipal(OneKDC.SERVER, "samepass".toCharArray());
+ kdc.writeJAASConf();
+ kdc.writeKtab(OneKDC.KTAB);
+
+ Context c, s;
+ c = Context.fromJAAS("client");
+ s = Context.fromJAAS("server");
+
+ switch (args[0]) {
+ case "a": // If server starts as another service, should fail
+ c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_SPNEGO_MECH_OID);
+ s.startAsServer(SERVER2.replace('/', '@'),
+ GSSUtil.GSS_SPNEGO_MECH_OID);
+ break;
+ case "b": // If client requests another server with the same keys,
+ // succeed to be compatible
+ c.startAsClient(SERVER2, GSSUtil.GSS_SPNEGO_MECH_OID);
+ s.startAsServer(OneKDC.SERVER.replace('/', '@'),
+ GSSUtil.GSS_SPNEGO_MECH_OID);
+ break;
+ }
+
+ Context.handshake(c, s);
+
+ s.dispose();
+ c.dispose();
+ }
+
+ /**
+ * This KDC returns the same salt for all principals. This means same
+ * passwords generate same keys.
+ */
+ static class KDC2 extends OneKDC {
+ KDC2() throws Exception {
+ super(null);
+ }
+ @Override
+ public String getSalt(PrincipalName pn) {
+ return "SAME";
+ }
+ }
+}
--- a/jdk/test/sun/security/krb5/auto/DynamicKeytab.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/sun/security/krb5/auto/DynamicKeytab.java Tue Jan 08 13:06:22 2013 -0800
@@ -24,6 +24,7 @@
/*
* @test
* @bug 6894072
+ * @compile -XDignore.symbol.file DynamicKeytab.java
* @run main/othervm DynamicKeytab
* @summary always refresh keytab
*/
--- a/jdk/test/sun/security/krb5/auto/KDC.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/sun/security/krb5/auto/KDC.java Tue Jan 08 13:06:22 2013 -0800
@@ -285,10 +285,12 @@
if (Character.isDigit(pass[pass.length-1])) {
kvno = pass[pass.length-1] - '0';
}
- ktab.addEntry(new PrincipalName(name,
- name.indexOf('/') < 0 ?
- PrincipalName.KRB_NT_UNKNOWN :
- PrincipalName.KRB_NT_SRV_HST),
+ PrincipalName pn = new PrincipalName(name,
+ name.indexOf('/') < 0 ?
+ PrincipalName.KRB_NT_UNKNOWN :
+ PrincipalName.KRB_NT_SRV_HST);
+ ktab.addEntry(pn,
+ getSalt(pn),
pass,
kvno,
true);
@@ -534,7 +536,7 @@
if (pass == null) {
throw new KrbException(server?
Krb5.KDC_ERR_S_PRINCIPAL_UNKNOWN:
- Krb5.KDC_ERR_C_PRINCIPAL_UNKNOWN);
+ Krb5.KDC_ERR_C_PRINCIPAL_UNKNOWN, pn.toString());
}
return pass;
}
@@ -544,7 +546,7 @@
* @param p principal
* @return the salt
*/
- private String getSalt(PrincipalName p) {
+ protected String getSalt(PrincipalName p) {
String pn = p.toString();
if (p.getRealmString() == null) {
pn = pn + "@" + getRealm();
--- a/jdk/test/sun/security/krb5/auto/KeyTabCompat.java Tue Jan 08 11:55:21 2013 -0800
+++ b/jdk/test/sun/security/krb5/auto/KeyTabCompat.java Tue Jan 08 13:06:22 2013 -0800
@@ -38,7 +38,7 @@
*
* 1. If there is only KerberosKeys in private credential set and no
* KerberosPrincipal. JAAS login should go on.
- * 2. Even if KeyTab is used, user can still get KerberosKeys from
+ * 2. If KeyTab is used, user won't get KerberosKeys from
* private credentials set.
*/
public class KeyTabCompat {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/TwoOrThree.java Tue Jan 08 13:06:22 2013 -0800
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8005447
+ * @summary default principal can act as anyone
+ * @compile -XDignore.symbol.file TwoOrThree.java
+ * @run main/othervm TwoOrThree first first
+ * @run main/othervm/fail TwoOrThree first second
+ * @run main/othervm TwoOrThree - first
+ * @run main/othervm TwoOrThree - second
+ * @run main/othervm/fail TwoOrThree - third
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import javax.security.auth.Subject;
+import sun.security.jgss.GSSUtil;
+
+/*
+ * The JAAS login has two krb5 modules
+ * 1. principal is A
+ * 2. principal is B
+ * A named principal can only accept itself. The default principal can accept
+ * either, but not any other service even if the keytab also include its keys.
+ */
+public class TwoOrThree {
+
+ public static void main(String[] args) throws Exception {
+
+ String server = args[0].equals("-") ? null : args[0];
+ String target = args[1];
+ OneKDC kdc = new OneKDC(null);
+ kdc.addPrincipal("first", "first".toCharArray());
+ kdc.addPrincipal("second", "second".toCharArray());
+ kdc.addPrincipal("third", "third".toCharArray());
+ kdc.writeKtab(OneKDC.KTAB);
+
+ Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+
+ // Using keytabs
+ Subject sub4s = new Subject();
+ Context.fromUserKtab(sub4s, "first", OneKDC.KTAB, true);
+ Context s = Context.fromUserKtab(sub4s, "second", OneKDC.KTAB, true);
+ c.startAsClient(target, GSSUtil.GSS_KRB5_MECH_OID);
+ s.startAsServer(server, GSSUtil.GSS_KRB5_MECH_OID);
+ Context.handshake(c, s);
+
+ // Using keys
+ sub4s = new Subject();
+ Context.fromUserPass(sub4s, "first", "first".toCharArray(), true);
+ s = Context.fromUserPass(sub4s, "second", "second".toCharArray(), true);
+ c.startAsClient(target, GSSUtil.GSS_KRB5_MECH_OID);
+ s.startAsServer(server, GSSUtil.GSS_KRB5_MECH_OID);
+ Context.handshake(c, s);
+
+ s.dispose();
+ c.dispose();
+ }
+}