mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8227437: S4U2proxy cannot continue because server's TGT cannot be found
Reviewed-by: weijun
This commit is contained in:
parent
5fd772a6f1
commit
3cd50f2666
23 changed files with 466 additions and 149 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2019, 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
|
||||
|
@ -49,7 +49,9 @@ public class Credentials {
|
|||
|
||||
Ticket ticket;
|
||||
PrincipalName client;
|
||||
PrincipalName clientAlias;
|
||||
PrincipalName server;
|
||||
PrincipalName serverAlias;
|
||||
EncryptionKey key;
|
||||
TicketFlags flags;
|
||||
KerberosTime authTime;
|
||||
|
@ -69,7 +71,9 @@ public class Credentials {
|
|||
|
||||
public Credentials(Ticket new_ticket,
|
||||
PrincipalName new_client,
|
||||
PrincipalName new_client_alias,
|
||||
PrincipalName new_server,
|
||||
PrincipalName new_server_alias,
|
||||
EncryptionKey new_key,
|
||||
TicketFlags new_flags,
|
||||
KerberosTime authTime,
|
||||
|
@ -78,14 +82,17 @@ public class Credentials {
|
|||
KerberosTime renewTill,
|
||||
HostAddresses cAddr,
|
||||
AuthorizationData authzData) {
|
||||
this(new_ticket, new_client, new_server, new_key, new_flags,
|
||||
authTime, new_startTime, new_endTime, renewTill, cAddr);
|
||||
this(new_ticket, new_client, new_client_alias, new_server,
|
||||
new_server_alias, new_key, new_flags, authTime,
|
||||
new_startTime, new_endTime, renewTill, cAddr);
|
||||
this.authzData = authzData;
|
||||
}
|
||||
|
||||
public Credentials(Ticket new_ticket,
|
||||
PrincipalName new_client,
|
||||
PrincipalName new_client_alias,
|
||||
PrincipalName new_server,
|
||||
PrincipalName new_server_alias,
|
||||
EncryptionKey new_key,
|
||||
TicketFlags new_flags,
|
||||
KerberosTime authTime,
|
||||
|
@ -95,7 +102,9 @@ public class Credentials {
|
|||
HostAddresses cAddr) {
|
||||
ticket = new_ticket;
|
||||
client = new_client;
|
||||
clientAlias = new_client_alias;
|
||||
server = new_server;
|
||||
serverAlias = new_server_alias;
|
||||
key = new_key;
|
||||
flags = new_flags;
|
||||
this.authTime = authTime;
|
||||
|
@ -107,7 +116,9 @@ public class Credentials {
|
|||
|
||||
public Credentials(byte[] encoding,
|
||||
String client,
|
||||
String clientAlias,
|
||||
String server,
|
||||
String serverAlias,
|
||||
byte[] keyBytes,
|
||||
int keyType,
|
||||
boolean[] flags,
|
||||
|
@ -118,7 +129,11 @@ public class Credentials {
|
|||
InetAddress[] cAddrs) throws KrbException, IOException {
|
||||
this(new Ticket(encoding),
|
||||
new PrincipalName(client, PrincipalName.KRB_NT_PRINCIPAL),
|
||||
(clientAlias == null? null : new PrincipalName(clientAlias,
|
||||
PrincipalName.KRB_NT_PRINCIPAL)),
|
||||
new PrincipalName(server, PrincipalName.KRB_NT_SRV_INST),
|
||||
(serverAlias == null? null : new PrincipalName(serverAlias,
|
||||
PrincipalName.KRB_NT_SRV_INST)),
|
||||
new EncryptionKey(keyType, keyBytes),
|
||||
(flags == null? null: new TicketFlags(flags)),
|
||||
(authTime == null? null: new KerberosTime(authTime)),
|
||||
|
@ -143,10 +158,18 @@ public class Credentials {
|
|||
return client;
|
||||
}
|
||||
|
||||
public final PrincipalName getClientAlias() {
|
||||
return clientAlias;
|
||||
}
|
||||
|
||||
public final PrincipalName getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public final PrincipalName getServerAlias() {
|
||||
return serverAlias;
|
||||
}
|
||||
|
||||
public final EncryptionKey getSessionKey() {
|
||||
return key;
|
||||
}
|
||||
|
@ -262,6 +285,7 @@ public class Credentials {
|
|||
return new KrbTgsReq(options,
|
||||
this,
|
||||
server,
|
||||
serverAlias,
|
||||
null, // from
|
||||
null, // till
|
||||
null, // rtime
|
||||
|
@ -484,7 +508,11 @@ public class Credentials {
|
|||
public static void printDebug(Credentials c) {
|
||||
System.out.println(">>> DEBUG: ----Credentials----");
|
||||
System.out.println("\tclient: " + c.client.toString());
|
||||
if (c.clientAlias != null)
|
||||
System.out.println("\tclient alias: " + c.clientAlias.toString());
|
||||
System.out.println("\tserver: " + c.server.toString());
|
||||
if (c.serverAlias != null)
|
||||
System.out.println("\tserver alias: " + c.serverAlias.toString());
|
||||
System.out.println("\tticket: sname: " + c.ticket.sname.toString());
|
||||
if (c.startTime != null) {
|
||||
System.out.println("\tstartTime: " + c.startTime.getTime());
|
||||
|
@ -512,7 +540,11 @@ public class Credentials {
|
|||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("Credentials:");
|
||||
sb.append( "\n client=").append(client);
|
||||
if (clientAlias != null)
|
||||
sb.append( "\n clientAlias=").append(clientAlias);
|
||||
sb.append( "\n server=").append(server);
|
||||
if (serverAlias != null)
|
||||
sb.append( "\n serverAlias=").append(serverAlias);
|
||||
if (authTime != null) {
|
||||
sb.append("\n authTime=").append(authTime);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2019, 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
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
package sun.security.krb5;
|
||||
|
||||
import javax.security.auth.kerberos.KerberosPrincipal;
|
||||
import javax.security.auth.kerberos.KerberosTicket;
|
||||
import javax.security.auth.kerberos.KeyTab;
|
||||
import sun.security.krb5.EncryptionKey;
|
||||
import sun.security.krb5.PrincipalName;
|
||||
|
@ -39,4 +41,12 @@ public interface JavaxSecurityAuthKerberosAccess {
|
|||
*/
|
||||
public sun.security.krb5.internal.ktab.KeyTab keyTabTakeSnapshot(
|
||||
KeyTab ktab);
|
||||
|
||||
public KerberosPrincipal kerberosTicketGetClientAlias(KerberosTicket t);
|
||||
|
||||
public void kerberosTicketSetClientAlias(KerberosTicket t, KerberosPrincipal a);
|
||||
|
||||
public KerberosPrincipal kerberosTicketGetServerAlias(KerberosTicket t);
|
||||
|
||||
public void kerberosTicketSetServerAlias(KerberosTicket t, KerberosPrincipal a);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2019, 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
|
||||
|
@ -363,7 +363,9 @@ public class KrbApReq {
|
|||
creds = new Credentials(
|
||||
apReqMessg.ticket,
|
||||
authenticator.cname,
|
||||
null,
|
||||
apReqMessg.ticket.sname,
|
||||
null,
|
||||
enc_ticketPart.key,
|
||||
enc_ticketPart.flags,
|
||||
enc_ticketPart.authtime,
|
||||
|
|
|
@ -118,7 +118,7 @@ class KrbAsRep extends KrbKdcRep {
|
|||
"Cannot find key for type/kvno to decrypt AS REP - " +
|
||||
EType.toString(encPartKeyType) + "/" + encPartKvno);
|
||||
}
|
||||
decrypt(dkey, asReq);
|
||||
decrypt(dkey, asReq, cname);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,7 +136,7 @@ class KrbAsRep extends KrbKdcRep {
|
|||
password,
|
||||
encPartKeyType,
|
||||
PAData.getSaltAndParams(encPartKeyType, rep.pAData));
|
||||
decrypt(dkey, asReq);
|
||||
decrypt(dkey, asReq, cname);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,7 +144,8 @@ class KrbAsRep extends KrbKdcRep {
|
|||
* @param dkey the decryption key to use
|
||||
* @param asReq the original AS-REQ sent, used to validate AS-REP
|
||||
*/
|
||||
private void decrypt(EncryptionKey dkey, KrbAsReq asReq)
|
||||
private void decrypt(EncryptionKey dkey, KrbAsReq asReq,
|
||||
PrincipalName cname)
|
||||
throws KrbException, Asn1Exception, IOException {
|
||||
byte[] enc_as_rep_bytes = rep.encPart.decrypt(dkey,
|
||||
KeyUsage.KU_ENC_AS_REP_PART);
|
||||
|
@ -157,10 +158,16 @@ class KrbAsRep extends KrbKdcRep {
|
|||
ASReq req = asReq.getMessage();
|
||||
check(true, req, rep, dkey);
|
||||
|
||||
PrincipalName clientAlias = cname;
|
||||
if (clientAlias.equals(rep.cname))
|
||||
clientAlias = null;
|
||||
|
||||
creds = new Credentials(
|
||||
rep.ticket,
|
||||
rep.cname,
|
||||
clientAlias,
|
||||
enc_part.sname,
|
||||
null, // No server alias expected in a TGT
|
||||
enc_part.key,
|
||||
enc_part.flags,
|
||||
enc_part.authtime,
|
||||
|
|
|
@ -68,6 +68,7 @@ public final class KrbAsReqBuilder {
|
|||
// Common data for AS-REQ fields
|
||||
private KDCOptions options;
|
||||
private PrincipalName cname;
|
||||
private PrincipalName refCname; // May be changed by referrals
|
||||
private PrincipalName sname;
|
||||
private KerberosTime from;
|
||||
private KerberosTime till;
|
||||
|
@ -100,6 +101,7 @@ public final class KrbAsReqBuilder {
|
|||
private void init(PrincipalName cname)
|
||||
throws KrbException {
|
||||
this.cname = cname;
|
||||
this.refCname = cname;
|
||||
state = State.INIT;
|
||||
}
|
||||
|
||||
|
@ -284,7 +286,7 @@ public final class KrbAsReqBuilder {
|
|||
}
|
||||
return new KrbAsReq(key,
|
||||
options,
|
||||
cname,
|
||||
refCname,
|
||||
sname,
|
||||
from,
|
||||
till,
|
||||
|
@ -334,7 +336,7 @@ public final class KrbAsReqBuilder {
|
|||
ReferralsState referralsState = new ReferralsState();
|
||||
while (true) {
|
||||
if (referralsState.refreshComm()) {
|
||||
comm = new KdcComm(cname.getRealmAsString());
|
||||
comm = new KdcComm(refCname.getRealmAsString());
|
||||
}
|
||||
try {
|
||||
req = build(pakey, referralsState);
|
||||
|
@ -384,7 +386,7 @@ public final class KrbAsReqBuilder {
|
|||
|
||||
ReferralsState() throws KrbException {
|
||||
if (Config.DISABLE_REFERRALS) {
|
||||
if (cname.getNameType() == PrincipalName.KRB_NT_ENTERPRISE) {
|
||||
if (refCname.getNameType() == PrincipalName.KRB_NT_ENTERPRISE) {
|
||||
throw new KrbException("NT-ENTERPRISE principals only allowed" +
|
||||
" when referrals are enabled.");
|
||||
}
|
||||
|
@ -402,15 +404,15 @@ public final class KrbAsReqBuilder {
|
|||
if (req.getMessage().reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) &&
|
||||
referredRealm != null && referredRealm.toString().length() > 0 &&
|
||||
count < Config.MAX_REFERRALS) {
|
||||
cname = new PrincipalName(cname.getNameType(),
|
||||
cname.getNameStrings(), referredRealm);
|
||||
refCname = new PrincipalName(refCname.getNameType(),
|
||||
refCname.getNameStrings(), referredRealm);
|
||||
refreshComm = true;
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (count < Config.MAX_REFERRALS &&
|
||||
cname.getNameType() != PrincipalName.KRB_NT_ENTERPRISE) {
|
||||
refCname.getNameType() != PrincipalName.KRB_NT_ENTERPRISE) {
|
||||
// Server may raise an error if CANONICALIZE is true.
|
||||
// Try CANONICALIZE false.
|
||||
enabled = false;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2019, 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,7 +76,7 @@ public class KrbCred {
|
|||
options.set(KDCOptions.FORWARDABLE, true);
|
||||
|
||||
KrbTgsReq tgsReq = new KrbTgsReq(options, tgt, tgService,
|
||||
null, null, null, null,
|
||||
null, null, null, null, null,
|
||||
null, // No easy way to get addresses right
|
||||
null, null, null);
|
||||
credMessg = createMessage(tgsReq.sendAndGetCreds(), key);
|
||||
|
@ -152,7 +152,7 @@ public class KrbCred {
|
|||
+ " endtime=" + endtime
|
||||
+ "renewTill=" + renewTill);
|
||||
}
|
||||
creds = new Credentials(ticket, pname, sname, credInfoKey,
|
||||
creds = new Credentials(ticket, pname, null, sname, null, credInfoKey,
|
||||
flags, authtime, starttime, endtime, renewTill, caddr);
|
||||
}
|
||||
|
||||
|
|
|
@ -86,9 +86,20 @@ public class KrbTgsRep extends KrbKdcRep {
|
|||
|
||||
check(false, req, rep, tgsReq.tgsReqKey);
|
||||
|
||||
PrincipalName serverAlias = tgsReq.getServerAlias();
|
||||
if (serverAlias != null) {
|
||||
PrincipalName repSname = enc_part.sname;
|
||||
if (serverAlias.equals(repSname) ||
|
||||
isReferralSname(repSname)) {
|
||||
serverAlias = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.creds = new Credentials(rep.ticket,
|
||||
rep.cname,
|
||||
tgsReq.getClientAlias(),
|
||||
enc_part.sname,
|
||||
serverAlias,
|
||||
enc_part.key,
|
||||
enc_part.flags,
|
||||
enc_part.authtime,
|
||||
|
@ -111,4 +122,16 @@ public class KrbTgsRep extends KrbKdcRep {
|
|||
sun.security.krb5.internal.ccache.Credentials setCredentials() {
|
||||
return new sun.security.krb5.internal.ccache.Credentials(rep, secondTicket);
|
||||
}
|
||||
|
||||
private static boolean isReferralSname(PrincipalName sname) {
|
||||
if (sname != null) {
|
||||
String[] snameStrings = sname.getNameStrings();
|
||||
if (snameStrings.length == 2 &&
|
||||
snameStrings[0].equals(
|
||||
PrincipalName.TGS_DEFAULT_SRV_NAME)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,9 @@ import java.util.Arrays;
|
|||
public class KrbTgsReq {
|
||||
|
||||
private PrincipalName princName;
|
||||
private PrincipalName clientAlias;
|
||||
private PrincipalName servName;
|
||||
private PrincipalName serverAlias;
|
||||
private TGSReq tgsReqMessg;
|
||||
private KerberosTime ctime;
|
||||
private Ticket secondTicket = null;
|
||||
|
@ -59,13 +61,16 @@ public class KrbTgsReq {
|
|||
|
||||
// Used in CredentialsUtil
|
||||
public KrbTgsReq(KDCOptions options, Credentials asCreds,
|
||||
PrincipalName cname, PrincipalName sname,
|
||||
PrincipalName cname, PrincipalName clientAlias,
|
||||
PrincipalName sname, PrincipalName serverAlias,
|
||||
Ticket[] additionalTickets, PAData[] extraPAs)
|
||||
throws KrbException, IOException {
|
||||
this(options,
|
||||
asCreds,
|
||||
cname,
|
||||
clientAlias,
|
||||
sname,
|
||||
serverAlias,
|
||||
null, // KerberosTime from
|
||||
null, // KerberosTime till
|
||||
null, // KerberosTime rtime
|
||||
|
@ -82,6 +87,7 @@ public class KrbTgsReq {
|
|||
KDCOptions options,
|
||||
Credentials asCreds,
|
||||
PrincipalName sname,
|
||||
PrincipalName serverAlias,
|
||||
KerberosTime from,
|
||||
KerberosTime till,
|
||||
KerberosTime rtime,
|
||||
|
@ -90,16 +96,18 @@ public class KrbTgsReq {
|
|||
AuthorizationData authorizationData,
|
||||
Ticket[] additionalTickets,
|
||||
EncryptionKey subKey) throws KrbException, IOException {
|
||||
this(options, asCreds, asCreds.getClient(), sname,
|
||||
from, till, rtime, eTypes, addresses,
|
||||
authorizationData, additionalTickets, subKey, null);
|
||||
this(options, asCreds, asCreds.getClient(), asCreds.getClientAlias(),
|
||||
sname, serverAlias, from, till, rtime, eTypes,
|
||||
addresses, authorizationData, additionalTickets, subKey, null);
|
||||
}
|
||||
|
||||
private KrbTgsReq(
|
||||
KDCOptions options,
|
||||
Credentials asCreds,
|
||||
PrincipalName cname,
|
||||
PrincipalName clientAlias,
|
||||
PrincipalName sname,
|
||||
PrincipalName serverAlias,
|
||||
KerberosTime from,
|
||||
KerberosTime till,
|
||||
KerberosTime rtime,
|
||||
|
@ -111,7 +119,9 @@ public class KrbTgsReq {
|
|||
PAData[] extraPAs) throws KrbException, IOException {
|
||||
|
||||
princName = cname;
|
||||
this.clientAlias = clientAlias;
|
||||
servName = sname;
|
||||
this.serverAlias = serverAlias;
|
||||
ctime = KerberosTime.now();
|
||||
|
||||
// check if they are valid arguments. The optional fields
|
||||
|
@ -365,6 +375,14 @@ public class KrbTgsReq {
|
|||
return secondTicket;
|
||||
}
|
||||
|
||||
PrincipalName getClientAlias() {
|
||||
return clientAlias;
|
||||
}
|
||||
|
||||
PrincipalName getServerAlias() {
|
||||
return serverAlias;
|
||||
}
|
||||
|
||||
private static void debug(String message) {
|
||||
// System.err.println(">>> KrbTgsReq: " + message);
|
||||
}
|
||||
|
|
|
@ -564,7 +564,9 @@ public class PrincipalName implements Cloneable {
|
|||
for (int i = 0; i < nameStrings.length; i++) {
|
||||
if (i > 0)
|
||||
str.append("/");
|
||||
str.append(nameStrings[i]);
|
||||
String n = nameStrings[i];
|
||||
n = n.replace("@", "\\@");
|
||||
str.append(n);
|
||||
}
|
||||
str.append("@");
|
||||
str.append(nameRealm.toString());
|
||||
|
|
|
@ -284,8 +284,9 @@ public class CredentialsUtil {
|
|||
// Try CANONICALIZE false.
|
||||
}
|
||||
}
|
||||
return serviceCredsSingle(options, asCreds,
|
||||
cname, sname, additionalTickets, extraPAs);
|
||||
return serviceCredsSingle(options, asCreds, cname,
|
||||
asCreds.getClientAlias(), sname, sname, additionalTickets,
|
||||
extraPAs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -300,26 +301,29 @@ public class CredentialsUtil {
|
|||
options = new KDCOptions(options.toBooleanArray());
|
||||
options.set(KDCOptions.CANONICALIZE, true);
|
||||
PrincipalName cSname = sname;
|
||||
PrincipalName refSname = sname; // May change with referrals
|
||||
Credentials creds = null;
|
||||
boolean isReferral = false;
|
||||
List<String> referrals = new LinkedList<>();
|
||||
PrincipalName clientAlias = asCreds.getClientAlias();
|
||||
while (referrals.size() <= Config.MAX_REFERRALS) {
|
||||
ReferralsCache.ReferralCacheEntry ref =
|
||||
ReferralsCache.get(sname, cSname.getRealmString());
|
||||
ReferralsCache.get(cname, sname, refSname.getRealmString());
|
||||
String toRealm = null;
|
||||
if (ref == null) {
|
||||
creds = serviceCredsSingle(options, asCreds,
|
||||
cname, cSname, additionalTickets, extraPAs);
|
||||
creds = serviceCredsSingle(options, asCreds, cname,
|
||||
clientAlias, refSname, cSname, additionalTickets,
|
||||
extraPAs);
|
||||
PrincipalName server = creds.getServer();
|
||||
if (!cSname.equals(server)) {
|
||||
if (!refSname.equals(server)) {
|
||||
String[] serverNameStrings = server.getNameStrings();
|
||||
if (serverNameStrings.length == 2 &&
|
||||
serverNameStrings[0].equals(
|
||||
PrincipalName.TGS_DEFAULT_SRV_NAME) &&
|
||||
!cSname.getRealmAsString().equals(serverNameStrings[1])) {
|
||||
!refSname.getRealmAsString().equals(serverNameStrings[1])) {
|
||||
// Server Name (sname) has the following format:
|
||||
// krbtgt/TO-REALM.COM@FROM-REALM.COM
|
||||
ReferralsCache.put(sname, server.getRealmString(),
|
||||
ReferralsCache.put(cname, sname, server.getRealmString(),
|
||||
serverNameStrings[1], creds);
|
||||
toRealm = serverNameStrings[1];
|
||||
isReferral = true;
|
||||
|
@ -336,8 +340,8 @@ public class CredentialsUtil {
|
|||
// Referrals loop detected
|
||||
return null;
|
||||
}
|
||||
cSname = new PrincipalName(cSname.getNameString(),
|
||||
cSname.getNameType(), toRealm);
|
||||
refSname = new PrincipalName(refSname.getNameString(),
|
||||
refSname.getNameType(), toRealm);
|
||||
referrals.add(toRealm);
|
||||
isReferral = false;
|
||||
continue;
|
||||
|
@ -356,14 +360,15 @@ public class CredentialsUtil {
|
|||
*/
|
||||
private static Credentials serviceCredsSingle(
|
||||
KDCOptions options, Credentials asCreds,
|
||||
PrincipalName cname, PrincipalName sname,
|
||||
PrincipalName cname, PrincipalName clientAlias,
|
||||
PrincipalName refSname, PrincipalName sname,
|
||||
Ticket[] additionalTickets, PAData[] extraPAs)
|
||||
throws KrbException, IOException {
|
||||
Credentials theCreds = null;
|
||||
boolean[] okAsDelegate = new boolean[]{true};
|
||||
String[] serverAsCredsNames = asCreds.getServer().getNameStrings();
|
||||
String tgtRealm = serverAsCredsNames[1];
|
||||
String serviceRealm = sname.getRealmString();
|
||||
String serviceRealm = refSname.getRealmString();
|
||||
if (!serviceRealm.equals(tgtRealm)) {
|
||||
// This is a cross-realm service request
|
||||
if (DEBUG) {
|
||||
|
@ -390,8 +395,8 @@ public class CredentialsUtil {
|
|||
System.out.println(">>> Credentials serviceCredsSingle:" +
|
||||
" same realm");
|
||||
}
|
||||
KrbTgsReq req = new KrbTgsReq(options, asCreds,
|
||||
cname, sname, additionalTickets, extraPAs);
|
||||
KrbTgsReq req = new KrbTgsReq(options, asCreds, cname, clientAlias,
|
||||
refSname, sname, additionalTickets, extraPAs);
|
||||
theCreds = req.sendAndGetCreds();
|
||||
if (theCreds != null) {
|
||||
if (DEBUG) {
|
||||
|
|
|
@ -139,7 +139,7 @@ public class KRBError implements java.io.Serializable {
|
|||
sTime = new_sTime;
|
||||
suSec = new_suSec;
|
||||
errorCode = new_errorCode;
|
||||
crealm = new_cname.getRealm();
|
||||
crealm = new_cname != null ? new_cname.getRealm() : null;
|
||||
cname = new_cname;
|
||||
sname = new_sname;
|
||||
eText = new_eText;
|
||||
|
@ -168,7 +168,7 @@ public class KRBError implements java.io.Serializable {
|
|||
sTime = new_sTime;
|
||||
suSec = new_suSec;
|
||||
errorCode = new_errorCode;
|
||||
crealm = new_cname.getRealm();
|
||||
crealm = new_cname != null ? new_cname.getRealm() : null;
|
||||
cname = new_cname;
|
||||
sname = new_sname;
|
||||
eText = new_eText;
|
||||
|
|
|
@ -45,8 +45,27 @@ import sun.security.krb5.PrincipalName;
|
|||
*/
|
||||
final class ReferralsCache {
|
||||
|
||||
private static Map<PrincipalName, Map<String, ReferralCacheEntry>> referralsMap =
|
||||
new HashMap<>();
|
||||
private static Map<ReferralCacheKey, Map<String, ReferralCacheEntry>>
|
||||
referralsMap = new HashMap<>();
|
||||
|
||||
static private final class ReferralCacheKey {
|
||||
private PrincipalName cname;
|
||||
private PrincipalName sname;
|
||||
ReferralCacheKey (PrincipalName cname, PrincipalName sname) {
|
||||
this.cname = cname;
|
||||
this.sname = sname;
|
||||
}
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof ReferralCacheKey))
|
||||
return false;
|
||||
ReferralCacheKey that = (ReferralCacheKey)other;
|
||||
return cname.equals(that.cname) &&
|
||||
sname.equals(that.sname);
|
||||
}
|
||||
public int hashCode() {
|
||||
return cname.hashCode() + sname.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
static final class ReferralCacheEntry {
|
||||
private final Credentials creds;
|
||||
|
@ -64,8 +83,9 @@ final class ReferralsCache {
|
|||
}
|
||||
|
||||
/*
|
||||
* Add a new referral entry to the cache, including: service principal,
|
||||
* source KDC realm, destination KDC realm and referral TGT.
|
||||
* Add a new referral entry to the cache, including: client principal,
|
||||
* service principal, source KDC realm, destination KDC realm and
|
||||
* referral TGT.
|
||||
*
|
||||
* If a loop is generated when adding the new referral, the first hop is
|
||||
* automatically removed. For example, let's assume that adding a
|
||||
|
@ -73,16 +93,17 @@ final class ReferralsCache {
|
|||
* REALM-1.COM -> REALM-2.COM -> REALM-3.COM -> REALM-1.COM. Then,
|
||||
* REALM-1.COM -> REALM-2.COM referral entry is removed from the cache.
|
||||
*/
|
||||
static synchronized void put(PrincipalName service,
|
||||
static synchronized void put(PrincipalName cname, PrincipalName service,
|
||||
String fromRealm, String toRealm, Credentials creds) {
|
||||
pruneExpired(service);
|
||||
ReferralCacheKey k = new ReferralCacheKey(cname, service);
|
||||
pruneExpired(k);
|
||||
if (creds.getEndTime().before(new Date())) {
|
||||
return;
|
||||
}
|
||||
Map<String, ReferralCacheEntry> entries = referralsMap.get(service);
|
||||
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
|
||||
if (entries == null) {
|
||||
entries = new HashMap<String, ReferralCacheEntry>();
|
||||
referralsMap.put(service, entries);
|
||||
referralsMap.put(k, entries);
|
||||
}
|
||||
entries.remove(fromRealm);
|
||||
ReferralCacheEntry newEntry = new ReferralCacheEntry(creds, toRealm);
|
||||
|
@ -103,13 +124,14 @@ final class ReferralsCache {
|
|||
}
|
||||
|
||||
/*
|
||||
* Obtain a referral entry from the cache given a service principal and a
|
||||
* source KDC realm.
|
||||
* Obtain a referral entry from the cache given a client principal,
|
||||
* service principal and a source KDC realm.
|
||||
*/
|
||||
static synchronized ReferralCacheEntry get(PrincipalName service,
|
||||
String fromRealm) {
|
||||
pruneExpired(service);
|
||||
Map<String, ReferralCacheEntry> entries = referralsMap.get(service);
|
||||
static synchronized ReferralCacheEntry get(PrincipalName cname,
|
||||
PrincipalName service, String fromRealm) {
|
||||
ReferralCacheKey k = new ReferralCacheKey(cname, service);
|
||||
pruneExpired(k);
|
||||
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
|
||||
if (entries != null) {
|
||||
ReferralCacheEntry toRef = entries.get(fromRealm);
|
||||
if (toRef != null) {
|
||||
|
@ -122,9 +144,9 @@ final class ReferralsCache {
|
|||
/*
|
||||
* Remove referral entries from the cache when referral TGTs expire.
|
||||
*/
|
||||
private static void pruneExpired(PrincipalName service) {
|
||||
private static void pruneExpired(ReferralCacheKey k) {
|
||||
Date now = new Date();
|
||||
Map<String, ReferralCacheEntry> entries = referralsMap.get(service);
|
||||
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
|
||||
if (entries != null) {
|
||||
for (Entry<String, ReferralCacheEntry> mapEntry :
|
||||
entries.entrySet()) {
|
||||
|
|
|
@ -180,8 +180,9 @@ public class Credentials {
|
|||
// is most likely to be the one in Authenticator in PA-TGS-REQ encoded
|
||||
// in TGS-REQ, therefore only stored with a service ticket. Currently
|
||||
// in Java, we only reads TGTs.
|
||||
return new sun.security.krb5.Credentials(ticket,
|
||||
cname, sname, key, flags, authtime, starttime, endtime, renewTill, caddr);
|
||||
return new sun.security.krb5.Credentials(ticket, cname, null, sname,
|
||||
null, key, flags, authtime, starttime, endtime, renewTill,
|
||||
caddr);
|
||||
}
|
||||
|
||||
public KerberosTime getStartTime() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue