6859027: Duplicate communications to KDC in GSSManager.createCredential(usage)

6859027: Duplicate communications to KDC in GSSManager.createCredential(usage)
This commit is contained in:
Weijun Wang 2021-08-27 15:45:31 -04:00
parent 594e5161b4
commit 2a507b313e
2 changed files with 114 additions and 4 deletions

View File

@ -40,6 +40,8 @@ import sun.security.krb5.Credentials;
import sun.security.krb5.EncryptionKey;
import sun.security.krb5.KrbException;
import java.io.IOException;
import java.util.Objects;
import sun.security.krb5.KerberosSecrets;
import sun.security.krb5.PrincipalName;
@ -75,6 +77,11 @@ public class Krb5Util {
return ticket;
}
// A one slot local ccache for krb5 login. This is only used when
// useSubjectCredsOnly is false.
static String lastClient = null;
static KerberosTicket lastTicket = null;
/**
* Retrieves the initial TGT corresponding to the client principal
* from the Subject in the specified AccessControlContext.
@ -82,7 +89,7 @@ public class Krb5Util {
* useSubjectCredsOnly is false, then obtain ticket from
* a LoginContext.
*/
static KerberosTicket getInitialTicket(GSSCaller caller,
static synchronized KerberosTicket getInitialTicket(GSSCaller caller,
String clientPrincipal,
@SuppressWarnings("removal") AccessControlContext acc) throws LoginException {
@ -95,9 +102,38 @@ public class Krb5Util {
// Try to get ticket from Subject obtained from GSSUtil
if (ticket == null && !GSSUtil.useSubjectCredsOnly(caller)) {
Subject subject = GSSUtil.login(caller, GSSUtil.GSS_KRB5_MECH_OID);
ticket = SubjectComber.find(subject,
null, clientPrincipal, KerberosTicket.class);
if (Objects.equals(clientPrincipal, lastClient)
&& lastTicket != null) {
if (lastTicket.isCurrent()) {
if (DEBUG) {
System.out.println("getInitialTicket: use cached ticket");
}
ticket = lastTicket;
} else if (lastTicket.isRenewable()) {
try {
lastTicket.refresh();
if (DEBUG) {
System.out.println("getInitialTicket: renew cached ticket");
}
ticket = lastTicket;
} catch (Exception e) {
if (DEBUG) {
System.out.println("getInitialTicket: renew cached ticket failed");
}
}
}
}
if (ticket == null) {
Subject subject = GSSUtil.login(caller, GSSUtil.GSS_KRB5_MECH_OID);
ticket = SubjectComber.find(subject,
null, clientPrincipal, KerberosTicket.class);
lastClient = clientPrincipal;
lastTicket = ticket;
if (DEBUG) {
System.out.println("getInitialTicket: retrieve ticket from KDC");
}
}
}
return ticket;
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2021, 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 6859027
* @summary Duplicate communications to KDC in GSSManager.createCredential(usage)
* @library /test/lib
* @compile -XDignore.symbol.file MultiMechsLoginOnce.java
* @run main jdk.test.lib.FileInstaller TestHosts TestHosts
* @run main/othervm -Djdk.net.hosts.file=TestHosts MultiMechsLoginOnce me
* @run main/othervm -Djdk.net.hosts.file=TestHosts MultiMechsLoginOnce null
*/
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;
public class MultiMechsLoginOnce {
static int count = 0;
public static void main(String[] args) throws Exception {
new OneKDC(null) {
@Override
protected byte[] processAsReq(byte[] in) throws Exception {
count++;
return super.processAsReq(in);
}
}.writeJAASConf()
.setOption(KDC.Option.PREAUTH_REQUIRED, false);
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
GSSManager man = GSSManager.getInstance();
// Test both with name and without name
GSSName me = args[0].equals("me")
? man.createName(OneKDC.USER, GSSName.NT_USER_NAME)
: null;
GSSCredential cred = man.createCredential(
me,
GSSCredential.DEFAULT_LIFETIME,
(Oid[])null,
GSSCredential.INITIATE_ONLY);
if (cred.getMechs().length < 2) {
throw new RuntimeException("Not multi mech: " + cred);
}
if (count != 1) {
throw new RuntimeException("Request not once: " + count);
}
}
}