mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +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) 2011, 2015, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -345,7 +345,7 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||||
|
|
||||||
if (krbcredsConstructor == 0) {
|
if (krbcredsConstructor == 0) {
|
||||||
krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>",
|
krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>",
|
||||||
"(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V");
|
"(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V");
|
||||||
if (krbcredsConstructor == 0) {
|
if (krbcredsConstructor == 0) {
|
||||||
printf("Couldn't find sun.security.krb5.internal.Ticket constructor\n");
|
printf("Couldn't find sun.security.krb5.internal.Ticket constructor\n");
|
||||||
break;
|
break;
|
||||||
|
@ -359,7 +359,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||||
krbcredsConstructor,
|
krbcredsConstructor,
|
||||||
ticket,
|
ticket,
|
||||||
clientPrincipal,
|
clientPrincipal,
|
||||||
|
NULL,
|
||||||
targetPrincipal,
|
targetPrincipal,
|
||||||
|
NULL,
|
||||||
encryptionKey,
|
encryptionKey,
|
||||||
ticketFlags,
|
ticketFlags,
|
||||||
authTime,
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,8 +26,6 @@
|
||||||
package javax.security.auth.kerberos;
|
package javax.security.auth.kerberos;
|
||||||
|
|
||||||
import sun.security.krb5.JavaxSecurityAuthKerberosAccess;
|
import sun.security.krb5.JavaxSecurityAuthKerberosAccess;
|
||||||
import sun.security.krb5.EncryptionKey;
|
|
||||||
import sun.security.krb5.PrincipalName;
|
|
||||||
|
|
||||||
class JavaxSecurityAuthKerberosAccessImpl
|
class JavaxSecurityAuthKerberosAccessImpl
|
||||||
implements JavaxSecurityAuthKerberosAccess {
|
implements JavaxSecurityAuthKerberosAccess {
|
||||||
|
@ -35,4 +33,20 @@ class JavaxSecurityAuthKerberosAccessImpl
|
||||||
KeyTab ktab) {
|
KeyTab ktab) {
|
||||||
return ktab.takeSnapshot();
|
return ktab.takeSnapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KerberosPrincipal kerberosTicketGetClientAlias(KerberosTicket t) {
|
||||||
|
return t.clientAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void kerberosTicketSetClientAlias(KerberosTicket t, KerberosPrincipal a) {
|
||||||
|
t.clientAlias = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KerberosPrincipal kerberosTicketGetServerAlias(KerberosTicket t) {
|
||||||
|
return t.serverAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void kerberosTicketSetServerAlias(KerberosTicket t, KerberosPrincipal a) {
|
||||||
|
t.serverAlias = a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2017, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -195,6 +195,10 @@ public class KerberosTicket implements Destroyable, Refreshable,
|
||||||
|
|
||||||
private transient boolean destroyed = false;
|
private transient boolean destroyed = false;
|
||||||
|
|
||||||
|
transient KerberosPrincipal clientAlias = null;
|
||||||
|
|
||||||
|
transient KerberosPrincipal serverAlias = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a {@code KerberosTicket} using credentials information that a
|
* Constructs a {@code KerberosTicket} using credentials information that a
|
||||||
* client either receives from a KDC or reads from a cache.
|
* client either receives from a KDC or reads from a cache.
|
||||||
|
@ -591,7 +595,11 @@ public class KerberosTicket implements Destroyable, Refreshable,
|
||||||
try {
|
try {
|
||||||
krb5Creds = new sun.security.krb5.Credentials(asn1Encoding,
|
krb5Creds = new sun.security.krb5.Credentials(asn1Encoding,
|
||||||
client.getName(),
|
client.getName(),
|
||||||
|
(clientAlias != null ?
|
||||||
|
clientAlias.getName() : null),
|
||||||
server.getName(),
|
server.getName(),
|
||||||
|
(serverAlias != null ?
|
||||||
|
serverAlias.getName() : null),
|
||||||
sessionKey.getEncoded(),
|
sessionKey.getEncoded(),
|
||||||
sessionKey.getKeyType(),
|
sessionKey.getKeyType(),
|
||||||
flags,
|
flags,
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -713,14 +713,14 @@ class Krb5Context implements GSSContextSpi {
|
||||||
if (subject != null &&
|
if (subject != null &&
|
||||||
!subject.isReadOnly()) {
|
!subject.isReadOnly()) {
|
||||||
/*
|
/*
|
||||||
* Store the service credentials as
|
* Store the service credentials as
|
||||||
* javax.security.auth.kerberos.KerberosTicket in
|
* javax.security.auth.kerberos.KerberosTicket in
|
||||||
* the Subject. We could wait till the context is
|
* the Subject. We could wait until the context is
|
||||||
* succesfully established; however it is easier
|
* successfully established; however it is easier
|
||||||
* to do here and there is no harm indoing it here.
|
* to do it here and there is no harm.
|
||||||
*/
|
*/
|
||||||
final KerberosTicket kt =
|
final KerberosTicket kt =
|
||||||
Krb5Util.credsToTicket(serviceCreds);
|
Krb5Util.credsToTicket(serviceCreds);
|
||||||
AccessController.doPrivileged (
|
AccessController.doPrivileged (
|
||||||
new java.security.PrivilegedAction<Void>() {
|
new java.security.PrivilegedAction<Void>() {
|
||||||
public Void run() {
|
public Void run() {
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -59,7 +59,9 @@ public class Krb5InitCredential
|
||||||
private Krb5InitCredential(Krb5NameElement name,
|
private Krb5InitCredential(Krb5NameElement name,
|
||||||
byte[] asn1Encoding,
|
byte[] asn1Encoding,
|
||||||
KerberosPrincipal client,
|
KerberosPrincipal client,
|
||||||
|
KerberosPrincipal clientAlias,
|
||||||
KerberosPrincipal server,
|
KerberosPrincipal server,
|
||||||
|
KerberosPrincipal serverAlias,
|
||||||
byte[] sessionKey,
|
byte[] sessionKey,
|
||||||
int keyType,
|
int keyType,
|
||||||
boolean[] flags,
|
boolean[] flags,
|
||||||
|
@ -80,14 +82,21 @@ public class Krb5InitCredential
|
||||||
endTime,
|
endTime,
|
||||||
renewTill,
|
renewTill,
|
||||||
clientAddresses);
|
clientAddresses);
|
||||||
|
KerberosSecrets.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketSetClientAlias(this, clientAlias);
|
||||||
|
KerberosSecrets.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketSetServerAlias(this, serverAlias);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Cache this for later use by the sun.security.krb5 package.
|
// Cache this for later use by the sun.security.krb5 package.
|
||||||
krb5Credentials = new Credentials(asn1Encoding,
|
krb5Credentials = new Credentials(asn1Encoding,
|
||||||
client.getName(),
|
client.getName(),
|
||||||
|
(clientAlias != null ?
|
||||||
|
clientAlias.getName() : null),
|
||||||
server.getName(),
|
server.getName(),
|
||||||
|
(serverAlias != null ?
|
||||||
|
serverAlias.getName() : null),
|
||||||
sessionKey,
|
sessionKey,
|
||||||
keyType,
|
keyType,
|
||||||
flags,
|
flags,
|
||||||
|
@ -110,7 +119,9 @@ public class Krb5InitCredential
|
||||||
Credentials delegatedCred,
|
Credentials delegatedCred,
|
||||||
byte[] asn1Encoding,
|
byte[] asn1Encoding,
|
||||||
KerberosPrincipal client,
|
KerberosPrincipal client,
|
||||||
|
KerberosPrincipal clientAlias,
|
||||||
KerberosPrincipal server,
|
KerberosPrincipal server,
|
||||||
|
KerberosPrincipal serverAlias,
|
||||||
byte[] sessionKey,
|
byte[] sessionKey,
|
||||||
int keyType,
|
int keyType,
|
||||||
boolean[] flags,
|
boolean[] flags,
|
||||||
|
@ -131,7 +142,10 @@ public class Krb5InitCredential
|
||||||
endTime,
|
endTime,
|
||||||
renewTill,
|
renewTill,
|
||||||
clientAddresses);
|
clientAddresses);
|
||||||
|
KerberosSecrets.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketSetClientAlias(this, clientAlias);
|
||||||
|
KerberosSecrets.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketSetServerAlias(this, serverAlias);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
// A delegated cred does not have all fields set. So do not try to
|
// A delegated cred does not have all fields set. So do not try to
|
||||||
// creat new Credentials out of the delegatedCred.
|
// creat new Credentials out of the delegatedCred.
|
||||||
|
@ -153,10 +167,18 @@ public class Krb5InitCredential
|
||||||
Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL);
|
Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KerberosPrincipal clientAlias = KerberosSecrets
|
||||||
|
.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketGetClientAlias(tgt);
|
||||||
|
KerberosPrincipal serverAlias = KerberosSecrets
|
||||||
|
.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketGetServerAlias(tgt);
|
||||||
return new Krb5InitCredential(name,
|
return new Krb5InitCredential(name,
|
||||||
tgt.getEncoded(),
|
tgt.getEncoded(),
|
||||||
tgt.getClient(),
|
tgt.getClient(),
|
||||||
|
clientAlias,
|
||||||
tgt.getServer(),
|
tgt.getServer(),
|
||||||
|
serverAlias,
|
||||||
tgt.getSessionKey().getEncoded(),
|
tgt.getSessionKey().getEncoded(),
|
||||||
tgt.getSessionKeyType(),
|
tgt.getSessionKeyType(),
|
||||||
tgt.getFlags(),
|
tgt.getFlags(),
|
||||||
|
@ -179,10 +201,14 @@ public class Krb5InitCredential
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PrincipalName cPrinc = delegatedCred.getClient();
|
PrincipalName cPrinc = delegatedCred.getClient();
|
||||||
|
PrincipalName cAPrinc = delegatedCred.getClientAlias();
|
||||||
PrincipalName sPrinc = delegatedCred.getServer();
|
PrincipalName sPrinc = delegatedCred.getServer();
|
||||||
|
PrincipalName sAPrinc = delegatedCred.getServerAlias();
|
||||||
|
|
||||||
KerberosPrincipal client = null;
|
KerberosPrincipal client = null;
|
||||||
|
KerberosPrincipal clientAlias = null;
|
||||||
KerberosPrincipal server = null;
|
KerberosPrincipal server = null;
|
||||||
|
KerberosPrincipal serverAlias = null;
|
||||||
|
|
||||||
Krb5NameElement credName = null;
|
Krb5NameElement credName = null;
|
||||||
|
|
||||||
|
@ -193,6 +219,10 @@ public class Krb5InitCredential
|
||||||
client = new KerberosPrincipal(fullName);
|
client = new KerberosPrincipal(fullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cAPrinc != null) {
|
||||||
|
clientAlias = new KerberosPrincipal(cAPrinc.getName());
|
||||||
|
}
|
||||||
|
|
||||||
// XXX Compare name to credName
|
// XXX Compare name to credName
|
||||||
|
|
||||||
if (sPrinc != null) {
|
if (sPrinc != null) {
|
||||||
|
@ -201,11 +231,17 @@ public class Krb5InitCredential
|
||||||
KerberosPrincipal.KRB_NT_SRV_INST);
|
KerberosPrincipal.KRB_NT_SRV_INST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sAPrinc != null) {
|
||||||
|
serverAlias = new KerberosPrincipal(sAPrinc.getName());
|
||||||
|
}
|
||||||
|
|
||||||
return new Krb5InitCredential(credName,
|
return new Krb5InitCredential(credName,
|
||||||
delegatedCred,
|
delegatedCred,
|
||||||
delegatedCred.getEncoded(),
|
delegatedCred.getEncoded(),
|
||||||
client,
|
client,
|
||||||
|
clientAlias,
|
||||||
server,
|
server,
|
||||||
|
serverAlias,
|
||||||
sessionKey.getBytes(),
|
sessionKey.getBytes(),
|
||||||
sessionKey.getEType(),
|
sessionKey.getEType(),
|
||||||
delegatedCred.getFlags(),
|
delegatedCred.getFlags(),
|
||||||
|
|
|
@ -132,7 +132,7 @@ public class Krb5Util {
|
||||||
|
|
||||||
public static KerberosTicket credsToTicket(Credentials serviceCreds) {
|
public static KerberosTicket credsToTicket(Credentials serviceCreds) {
|
||||||
EncryptionKey sessionKey = serviceCreds.getSessionKey();
|
EncryptionKey sessionKey = serviceCreds.getSessionKey();
|
||||||
return new KerberosTicket(
|
KerberosTicket kt = new KerberosTicket(
|
||||||
serviceCreds.getEncoded(),
|
serviceCreds.getEncoded(),
|
||||||
new KerberosPrincipal(serviceCreds.getClient().getName()),
|
new KerberosPrincipal(serviceCreds.getClient().getName()),
|
||||||
new KerberosPrincipal(serviceCreds.getServer().getName(),
|
new KerberosPrincipal(serviceCreds.getServer().getName(),
|
||||||
|
@ -145,14 +145,35 @@ public class Krb5Util {
|
||||||
serviceCreds.getEndTime(),
|
serviceCreds.getEndTime(),
|
||||||
serviceCreds.getRenewTill(),
|
serviceCreds.getRenewTill(),
|
||||||
serviceCreds.getClientAddresses());
|
serviceCreds.getClientAddresses());
|
||||||
|
PrincipalName clientAlias = serviceCreds.getClientAlias();
|
||||||
|
PrincipalName serverAlias = serviceCreds.getServerAlias();
|
||||||
|
if (clientAlias != null) {
|
||||||
|
KerberosSecrets.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketSetClientAlias(kt, new KerberosPrincipal(
|
||||||
|
clientAlias.getName(), clientAlias.getNameType()));
|
||||||
|
}
|
||||||
|
if (serverAlias != null) {
|
||||||
|
KerberosSecrets.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketSetServerAlias(kt, new KerberosPrincipal(
|
||||||
|
serverAlias.getName(), serverAlias.getNameType()));
|
||||||
|
}
|
||||||
|
return kt;
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Credentials ticketToCreds(KerberosTicket kerbTicket)
|
public static Credentials ticketToCreds(KerberosTicket kerbTicket)
|
||||||
throws KrbException, IOException {
|
throws KrbException, IOException {
|
||||||
|
KerberosPrincipal clientAlias = KerberosSecrets
|
||||||
|
.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketGetClientAlias(kerbTicket);
|
||||||
|
KerberosPrincipal serverAlias = KerberosSecrets
|
||||||
|
.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketGetServerAlias(kerbTicket);
|
||||||
return new Credentials(
|
return new Credentials(
|
||||||
kerbTicket.getEncoded(),
|
kerbTicket.getEncoded(),
|
||||||
kerbTicket.getClient().getName(),
|
kerbTicket.getClient().getName(),
|
||||||
|
(clientAlias != null ? clientAlias.getName() : null),
|
||||||
kerbTicket.getServer().getName(),
|
kerbTicket.getServer().getName(),
|
||||||
|
(serverAlias != null ? serverAlias.getName() : null),
|
||||||
kerbTicket.getSessionKey().getEncoded(),
|
kerbTicket.getSessionKey().getEncoded(),
|
||||||
kerbTicket.getSessionKeyType(),
|
kerbTicket.getSessionKeyType(),
|
||||||
kerbTicket.getFlags(),
|
kerbTicket.getFlags(),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
package sun.security.jgss.krb5;
|
package sun.security.jgss.krb5;
|
||||||
|
|
||||||
|
import sun.security.krb5.KerberosSecrets;
|
||||||
|
|
||||||
import javax.security.auth.kerberos.KerberosTicket;
|
import javax.security.auth.kerberos.KerberosTicket;
|
||||||
import javax.security.auth.kerberos.KerberosKey;
|
import javax.security.auth.kerberos.KerberosKey;
|
||||||
import javax.security.auth.Subject;
|
import javax.security.auth.Subject;
|
||||||
|
@ -182,24 +184,45 @@ class SubjectComber {
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
KerberosPrincipal serverAlias = KerberosSecrets
|
||||||
|
.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketGetServerAlias(ticket);
|
||||||
if (serverPrincipal == null ||
|
if (serverPrincipal == null ||
|
||||||
ticket.getServer().getName().equals(serverPrincipal)) {
|
ticket.getServer().getName().equals(serverPrincipal) ||
|
||||||
|
(serverAlias != null &&
|
||||||
|
serverPrincipal.equals(
|
||||||
|
serverAlias.getName()))) {
|
||||||
|
KerberosPrincipal clientAlias = KerberosSecrets
|
||||||
|
.getJavaxSecurityAuthKerberosAccess()
|
||||||
|
.kerberosTicketGetClientAlias(ticket);
|
||||||
if (clientPrincipal == null ||
|
if (clientPrincipal == null ||
|
||||||
clientPrincipal.equals(
|
clientPrincipal.equals(
|
||||||
ticket.getClient().getName())) {
|
ticket.getClient().getName()) ||
|
||||||
|
(clientAlias != null &&
|
||||||
|
clientPrincipal.equals(
|
||||||
|
clientAlias.getName()))) {
|
||||||
if (oneOnly) {
|
if (oneOnly) {
|
||||||
return ticket;
|
return ticket;
|
||||||
} else {
|
} else {
|
||||||
// Record names so that tickets will
|
// Record names so that tickets will
|
||||||
// all belong to same principals
|
// all belong to same principals
|
||||||
if (clientPrincipal == null) {
|
if (clientPrincipal == null) {
|
||||||
clientPrincipal =
|
if (clientAlias == null) {
|
||||||
ticket.getClient().getName();
|
clientPrincipal =
|
||||||
|
ticket.getClient().getName();
|
||||||
|
} else {
|
||||||
|
clientPrincipal =
|
||||||
|
clientAlias.getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (serverPrincipal == null) {
|
if (serverPrincipal == null) {
|
||||||
serverPrincipal =
|
if (serverAlias == null) {
|
||||||
ticket.getServer().getName();
|
serverPrincipal =
|
||||||
|
ticket.getServer().getName();
|
||||||
|
} else {
|
||||||
|
serverPrincipal =
|
||||||
|
serverAlias.getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
answer.add(credClass.cast(ticket));
|
answer.add(credClass.cast(ticket));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -49,7 +49,9 @@ public class Credentials {
|
||||||
|
|
||||||
Ticket ticket;
|
Ticket ticket;
|
||||||
PrincipalName client;
|
PrincipalName client;
|
||||||
|
PrincipalName clientAlias;
|
||||||
PrincipalName server;
|
PrincipalName server;
|
||||||
|
PrincipalName serverAlias;
|
||||||
EncryptionKey key;
|
EncryptionKey key;
|
||||||
TicketFlags flags;
|
TicketFlags flags;
|
||||||
KerberosTime authTime;
|
KerberosTime authTime;
|
||||||
|
@ -69,7 +71,9 @@ public class Credentials {
|
||||||
|
|
||||||
public Credentials(Ticket new_ticket,
|
public Credentials(Ticket new_ticket,
|
||||||
PrincipalName new_client,
|
PrincipalName new_client,
|
||||||
|
PrincipalName new_client_alias,
|
||||||
PrincipalName new_server,
|
PrincipalName new_server,
|
||||||
|
PrincipalName new_server_alias,
|
||||||
EncryptionKey new_key,
|
EncryptionKey new_key,
|
||||||
TicketFlags new_flags,
|
TicketFlags new_flags,
|
||||||
KerberosTime authTime,
|
KerberosTime authTime,
|
||||||
|
@ -78,14 +82,17 @@ public class Credentials {
|
||||||
KerberosTime renewTill,
|
KerberosTime renewTill,
|
||||||
HostAddresses cAddr,
|
HostAddresses cAddr,
|
||||||
AuthorizationData authzData) {
|
AuthorizationData authzData) {
|
||||||
this(new_ticket, new_client, new_server, new_key, new_flags,
|
this(new_ticket, new_client, new_client_alias, new_server,
|
||||||
authTime, new_startTime, new_endTime, renewTill, cAddr);
|
new_server_alias, new_key, new_flags, authTime,
|
||||||
|
new_startTime, new_endTime, renewTill, cAddr);
|
||||||
this.authzData = authzData;
|
this.authzData = authzData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Credentials(Ticket new_ticket,
|
public Credentials(Ticket new_ticket,
|
||||||
PrincipalName new_client,
|
PrincipalName new_client,
|
||||||
|
PrincipalName new_client_alias,
|
||||||
PrincipalName new_server,
|
PrincipalName new_server,
|
||||||
|
PrincipalName new_server_alias,
|
||||||
EncryptionKey new_key,
|
EncryptionKey new_key,
|
||||||
TicketFlags new_flags,
|
TicketFlags new_flags,
|
||||||
KerberosTime authTime,
|
KerberosTime authTime,
|
||||||
|
@ -95,7 +102,9 @@ public class Credentials {
|
||||||
HostAddresses cAddr) {
|
HostAddresses cAddr) {
|
||||||
ticket = new_ticket;
|
ticket = new_ticket;
|
||||||
client = new_client;
|
client = new_client;
|
||||||
|
clientAlias = new_client_alias;
|
||||||
server = new_server;
|
server = new_server;
|
||||||
|
serverAlias = new_server_alias;
|
||||||
key = new_key;
|
key = new_key;
|
||||||
flags = new_flags;
|
flags = new_flags;
|
||||||
this.authTime = authTime;
|
this.authTime = authTime;
|
||||||
|
@ -107,7 +116,9 @@ public class Credentials {
|
||||||
|
|
||||||
public Credentials(byte[] encoding,
|
public Credentials(byte[] encoding,
|
||||||
String client,
|
String client,
|
||||||
|
String clientAlias,
|
||||||
String server,
|
String server,
|
||||||
|
String serverAlias,
|
||||||
byte[] keyBytes,
|
byte[] keyBytes,
|
||||||
int keyType,
|
int keyType,
|
||||||
boolean[] flags,
|
boolean[] flags,
|
||||||
|
@ -118,7 +129,11 @@ public class Credentials {
|
||||||
InetAddress[] cAddrs) throws KrbException, IOException {
|
InetAddress[] cAddrs) throws KrbException, IOException {
|
||||||
this(new Ticket(encoding),
|
this(new Ticket(encoding),
|
||||||
new PrincipalName(client, PrincipalName.KRB_NT_PRINCIPAL),
|
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),
|
new PrincipalName(server, PrincipalName.KRB_NT_SRV_INST),
|
||||||
|
(serverAlias == null? null : new PrincipalName(serverAlias,
|
||||||
|
PrincipalName.KRB_NT_SRV_INST)),
|
||||||
new EncryptionKey(keyType, keyBytes),
|
new EncryptionKey(keyType, keyBytes),
|
||||||
(flags == null? null: new TicketFlags(flags)),
|
(flags == null? null: new TicketFlags(flags)),
|
||||||
(authTime == null? null: new KerberosTime(authTime)),
|
(authTime == null? null: new KerberosTime(authTime)),
|
||||||
|
@ -143,10 +158,18 @@ public class Credentials {
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final PrincipalName getClientAlias() {
|
||||||
|
return clientAlias;
|
||||||
|
}
|
||||||
|
|
||||||
public final PrincipalName getServer() {
|
public final PrincipalName getServer() {
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final PrincipalName getServerAlias() {
|
||||||
|
return serverAlias;
|
||||||
|
}
|
||||||
|
|
||||||
public final EncryptionKey getSessionKey() {
|
public final EncryptionKey getSessionKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
@ -262,6 +285,7 @@ public class Credentials {
|
||||||
return new KrbTgsReq(options,
|
return new KrbTgsReq(options,
|
||||||
this,
|
this,
|
||||||
server,
|
server,
|
||||||
|
serverAlias,
|
||||||
null, // from
|
null, // from
|
||||||
null, // till
|
null, // till
|
||||||
null, // rtime
|
null, // rtime
|
||||||
|
@ -484,7 +508,11 @@ public class Credentials {
|
||||||
public static void printDebug(Credentials c) {
|
public static void printDebug(Credentials c) {
|
||||||
System.out.println(">>> DEBUG: ----Credentials----");
|
System.out.println(">>> DEBUG: ----Credentials----");
|
||||||
System.out.println("\tclient: " + c.client.toString());
|
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());
|
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());
|
System.out.println("\tticket: sname: " + c.ticket.sname.toString());
|
||||||
if (c.startTime != null) {
|
if (c.startTime != null) {
|
||||||
System.out.println("\tstartTime: " + c.startTime.getTime());
|
System.out.println("\tstartTime: " + c.startTime.getTime());
|
||||||
|
@ -512,7 +540,11 @@ public class Credentials {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder("Credentials:");
|
StringBuilder sb = new StringBuilder("Credentials:");
|
||||||
sb.append( "\n client=").append(client);
|
sb.append( "\n client=").append(client);
|
||||||
|
if (clientAlias != null)
|
||||||
|
sb.append( "\n clientAlias=").append(clientAlias);
|
||||||
sb.append( "\n server=").append(server);
|
sb.append( "\n server=").append(server);
|
||||||
|
if (serverAlias != null)
|
||||||
|
sb.append( "\n serverAlias=").append(serverAlias);
|
||||||
if (authTime != null) {
|
if (authTime != null) {
|
||||||
sb.append("\n authTime=").append(authTime);
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
package sun.security.krb5;
|
package sun.security.krb5;
|
||||||
|
|
||||||
|
import javax.security.auth.kerberos.KerberosPrincipal;
|
||||||
|
import javax.security.auth.kerberos.KerberosTicket;
|
||||||
import javax.security.auth.kerberos.KeyTab;
|
import javax.security.auth.kerberos.KeyTab;
|
||||||
import sun.security.krb5.EncryptionKey;
|
import sun.security.krb5.EncryptionKey;
|
||||||
import sun.security.krb5.PrincipalName;
|
import sun.security.krb5.PrincipalName;
|
||||||
|
@ -39,4 +41,12 @@ public interface JavaxSecurityAuthKerberosAccess {
|
||||||
*/
|
*/
|
||||||
public sun.security.krb5.internal.ktab.KeyTab keyTabTakeSnapshot(
|
public sun.security.krb5.internal.ktab.KeyTab keyTabTakeSnapshot(
|
||||||
KeyTab ktab);
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -363,7 +363,9 @@ public class KrbApReq {
|
||||||
creds = new Credentials(
|
creds = new Credentials(
|
||||||
apReqMessg.ticket,
|
apReqMessg.ticket,
|
||||||
authenticator.cname,
|
authenticator.cname,
|
||||||
|
null,
|
||||||
apReqMessg.ticket.sname,
|
apReqMessg.ticket.sname,
|
||||||
|
null,
|
||||||
enc_ticketPart.key,
|
enc_ticketPart.key,
|
||||||
enc_ticketPart.flags,
|
enc_ticketPart.flags,
|
||||||
enc_ticketPart.authtime,
|
enc_ticketPart.authtime,
|
||||||
|
|
|
@ -118,7 +118,7 @@ class KrbAsRep extends KrbKdcRep {
|
||||||
"Cannot find key for type/kvno to decrypt AS REP - " +
|
"Cannot find key for type/kvno to decrypt AS REP - " +
|
||||||
EType.toString(encPartKeyType) + "/" + encPartKvno);
|
EType.toString(encPartKeyType) + "/" + encPartKvno);
|
||||||
}
|
}
|
||||||
decrypt(dkey, asReq);
|
decrypt(dkey, asReq, cname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -136,7 +136,7 @@ class KrbAsRep extends KrbKdcRep {
|
||||||
password,
|
password,
|
||||||
encPartKeyType,
|
encPartKeyType,
|
||||||
PAData.getSaltAndParams(encPartKeyType, rep.pAData));
|
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 dkey the decryption key to use
|
||||||
* @param asReq the original AS-REQ sent, used to validate AS-REP
|
* @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 {
|
throws KrbException, Asn1Exception, IOException {
|
||||||
byte[] enc_as_rep_bytes = rep.encPart.decrypt(dkey,
|
byte[] enc_as_rep_bytes = rep.encPart.decrypt(dkey,
|
||||||
KeyUsage.KU_ENC_AS_REP_PART);
|
KeyUsage.KU_ENC_AS_REP_PART);
|
||||||
|
@ -157,10 +158,16 @@ class KrbAsRep extends KrbKdcRep {
|
||||||
ASReq req = asReq.getMessage();
|
ASReq req = asReq.getMessage();
|
||||||
check(true, req, rep, dkey);
|
check(true, req, rep, dkey);
|
||||||
|
|
||||||
|
PrincipalName clientAlias = cname;
|
||||||
|
if (clientAlias.equals(rep.cname))
|
||||||
|
clientAlias = null;
|
||||||
|
|
||||||
creds = new Credentials(
|
creds = new Credentials(
|
||||||
rep.ticket,
|
rep.ticket,
|
||||||
rep.cname,
|
rep.cname,
|
||||||
|
clientAlias,
|
||||||
enc_part.sname,
|
enc_part.sname,
|
||||||
|
null, // No server alias expected in a TGT
|
||||||
enc_part.key,
|
enc_part.key,
|
||||||
enc_part.flags,
|
enc_part.flags,
|
||||||
enc_part.authtime,
|
enc_part.authtime,
|
||||||
|
|
|
@ -68,6 +68,7 @@ public final class KrbAsReqBuilder {
|
||||||
// Common data for AS-REQ fields
|
// Common data for AS-REQ fields
|
||||||
private KDCOptions options;
|
private KDCOptions options;
|
||||||
private PrincipalName cname;
|
private PrincipalName cname;
|
||||||
|
private PrincipalName refCname; // May be changed by referrals
|
||||||
private PrincipalName sname;
|
private PrincipalName sname;
|
||||||
private KerberosTime from;
|
private KerberosTime from;
|
||||||
private KerberosTime till;
|
private KerberosTime till;
|
||||||
|
@ -100,6 +101,7 @@ public final class KrbAsReqBuilder {
|
||||||
private void init(PrincipalName cname)
|
private void init(PrincipalName cname)
|
||||||
throws KrbException {
|
throws KrbException {
|
||||||
this.cname = cname;
|
this.cname = cname;
|
||||||
|
this.refCname = cname;
|
||||||
state = State.INIT;
|
state = State.INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +286,7 @@ public final class KrbAsReqBuilder {
|
||||||
}
|
}
|
||||||
return new KrbAsReq(key,
|
return new KrbAsReq(key,
|
||||||
options,
|
options,
|
||||||
cname,
|
refCname,
|
||||||
sname,
|
sname,
|
||||||
from,
|
from,
|
||||||
till,
|
till,
|
||||||
|
@ -334,7 +336,7 @@ public final class KrbAsReqBuilder {
|
||||||
ReferralsState referralsState = new ReferralsState();
|
ReferralsState referralsState = new ReferralsState();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (referralsState.refreshComm()) {
|
if (referralsState.refreshComm()) {
|
||||||
comm = new KdcComm(cname.getRealmAsString());
|
comm = new KdcComm(refCname.getRealmAsString());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
req = build(pakey, referralsState);
|
req = build(pakey, referralsState);
|
||||||
|
@ -384,7 +386,7 @@ public final class KrbAsReqBuilder {
|
||||||
|
|
||||||
ReferralsState() throws KrbException {
|
ReferralsState() throws KrbException {
|
||||||
if (Config.DISABLE_REFERRALS) {
|
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" +
|
throw new KrbException("NT-ENTERPRISE principals only allowed" +
|
||||||
" when referrals are enabled.");
|
" when referrals are enabled.");
|
||||||
}
|
}
|
||||||
|
@ -402,15 +404,15 @@ public final class KrbAsReqBuilder {
|
||||||
if (req.getMessage().reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) &&
|
if (req.getMessage().reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) &&
|
||||||
referredRealm != null && referredRealm.toString().length() > 0 &&
|
referredRealm != null && referredRealm.toString().length() > 0 &&
|
||||||
count < Config.MAX_REFERRALS) {
|
count < Config.MAX_REFERRALS) {
|
||||||
cname = new PrincipalName(cname.getNameType(),
|
refCname = new PrincipalName(refCname.getNameType(),
|
||||||
cname.getNameStrings(), referredRealm);
|
refCname.getNameStrings(), referredRealm);
|
||||||
refreshComm = true;
|
refreshComm = true;
|
||||||
count++;
|
count++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count < Config.MAX_REFERRALS &&
|
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.
|
// Server may raise an error if CANONICALIZE is true.
|
||||||
// Try CANONICALIZE false.
|
// Try CANONICALIZE false.
|
||||||
enabled = 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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);
|
options.set(KDCOptions.FORWARDABLE, true);
|
||||||
|
|
||||||
KrbTgsReq tgsReq = new KrbTgsReq(options, tgt, tgService,
|
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, // No easy way to get addresses right
|
||||||
null, null, null);
|
null, null, null);
|
||||||
credMessg = createMessage(tgsReq.sendAndGetCreds(), key);
|
credMessg = createMessage(tgsReq.sendAndGetCreds(), key);
|
||||||
|
@ -152,7 +152,7 @@ public class KrbCred {
|
||||||
+ " endtime=" + endtime
|
+ " endtime=" + endtime
|
||||||
+ "renewTill=" + renewTill);
|
+ "renewTill=" + renewTill);
|
||||||
}
|
}
|
||||||
creds = new Credentials(ticket, pname, sname, credInfoKey,
|
creds = new Credentials(ticket, pname, null, sname, null, credInfoKey,
|
||||||
flags, authtime, starttime, endtime, renewTill, caddr);
|
flags, authtime, starttime, endtime, renewTill, caddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,9 +86,20 @@ public class KrbTgsRep extends KrbKdcRep {
|
||||||
|
|
||||||
check(false, req, rep, tgsReq.tgsReqKey);
|
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,
|
this.creds = new Credentials(rep.ticket,
|
||||||
rep.cname,
|
rep.cname,
|
||||||
|
tgsReq.getClientAlias(),
|
||||||
enc_part.sname,
|
enc_part.sname,
|
||||||
|
serverAlias,
|
||||||
enc_part.key,
|
enc_part.key,
|
||||||
enc_part.flags,
|
enc_part.flags,
|
||||||
enc_part.authtime,
|
enc_part.authtime,
|
||||||
|
@ -111,4 +122,16 @@ public class KrbTgsRep extends KrbKdcRep {
|
||||||
sun.security.krb5.internal.ccache.Credentials setCredentials() {
|
sun.security.krb5.internal.ccache.Credentials setCredentials() {
|
||||||
return new sun.security.krb5.internal.ccache.Credentials(rep, secondTicket);
|
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 {
|
public class KrbTgsReq {
|
||||||
|
|
||||||
private PrincipalName princName;
|
private PrincipalName princName;
|
||||||
|
private PrincipalName clientAlias;
|
||||||
private PrincipalName servName;
|
private PrincipalName servName;
|
||||||
|
private PrincipalName serverAlias;
|
||||||
private TGSReq tgsReqMessg;
|
private TGSReq tgsReqMessg;
|
||||||
private KerberosTime ctime;
|
private KerberosTime ctime;
|
||||||
private Ticket secondTicket = null;
|
private Ticket secondTicket = null;
|
||||||
|
@ -59,13 +61,16 @@ public class KrbTgsReq {
|
||||||
|
|
||||||
// Used in CredentialsUtil
|
// Used in CredentialsUtil
|
||||||
public KrbTgsReq(KDCOptions options, Credentials asCreds,
|
public KrbTgsReq(KDCOptions options, Credentials asCreds,
|
||||||
PrincipalName cname, PrincipalName sname,
|
PrincipalName cname, PrincipalName clientAlias,
|
||||||
|
PrincipalName sname, PrincipalName serverAlias,
|
||||||
Ticket[] additionalTickets, PAData[] extraPAs)
|
Ticket[] additionalTickets, PAData[] extraPAs)
|
||||||
throws KrbException, IOException {
|
throws KrbException, IOException {
|
||||||
this(options,
|
this(options,
|
||||||
asCreds,
|
asCreds,
|
||||||
cname,
|
cname,
|
||||||
|
clientAlias,
|
||||||
sname,
|
sname,
|
||||||
|
serverAlias,
|
||||||
null, // KerberosTime from
|
null, // KerberosTime from
|
||||||
null, // KerberosTime till
|
null, // KerberosTime till
|
||||||
null, // KerberosTime rtime
|
null, // KerberosTime rtime
|
||||||
|
@ -82,6 +87,7 @@ public class KrbTgsReq {
|
||||||
KDCOptions options,
|
KDCOptions options,
|
||||||
Credentials asCreds,
|
Credentials asCreds,
|
||||||
PrincipalName sname,
|
PrincipalName sname,
|
||||||
|
PrincipalName serverAlias,
|
||||||
KerberosTime from,
|
KerberosTime from,
|
||||||
KerberosTime till,
|
KerberosTime till,
|
||||||
KerberosTime rtime,
|
KerberosTime rtime,
|
||||||
|
@ -90,16 +96,18 @@ public class KrbTgsReq {
|
||||||
AuthorizationData authorizationData,
|
AuthorizationData authorizationData,
|
||||||
Ticket[] additionalTickets,
|
Ticket[] additionalTickets,
|
||||||
EncryptionKey subKey) throws KrbException, IOException {
|
EncryptionKey subKey) throws KrbException, IOException {
|
||||||
this(options, asCreds, asCreds.getClient(), sname,
|
this(options, asCreds, asCreds.getClient(), asCreds.getClientAlias(),
|
||||||
from, till, rtime, eTypes, addresses,
|
sname, serverAlias, from, till, rtime, eTypes,
|
||||||
authorizationData, additionalTickets, subKey, null);
|
addresses, authorizationData, additionalTickets, subKey, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KrbTgsReq(
|
private KrbTgsReq(
|
||||||
KDCOptions options,
|
KDCOptions options,
|
||||||
Credentials asCreds,
|
Credentials asCreds,
|
||||||
PrincipalName cname,
|
PrincipalName cname,
|
||||||
|
PrincipalName clientAlias,
|
||||||
PrincipalName sname,
|
PrincipalName sname,
|
||||||
|
PrincipalName serverAlias,
|
||||||
KerberosTime from,
|
KerberosTime from,
|
||||||
KerberosTime till,
|
KerberosTime till,
|
||||||
KerberosTime rtime,
|
KerberosTime rtime,
|
||||||
|
@ -111,7 +119,9 @@ public class KrbTgsReq {
|
||||||
PAData[] extraPAs) throws KrbException, IOException {
|
PAData[] extraPAs) throws KrbException, IOException {
|
||||||
|
|
||||||
princName = cname;
|
princName = cname;
|
||||||
|
this.clientAlias = clientAlias;
|
||||||
servName = sname;
|
servName = sname;
|
||||||
|
this.serverAlias = serverAlias;
|
||||||
ctime = KerberosTime.now();
|
ctime = KerberosTime.now();
|
||||||
|
|
||||||
// check if they are valid arguments. The optional fields
|
// check if they are valid arguments. The optional fields
|
||||||
|
@ -365,6 +375,14 @@ public class KrbTgsReq {
|
||||||
return secondTicket;
|
return secondTicket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrincipalName getClientAlias() {
|
||||||
|
return clientAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrincipalName getServerAlias() {
|
||||||
|
return serverAlias;
|
||||||
|
}
|
||||||
|
|
||||||
private static void debug(String message) {
|
private static void debug(String message) {
|
||||||
// System.err.println(">>> KrbTgsReq: " + message);
|
// System.err.println(">>> KrbTgsReq: " + message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -564,7 +564,9 @@ public class PrincipalName implements Cloneable {
|
||||||
for (int i = 0; i < nameStrings.length; i++) {
|
for (int i = 0; i < nameStrings.length; i++) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
str.append("/");
|
str.append("/");
|
||||||
str.append(nameStrings[i]);
|
String n = nameStrings[i];
|
||||||
|
n = n.replace("@", "\\@");
|
||||||
|
str.append(n);
|
||||||
}
|
}
|
||||||
str.append("@");
|
str.append("@");
|
||||||
str.append(nameRealm.toString());
|
str.append(nameRealm.toString());
|
||||||
|
|
|
@ -284,8 +284,9 @@ public class CredentialsUtil {
|
||||||
// Try CANONICALIZE false.
|
// Try CANONICALIZE false.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return serviceCredsSingle(options, asCreds,
|
return serviceCredsSingle(options, asCreds, cname,
|
||||||
cname, sname, additionalTickets, extraPAs);
|
asCreds.getClientAlias(), sname, sname, additionalTickets,
|
||||||
|
extraPAs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -300,26 +301,29 @@ public class CredentialsUtil {
|
||||||
options = new KDCOptions(options.toBooleanArray());
|
options = new KDCOptions(options.toBooleanArray());
|
||||||
options.set(KDCOptions.CANONICALIZE, true);
|
options.set(KDCOptions.CANONICALIZE, true);
|
||||||
PrincipalName cSname = sname;
|
PrincipalName cSname = sname;
|
||||||
|
PrincipalName refSname = sname; // May change with referrals
|
||||||
Credentials creds = null;
|
Credentials creds = null;
|
||||||
boolean isReferral = false;
|
boolean isReferral = false;
|
||||||
List<String> referrals = new LinkedList<>();
|
List<String> referrals = new LinkedList<>();
|
||||||
|
PrincipalName clientAlias = asCreds.getClientAlias();
|
||||||
while (referrals.size() <= Config.MAX_REFERRALS) {
|
while (referrals.size() <= Config.MAX_REFERRALS) {
|
||||||
ReferralsCache.ReferralCacheEntry ref =
|
ReferralsCache.ReferralCacheEntry ref =
|
||||||
ReferralsCache.get(sname, cSname.getRealmString());
|
ReferralsCache.get(cname, sname, refSname.getRealmString());
|
||||||
String toRealm = null;
|
String toRealm = null;
|
||||||
if (ref == null) {
|
if (ref == null) {
|
||||||
creds = serviceCredsSingle(options, asCreds,
|
creds = serviceCredsSingle(options, asCreds, cname,
|
||||||
cname, cSname, additionalTickets, extraPAs);
|
clientAlias, refSname, cSname, additionalTickets,
|
||||||
|
extraPAs);
|
||||||
PrincipalName server = creds.getServer();
|
PrincipalName server = creds.getServer();
|
||||||
if (!cSname.equals(server)) {
|
if (!refSname.equals(server)) {
|
||||||
String[] serverNameStrings = server.getNameStrings();
|
String[] serverNameStrings = server.getNameStrings();
|
||||||
if (serverNameStrings.length == 2 &&
|
if (serverNameStrings.length == 2 &&
|
||||||
serverNameStrings[0].equals(
|
serverNameStrings[0].equals(
|
||||||
PrincipalName.TGS_DEFAULT_SRV_NAME) &&
|
PrincipalName.TGS_DEFAULT_SRV_NAME) &&
|
||||||
!cSname.getRealmAsString().equals(serverNameStrings[1])) {
|
!refSname.getRealmAsString().equals(serverNameStrings[1])) {
|
||||||
// Server Name (sname) has the following format:
|
// Server Name (sname) has the following format:
|
||||||
// krbtgt/TO-REALM.COM@FROM-REALM.COM
|
// krbtgt/TO-REALM.COM@FROM-REALM.COM
|
||||||
ReferralsCache.put(sname, server.getRealmString(),
|
ReferralsCache.put(cname, sname, server.getRealmString(),
|
||||||
serverNameStrings[1], creds);
|
serverNameStrings[1], creds);
|
||||||
toRealm = serverNameStrings[1];
|
toRealm = serverNameStrings[1];
|
||||||
isReferral = true;
|
isReferral = true;
|
||||||
|
@ -336,8 +340,8 @@ public class CredentialsUtil {
|
||||||
// Referrals loop detected
|
// Referrals loop detected
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
cSname = new PrincipalName(cSname.getNameString(),
|
refSname = new PrincipalName(refSname.getNameString(),
|
||||||
cSname.getNameType(), toRealm);
|
refSname.getNameType(), toRealm);
|
||||||
referrals.add(toRealm);
|
referrals.add(toRealm);
|
||||||
isReferral = false;
|
isReferral = false;
|
||||||
continue;
|
continue;
|
||||||
|
@ -356,14 +360,15 @@ public class CredentialsUtil {
|
||||||
*/
|
*/
|
||||||
private static Credentials serviceCredsSingle(
|
private static Credentials serviceCredsSingle(
|
||||||
KDCOptions options, Credentials asCreds,
|
KDCOptions options, Credentials asCreds,
|
||||||
PrincipalName cname, PrincipalName sname,
|
PrincipalName cname, PrincipalName clientAlias,
|
||||||
|
PrincipalName refSname, PrincipalName sname,
|
||||||
Ticket[] additionalTickets, PAData[] extraPAs)
|
Ticket[] additionalTickets, PAData[] extraPAs)
|
||||||
throws KrbException, IOException {
|
throws KrbException, IOException {
|
||||||
Credentials theCreds = null;
|
Credentials theCreds = null;
|
||||||
boolean[] okAsDelegate = new boolean[]{true};
|
boolean[] okAsDelegate = new boolean[]{true};
|
||||||
String[] serverAsCredsNames = asCreds.getServer().getNameStrings();
|
String[] serverAsCredsNames = asCreds.getServer().getNameStrings();
|
||||||
String tgtRealm = serverAsCredsNames[1];
|
String tgtRealm = serverAsCredsNames[1];
|
||||||
String serviceRealm = sname.getRealmString();
|
String serviceRealm = refSname.getRealmString();
|
||||||
if (!serviceRealm.equals(tgtRealm)) {
|
if (!serviceRealm.equals(tgtRealm)) {
|
||||||
// This is a cross-realm service request
|
// This is a cross-realm service request
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -390,8 +395,8 @@ public class CredentialsUtil {
|
||||||
System.out.println(">>> Credentials serviceCredsSingle:" +
|
System.out.println(">>> Credentials serviceCredsSingle:" +
|
||||||
" same realm");
|
" same realm");
|
||||||
}
|
}
|
||||||
KrbTgsReq req = new KrbTgsReq(options, asCreds,
|
KrbTgsReq req = new KrbTgsReq(options, asCreds, cname, clientAlias,
|
||||||
cname, sname, additionalTickets, extraPAs);
|
refSname, sname, additionalTickets, extraPAs);
|
||||||
theCreds = req.sendAndGetCreds();
|
theCreds = req.sendAndGetCreds();
|
||||||
if (theCreds != null) {
|
if (theCreds != null) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
|
|
@ -139,7 +139,7 @@ public class KRBError implements java.io.Serializable {
|
||||||
sTime = new_sTime;
|
sTime = new_sTime;
|
||||||
suSec = new_suSec;
|
suSec = new_suSec;
|
||||||
errorCode = new_errorCode;
|
errorCode = new_errorCode;
|
||||||
crealm = new_cname.getRealm();
|
crealm = new_cname != null ? new_cname.getRealm() : null;
|
||||||
cname = new_cname;
|
cname = new_cname;
|
||||||
sname = new_sname;
|
sname = new_sname;
|
||||||
eText = new_eText;
|
eText = new_eText;
|
||||||
|
@ -168,7 +168,7 @@ public class KRBError implements java.io.Serializable {
|
||||||
sTime = new_sTime;
|
sTime = new_sTime;
|
||||||
suSec = new_suSec;
|
suSec = new_suSec;
|
||||||
errorCode = new_errorCode;
|
errorCode = new_errorCode;
|
||||||
crealm = new_cname.getRealm();
|
crealm = new_cname != null ? new_cname.getRealm() : null;
|
||||||
cname = new_cname;
|
cname = new_cname;
|
||||||
sname = new_sname;
|
sname = new_sname;
|
||||||
eText = new_eText;
|
eText = new_eText;
|
||||||
|
|
|
@ -45,8 +45,27 @@ import sun.security.krb5.PrincipalName;
|
||||||
*/
|
*/
|
||||||
final class ReferralsCache {
|
final class ReferralsCache {
|
||||||
|
|
||||||
private static Map<PrincipalName, Map<String, ReferralCacheEntry>> referralsMap =
|
private static Map<ReferralCacheKey, Map<String, ReferralCacheEntry>>
|
||||||
new HashMap<>();
|
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 {
|
static final class ReferralCacheEntry {
|
||||||
private final Credentials creds;
|
private final Credentials creds;
|
||||||
|
@ -64,8 +83,9 @@ final class ReferralsCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a new referral entry to the cache, including: service principal,
|
* Add a new referral entry to the cache, including: client principal,
|
||||||
* source KDC realm, destination KDC realm and referral TGT.
|
* 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
|
* If a loop is generated when adding the new referral, the first hop is
|
||||||
* automatically removed. For example, let's assume that adding a
|
* 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 -> REALM-3.COM -> REALM-1.COM. Then,
|
||||||
* REALM-1.COM -> REALM-2.COM referral entry is removed from the cache.
|
* 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) {
|
String fromRealm, String toRealm, Credentials creds) {
|
||||||
pruneExpired(service);
|
ReferralCacheKey k = new ReferralCacheKey(cname, service);
|
||||||
|
pruneExpired(k);
|
||||||
if (creds.getEndTime().before(new Date())) {
|
if (creds.getEndTime().before(new Date())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Map<String, ReferralCacheEntry> entries = referralsMap.get(service);
|
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
|
||||||
if (entries == null) {
|
if (entries == null) {
|
||||||
entries = new HashMap<String, ReferralCacheEntry>();
|
entries = new HashMap<String, ReferralCacheEntry>();
|
||||||
referralsMap.put(service, entries);
|
referralsMap.put(k, entries);
|
||||||
}
|
}
|
||||||
entries.remove(fromRealm);
|
entries.remove(fromRealm);
|
||||||
ReferralCacheEntry newEntry = new ReferralCacheEntry(creds, toRealm);
|
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
|
* Obtain a referral entry from the cache given a client principal,
|
||||||
* source KDC realm.
|
* service principal and a source KDC realm.
|
||||||
*/
|
*/
|
||||||
static synchronized ReferralCacheEntry get(PrincipalName service,
|
static synchronized ReferralCacheEntry get(PrincipalName cname,
|
||||||
String fromRealm) {
|
PrincipalName service, String fromRealm) {
|
||||||
pruneExpired(service);
|
ReferralCacheKey k = new ReferralCacheKey(cname, service);
|
||||||
Map<String, ReferralCacheEntry> entries = referralsMap.get(service);
|
pruneExpired(k);
|
||||||
|
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
|
||||||
if (entries != null) {
|
if (entries != null) {
|
||||||
ReferralCacheEntry toRef = entries.get(fromRealm);
|
ReferralCacheEntry toRef = entries.get(fromRealm);
|
||||||
if (toRef != null) {
|
if (toRef != null) {
|
||||||
|
@ -122,9 +144,9 @@ final class ReferralsCache {
|
||||||
/*
|
/*
|
||||||
* Remove referral entries from the cache when referral TGTs expire.
|
* 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();
|
Date now = new Date();
|
||||||
Map<String, ReferralCacheEntry> entries = referralsMap.get(service);
|
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
|
||||||
if (entries != null) {
|
if (entries != null) {
|
||||||
for (Entry<String, ReferralCacheEntry> mapEntry :
|
for (Entry<String, ReferralCacheEntry> mapEntry :
|
||||||
entries.entrySet()) {
|
entries.entrySet()) {
|
||||||
|
|
|
@ -180,8 +180,9 @@ public class Credentials {
|
||||||
// is most likely to be the one in Authenticator in PA-TGS-REQ encoded
|
// 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 TGS-REQ, therefore only stored with a service ticket. Currently
|
||||||
// in Java, we only reads TGTs.
|
// in Java, we only reads TGTs.
|
||||||
return new sun.security.krb5.Credentials(ticket,
|
return new sun.security.krb5.Credentials(ticket, cname, null, sname,
|
||||||
cname, sname, key, flags, authtime, starttime, endtime, renewTill, caddr);
|
null, key, flags, authtime, starttime, endtime, renewTill,
|
||||||
|
caddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KerberosTime getStartTime() {
|
public KerberosTime getStartTime() {
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -406,6 +406,8 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||||
"(Lsun/security/krb5/internal/Ticket;"
|
"(Lsun/security/krb5/internal/Ticket;"
|
||||||
"Lsun/security/krb5/PrincipalName;"
|
"Lsun/security/krb5/PrincipalName;"
|
||||||
"Lsun/security/krb5/PrincipalName;"
|
"Lsun/security/krb5/PrincipalName;"
|
||||||
|
"Lsun/security/krb5/PrincipalName;"
|
||||||
|
"Lsun/security/krb5/PrincipalName;"
|
||||||
"Lsun/security/krb5/EncryptionKey;"
|
"Lsun/security/krb5/EncryptionKey;"
|
||||||
"Lsun/security/krb5/internal/TicketFlags;"
|
"Lsun/security/krb5/internal/TicketFlags;"
|
||||||
"Lsun/security/krb5/internal/KerberosTime;"
|
"Lsun/security/krb5/internal/KerberosTime;"
|
||||||
|
@ -667,7 +669,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||||
krbcredsConstructor,
|
krbcredsConstructor,
|
||||||
ticket,
|
ticket,
|
||||||
clientPrincipal,
|
clientPrincipal,
|
||||||
|
NULL,
|
||||||
targetPrincipal,
|
targetPrincipal,
|
||||||
|
NULL,
|
||||||
encryptionKey,
|
encryptionKey,
|
||||||
ticketFlags,
|
ticketFlags,
|
||||||
authTime, // mdu
|
authTime, // mdu
|
||||||
|
|
|
@ -808,8 +808,10 @@ public class KDC {
|
||||||
|
|
||||||
PrincipalName cname = null;
|
PrincipalName cname = null;
|
||||||
boolean allowForwardable = true;
|
boolean allowForwardable = true;
|
||||||
|
boolean isReferral = false;
|
||||||
if (body.kdcOptions.get(KDCOptions.CANONICALIZE)) {
|
if (body.kdcOptions.get(KDCOptions.CANONICALIZE)) {
|
||||||
|
System.out.println(realm + "> verifying referral for " +
|
||||||
|
body.sname.getNameString());
|
||||||
KDC referral = aliasReferrals.get(body.sname.getNameString());
|
KDC referral = aliasReferrals.get(body.sname.getNameString());
|
||||||
if (referral != null) {
|
if (referral != null) {
|
||||||
service = new PrincipalName(
|
service = new PrincipalName(
|
||||||
|
@ -817,6 +819,9 @@ public class KDC {
|
||||||
PrincipalName.NAME_COMPONENT_SEPARATOR_STR +
|
PrincipalName.NAME_COMPONENT_SEPARATOR_STR +
|
||||||
referral.getRealm(), PrincipalName.KRB_NT_SRV_INST,
|
referral.getRealm(), PrincipalName.KRB_NT_SRV_INST,
|
||||||
this.getRealm());
|
this.getRealm());
|
||||||
|
System.out.println(realm + "> referral to " +
|
||||||
|
referral.getRealm());
|
||||||
|
isReferral = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -918,7 +923,8 @@ public class KDC {
|
||||||
if (body.kdcOptions.get(KDCOptions.ALLOW_POSTDATE)) {
|
if (body.kdcOptions.get(KDCOptions.ALLOW_POSTDATE)) {
|
||||||
bFlags[Krb5.TKT_OPTS_MAY_POSTDATE] = true;
|
bFlags[Krb5.TKT_OPTS_MAY_POSTDATE] = true;
|
||||||
}
|
}
|
||||||
if (body.kdcOptions.get(KDCOptions.CNAME_IN_ADDL_TKT)) {
|
if (body.kdcOptions.get(KDCOptions.CNAME_IN_ADDL_TKT) &&
|
||||||
|
!isReferral) {
|
||||||
if (!options.containsKey(Option.ALLOW_S4U2PROXY)) {
|
if (!options.containsKey(Option.ALLOW_S4U2PROXY)) {
|
||||||
// Don't understand CNAME_IN_ADDL_TKT
|
// Don't understand CNAME_IN_ADDL_TKT
|
||||||
throw new KrbException(Krb5.KDC_ERR_BADOPTION);
|
throw new KrbException(Krb5.KDC_ERR_BADOPTION);
|
||||||
|
@ -1074,8 +1080,7 @@ public class KDC {
|
||||||
}
|
}
|
||||||
int eType = eTypes[0];
|
int eType = eTypes[0];
|
||||||
|
|
||||||
if (body.kdcOptions.get(KDCOptions.CANONICALIZE) &&
|
if (body.kdcOptions.get(KDCOptions.CANONICALIZE)) {
|
||||||
body.cname.getNameType() == PrincipalName.KRB_NT_ENTERPRISE) {
|
|
||||||
PrincipalName principal = alias2Principals.get(
|
PrincipalName principal = alias2Principals.get(
|
||||||
body.cname.getNameString());
|
body.cname.getNameString());
|
||||||
if (principal != null) {
|
if (principal != null) {
|
||||||
|
|
|
@ -30,9 +30,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import sun.security.krb5.Credentials;
|
import java.security.Principal;
|
||||||
import sun.security.krb5.internal.CredentialsUtil;
|
import java.util.Arrays;
|
||||||
import sun.security.krb5.KrbAsReqBuilder;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.security.auth.kerberos.KerberosTicket;
|
||||||
|
import javax.security.auth.Subject;
|
||||||
|
|
||||||
|
import org.ietf.jgss.GSSName;
|
||||||
|
|
||||||
|
import sun.security.jgss.GSSUtil;
|
||||||
import sun.security.krb5.PrincipalName;
|
import sun.security.krb5.PrincipalName;
|
||||||
|
|
||||||
public class ReferralsTest {
|
public class ReferralsTest {
|
||||||
|
@ -41,39 +50,32 @@ public class ReferralsTest {
|
||||||
private static final String realmKDC1 = "RABBIT.HOLE";
|
private static final String realmKDC1 = "RABBIT.HOLE";
|
||||||
private static final String realmKDC2 = "DEV.RABBIT.HOLE";
|
private static final String realmKDC2 = "DEV.RABBIT.HOLE";
|
||||||
private static final char[] password = "123qwe@Z".toCharArray();
|
private static final char[] password = "123qwe@Z".toCharArray();
|
||||||
|
|
||||||
|
// Names
|
||||||
private static final String clientName = "test";
|
private static final String clientName = "test";
|
||||||
|
|
||||||
private static final String clientAlias = clientName +
|
|
||||||
PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1;
|
|
||||||
|
|
||||||
private static final String clientKDC1QueryName = clientAlias.replaceAll(
|
|
||||||
PrincipalName.NAME_REALM_SEPARATOR_STR, "\\\\" +
|
|
||||||
PrincipalName.NAME_REALM_SEPARATOR_STR) +
|
|
||||||
PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1;
|
|
||||||
private static PrincipalName clientKDC1QueryPrincipal = null;
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
clientKDC1QueryPrincipal = new PrincipalName(
|
|
||||||
clientKDC1QueryName, PrincipalName.KRB_NT_ENTERPRISE,
|
|
||||||
null);
|
|
||||||
} catch (Throwable t) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String clientKDC2Name = clientName +
|
|
||||||
PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC2;
|
|
||||||
|
|
||||||
private static final String serviceName = "http" +
|
private static final String serviceName = "http" +
|
||||||
PrincipalName.NAME_COMPONENT_SEPARATOR_STR +
|
PrincipalName.NAME_COMPONENT_SEPARATOR_STR +
|
||||||
"server.dev.rabbit.hole";
|
"server.dev.rabbit.hole";
|
||||||
|
|
||||||
private static Credentials tgt;
|
// Alias
|
||||||
private static Credentials tgs;
|
private static final String clientAlias = clientName +
|
||||||
|
PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1;
|
||||||
|
|
||||||
|
// Names + realms
|
||||||
|
private static final String clientKDC1Name = clientAlias.replaceAll(
|
||||||
|
PrincipalName.NAME_REALM_SEPARATOR_STR, "\\\\" +
|
||||||
|
PrincipalName.NAME_REALM_SEPARATOR_STR) +
|
||||||
|
PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1;
|
||||||
|
private static final String clientKDC2Name = clientName +
|
||||||
|
PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC2;
|
||||||
|
private static final String serviceKDC2Name = serviceName +
|
||||||
|
PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC2;
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
try {
|
try {
|
||||||
initializeKDCs();
|
initializeKDCs();
|
||||||
getTGT();
|
testSubjectCredentials();
|
||||||
getTGS();
|
testDelegated();
|
||||||
} finally {
|
} finally {
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
@ -108,6 +110,11 @@ public class ReferralsTest {
|
||||||
kdc1.registerAlias(serviceName, kdc2);
|
kdc1.registerAlias(serviceName, kdc2);
|
||||||
kdc2.registerAlias(clientAlias, clientKDC2Name);
|
kdc2.registerAlias(clientAlias, clientKDC2Name);
|
||||||
|
|
||||||
|
Map<String,List<String>> mapKDC2 = new HashMap<>();
|
||||||
|
mapKDC2.put(serviceName + "@" + realmKDC2, Arrays.asList(
|
||||||
|
new String[]{serviceName + "@" + realmKDC2}));
|
||||||
|
kdc2.setOption(KDC.Option.ALLOW_S4U2PROXY, mapKDC2);
|
||||||
|
|
||||||
KDC.saveConfig(krbConfigName, kdc1, kdc2,
|
KDC.saveConfig(krbConfigName, kdc1, kdc2,
|
||||||
"forwardable=true");
|
"forwardable=true");
|
||||||
System.setProperty("java.security.krb5.conf", krbConfigName);
|
System.setProperty("java.security.krb5.conf", krbConfigName);
|
||||||
|
@ -120,50 +127,123 @@ public class ReferralsTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void getTGT() throws Exception {
|
/*
|
||||||
KrbAsReqBuilder builder = new KrbAsReqBuilder(clientKDC1QueryPrincipal,
|
* The client subject (whose principal is
|
||||||
password);
|
* test@RABBIT.HOLE@RABBIT.HOLE) will obtain a TGT after
|
||||||
tgt = builder.action().getCreds();
|
* realm referral and name canonicalization (TGT cname
|
||||||
builder.destroy();
|
* will be test@DEV.RABBIT.HOLE). With this TGT, the client will request
|
||||||
|
* a TGS for service http/server.dev.rabbit.hole@RABBIT.HOLE. After
|
||||||
|
* realm referral, a http/server.dev.rabbit.hole@DEV.RABBIT.HOLE TGS
|
||||||
|
* will be obtained.
|
||||||
|
*
|
||||||
|
* Assert that we get the proper TGT and TGS tickets, and that they are
|
||||||
|
* associated to the client subject.
|
||||||
|
*
|
||||||
|
* Assert that if we request a TGS for the same service again (based on the
|
||||||
|
* original service name), we don't get a new one but the previous,
|
||||||
|
* already in the subject credentials.
|
||||||
|
*/
|
||||||
|
private static void testSubjectCredentials() throws Exception {
|
||||||
|
Subject clientSubject = new Subject();
|
||||||
|
Context clientContext = Context.fromUserPass(clientSubject,
|
||||||
|
clientKDC1Name, password, false);
|
||||||
|
|
||||||
|
Set<Principal> clientPrincipals = clientSubject.getPrincipals();
|
||||||
|
if (clientPrincipals.size() != 1) {
|
||||||
|
throw new Exception("Only one client subject principal expected");
|
||||||
|
}
|
||||||
|
Principal clientPrincipal = clientPrincipals.iterator().next();
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
System.out.println("TGT");
|
System.out.println("Client subject principal: " +
|
||||||
System.out.println("----------------------");
|
clientPrincipal.getName());
|
||||||
System.out.println(tgt);
|
|
||||||
System.out.println("----------------------");
|
|
||||||
}
|
}
|
||||||
if (tgt == null) {
|
if (!clientPrincipal.getName().equals(clientKDC1Name)) {
|
||||||
throw new Exception("TGT is null");
|
throw new Exception("Unexpected client subject principal.");
|
||||||
}
|
}
|
||||||
if (!tgt.getClient().getName().equals(clientKDC2Name)) {
|
|
||||||
throw new Exception("Unexpected TGT client");
|
clientContext.startAsClient(serviceName, GSSUtil.GSS_KRB5_MECH_OID);
|
||||||
|
clientContext.take(new byte[0]);
|
||||||
|
Set<KerberosTicket> clientTickets =
|
||||||
|
clientSubject.getPrivateCredentials(KerberosTicket.class);
|
||||||
|
boolean tgtFound = false;
|
||||||
|
boolean tgsFound = false;
|
||||||
|
for (KerberosTicket clientTicket : clientTickets) {
|
||||||
|
String cname = clientTicket.getClient().getName();
|
||||||
|
String sname = clientTicket.getServer().getName();
|
||||||
|
if (cname.equals(clientKDC2Name)) {
|
||||||
|
if (sname.equals(PrincipalName.TGS_DEFAULT_SRV_NAME +
|
||||||
|
PrincipalName.NAME_COMPONENT_SEPARATOR_STR +
|
||||||
|
realmKDC2 + PrincipalName.NAME_REALM_SEPARATOR_STR +
|
||||||
|
realmKDC2)) {
|
||||||
|
tgtFound = true;
|
||||||
|
} else if (sname.equals(serviceKDC2Name)) {
|
||||||
|
tgsFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
System.out.println("Client subject KerberosTicket:");
|
||||||
|
System.out.println(clientTicket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
String[] tgtServerNames = tgt.getServer().getNameStrings();
|
if (!tgtFound || !tgsFound) {
|
||||||
if (tgtServerNames.length != 2 || !tgtServerNames[0].equals(
|
throw new Exception("client subject tickets (TGT/TGS) not found.");
|
||||||
PrincipalName.TGS_DEFAULT_SRV_NAME) ||
|
}
|
||||||
!tgtServerNames[1].equals(realmKDC2) ||
|
int numOfTickets = clientTickets.size();
|
||||||
!tgt.getServer().getRealmString().equals(realmKDC2)) {
|
clientContext.startAsClient(serviceName, GSSUtil.GSS_KRB5_MECH_OID);
|
||||||
throw new Exception("Unexpected TGT server");
|
clientContext.take(new byte[0]);
|
||||||
|
clientContext.status();
|
||||||
|
int newNumOfTickets =
|
||||||
|
clientSubject.getPrivateCredentials(KerberosTicket.class).size();
|
||||||
|
if (DEBUG) {
|
||||||
|
System.out.println("client subject number of tickets: " +
|
||||||
|
numOfTickets);
|
||||||
|
System.out.println("client subject new number of tickets: " +
|
||||||
|
newNumOfTickets);
|
||||||
|
}
|
||||||
|
if (numOfTickets != newNumOfTickets) {
|
||||||
|
throw new Exception("Useless client subject TGS request because" +
|
||||||
|
" TGS was not found in private credentials.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void getTGS() throws Exception {
|
/*
|
||||||
tgs = CredentialsUtil.acquireServiceCreds(serviceName +
|
* The server (http/server.dev.rabbit.hole@DEV.RABBIT.HOLE)
|
||||||
PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1, tgt);
|
* will authenticate on itself on behalf of the client
|
||||||
|
* (test@DEV.RABBIT.HOLE). Cross-realm referrals will occur
|
||||||
|
* when requesting different TGTs and TGSs (including the
|
||||||
|
* request for delegated credentials).
|
||||||
|
*/
|
||||||
|
private static void testDelegated() throws Exception {
|
||||||
|
Context c = Context.fromUserPass(clientKDC2Name,
|
||||||
|
password, false);
|
||||||
|
c.startAsClient(serviceName, GSSUtil.GSS_KRB5_MECH_OID);
|
||||||
|
Context s = Context.fromUserPass(serviceKDC2Name,
|
||||||
|
password, true);
|
||||||
|
s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
|
||||||
|
Context.handshake(c, s);
|
||||||
|
Context delegatedContext = s.delegated();
|
||||||
|
delegatedContext.startAsClient(serviceName, GSSUtil.GSS_KRB5_MECH_OID);
|
||||||
|
delegatedContext.x().requestMutualAuth(false);
|
||||||
|
Context s2 = Context.fromUserPass(serviceKDC2Name,
|
||||||
|
password, true);
|
||||||
|
s2.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
|
||||||
|
|
||||||
|
// Test authentication
|
||||||
|
Context.handshake(delegatedContext, s2);
|
||||||
|
if (!delegatedContext.x().isEstablished() || !s2.x().isEstablished()) {
|
||||||
|
throw new Exception("Delegated authentication failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test identities
|
||||||
|
GSSName contextInitiatorName = delegatedContext.x().getSrcName();
|
||||||
|
GSSName contextAcceptorName = delegatedContext.x().getTargName();
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
System.out.println("TGS");
|
System.out.println("Context initiator: " + contextInitiatorName);
|
||||||
System.out.println("----------------------");
|
System.out.println("Context acceptor: " + contextAcceptorName);
|
||||||
System.out.println(tgs);
|
|
||||||
System.out.println("----------------------");
|
|
||||||
}
|
}
|
||||||
if (tgs == null) {
|
if (!contextInitiatorName.toString().equals(clientKDC2Name) ||
|
||||||
throw new Exception("TGS is null");
|
!contextAcceptorName.toString().equals(serviceName)) {
|
||||||
}
|
throw new Exception("Unexpected initiator or acceptor names");
|
||||||
if (!tgs.getClient().getName().equals(clientKDC2Name)) {
|
|
||||||
throw new Exception("Unexpected TGS client");
|
|
||||||
}
|
|
||||||
if (!tgs.getServer().getNameString().equals(serviceName) ||
|
|
||||||
!tgs.getServer().getRealmString().equals(realmKDC2)) {
|
|
||||||
throw new Exception("Unexpected TGS server");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue