# HG changeset patch # User valeriep # Date 1357679182 28800 # Node ID ca5fca41f778ece2e74956975770537afc91fd3f # Parent ec6b49ce42b13031b51ba642f808293d78e1c67a# Parent 31d8a6072b16c2071986114915542d4fb42958b4 Merge diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java --- 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(); diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java --- 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() { - public Krb5Util.ServiceCreds run() throws Exception { + new PrivilegedExceptionAction() { + 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); } /** diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java --- 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(); diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java --- 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 { diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java --- 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 ktabs; - private List 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 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 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 allPrincs; + + // All private credentials that can be used + private List ktabs; + private List 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 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 answer = (oneOnly ? null : new ArrayList()); - if (credClass == KeyTab.class) { // Principal un-related - // We are looking for credentials unrelated to serverPrincipal - Iterator 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 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)); } } diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/src/share/classes/sun/security/krb5/KrbApReq.java --- 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) { diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java --- 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. diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/src/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java --- 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]; diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/src/windows/classes/sun/nio/ch/PipeImpl.java --- 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; } diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/ProblemList.txt --- 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 diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/java/nio/channels/Pipe/PipeInterrupt.java --- /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; + } +} diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java --- 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() { diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/java/rmi/activation/checkusage/CheckUsage.java --- 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; } } } diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java --- 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); diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/java/rmi/registry/checkusage/CheckUsage.java --- 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; } } } diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/java/rmi/registry/reexport/Reexport.java --- 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) { diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/java/rmi/testlibrary/JavaVM.java --- 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(); } } diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/java/rmi/testlibrary/RMID.java --- 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...). diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java --- 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."); } diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java --- 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"); } } diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/rmi/runtime/Log/4504153/Test4504153.java --- 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(); diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java --- 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 diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java --- 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) { diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/security/krb5/ServiceCredsCombination.java --- /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() { + @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(); + } +} diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/security/krb5/auto/AcceptPermissions.java --- /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 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 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(); + } +} diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/security/krb5/auto/CleanState.java --- 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 */ diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/security/krb5/auto/Context.java --- 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 map = new HashMap<>(); Map 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 map = new HashMap<>(); diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/security/krb5/auto/DiffNameSameKey.java --- /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"; + } + } +} diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/security/krb5/auto/DynamicKeytab.java --- 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 */ diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/security/krb5/auto/KDC.java --- 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(); diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/security/krb5/auto/KeyTabCompat.java --- 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 { diff -r ec6b49ce42b1 -r ca5fca41f778 jdk/test/sun/security/krb5/auto/TwoOrThree.java --- /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(); + } +}