|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.jgss.krb5; |
|
|
|
import org.ietf.jgss.*; |
|
import sun.security.jgss.GSSCaller; |
|
import sun.security.jgss.spi.*; |
|
import sun.security.krb5.*; |
|
import sun.security.krb5.Config; |
|
import javax.security.auth.kerberos.*; |
|
import java.net.InetAddress; |
|
import java.io.IOException; |
|
import java.util.Date; |
|
import java.security.AccessController; |
|
import java.security.AccessControlContext; |
|
import java.security.PrivilegedExceptionAction; |
|
import java.security.PrivilegedActionException; |
|
|
|
/** |
|
* Implements the krb5 initiator credential element. |
|
* |
|
* @author Mayank Upadhyay |
|
* @author Ram Marti |
|
* @since 1.4 |
|
*/ |
|
|
|
public class Krb5InitCredential |
|
extends KerberosTicket |
|
implements Krb5CredElement { |
|
|
|
private static final long serialVersionUID = 7723415700837898232L; |
|
|
|
private Krb5NameElement name; |
|
private Credentials krb5Credentials; |
|
public KerberosTicket proxyTicket; |
|
|
|
private Krb5InitCredential(Krb5NameElement name, |
|
byte[] asn1Encoding, |
|
KerberosPrincipal client, |
|
KerberosPrincipal clientAlias, |
|
KerberosPrincipal server, |
|
KerberosPrincipal serverAlias, |
|
byte[] sessionKey, |
|
int keyType, |
|
boolean[] flags, |
|
Date authTime, |
|
Date startTime, |
|
Date endTime, |
|
Date renewTill, |
|
InetAddress[] clientAddresses) |
|
throws GSSException { |
|
super(asn1Encoding, |
|
client, |
|
server, |
|
sessionKey, |
|
keyType, |
|
flags, |
|
authTime, |
|
startTime, |
|
endTime, |
|
renewTill, |
|
clientAddresses); |
|
KerberosSecrets.getJavaxSecurityAuthKerberosAccess() |
|
.kerberosTicketSetClientAlias(this, clientAlias); |
|
KerberosSecrets.getJavaxSecurityAuthKerberosAccess() |
|
.kerberosTicketSetServerAlias(this, serverAlias); |
|
this.name = name; |
|
|
|
try { |
|
|
|
krb5Credentials = new Credentials(asn1Encoding, |
|
client.getName(), |
|
(clientAlias != null ? |
|
clientAlias.getName() : null), |
|
server.getName(), |
|
(serverAlias != null ? |
|
serverAlias.getName() : null), |
|
sessionKey, |
|
keyType, |
|
flags, |
|
authTime, |
|
startTime, |
|
endTime, |
|
renewTill, |
|
clientAddresses); |
|
} catch (KrbException e) { |
|
throw new GSSException(GSSException.NO_CRED, -1, |
|
e.getMessage()); |
|
} catch (IOException e) { |
|
throw new GSSException(GSSException.NO_CRED, -1, |
|
e.getMessage()); |
|
} |
|
|
|
} |
|
|
|
private Krb5InitCredential(Krb5NameElement name, |
|
Credentials delegatedCred, |
|
byte[] asn1Encoding, |
|
KerberosPrincipal client, |
|
KerberosPrincipal clientAlias, |
|
KerberosPrincipal server, |
|
KerberosPrincipal serverAlias, |
|
byte[] sessionKey, |
|
int keyType, |
|
boolean[] flags, |
|
Date authTime, |
|
Date startTime, |
|
Date endTime, |
|
Date renewTill, |
|
InetAddress[] clientAddresses) |
|
throws GSSException { |
|
super(asn1Encoding, |
|
client, |
|
server, |
|
sessionKey, |
|
keyType, |
|
flags, |
|
authTime, |
|
startTime, |
|
endTime, |
|
renewTill, |
|
clientAddresses); |
|
KerberosSecrets.getJavaxSecurityAuthKerberosAccess() |
|
.kerberosTicketSetClientAlias(this, clientAlias); |
|
KerberosSecrets.getJavaxSecurityAuthKerberosAccess() |
|
.kerberosTicketSetServerAlias(this, serverAlias); |
|
this.name = name; |
|
// A delegated cred does not have all fields set. So do not try to |
|
|
|
this.krb5Credentials = delegatedCred; |
|
} |
|
|
|
static Krb5InitCredential getInstance(GSSCaller caller, Krb5NameElement name, |
|
int initLifetime) |
|
throws GSSException { |
|
|
|
KerberosTicket tgt = getTgt(caller, name, initLifetime); |
|
if (tgt == null) |
|
throw new GSSException(GSSException.NO_CRED, -1, |
|
"Failed to find any Kerberos tgt"); |
|
|
|
if (name == null) { |
|
String fullName = tgt.getClient().getName(); |
|
name = Krb5NameElement.getInstance(fullName, |
|
Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL); |
|
} |
|
|
|
KerberosPrincipal clientAlias = KerberosSecrets |
|
.getJavaxSecurityAuthKerberosAccess() |
|
.kerberosTicketGetClientAlias(tgt); |
|
KerberosPrincipal serverAlias = KerberosSecrets |
|
.getJavaxSecurityAuthKerberosAccess() |
|
.kerberosTicketGetServerAlias(tgt); |
|
Krb5InitCredential result = new Krb5InitCredential(name, |
|
tgt.getEncoded(), |
|
tgt.getClient(), |
|
clientAlias, |
|
tgt.getServer(), |
|
serverAlias, |
|
tgt.getSessionKey().getEncoded(), |
|
tgt.getSessionKeyType(), |
|
tgt.getFlags(), |
|
tgt.getAuthTime(), |
|
tgt.getStartTime(), |
|
tgt.getEndTime(), |
|
tgt.getRenewTill(), |
|
tgt.getClientAddresses()); |
|
result.proxyTicket = KerberosSecrets.getJavaxSecurityAuthKerberosAccess(). |
|
kerberosTicketGetProxy(tgt); |
|
return result; |
|
} |
|
|
|
static Krb5InitCredential getInstance(Krb5NameElement name, |
|
Credentials delegatedCred) |
|
throws GSSException { |
|
|
|
EncryptionKey sessionKey = delegatedCred.getSessionKey(); |
|
|
|
/* |
|
* all of the following data is optional in a KRB-CRED |
|
* messages. This check for each field. |
|
*/ |
|
|
|
PrincipalName cPrinc = delegatedCred.getClient(); |
|
PrincipalName cAPrinc = delegatedCred.getClientAlias(); |
|
PrincipalName sPrinc = delegatedCred.getServer(); |
|
PrincipalName sAPrinc = delegatedCred.getServerAlias(); |
|
|
|
KerberosPrincipal client = null; |
|
KerberosPrincipal clientAlias = null; |
|
KerberosPrincipal server = null; |
|
KerberosPrincipal serverAlias = null; |
|
|
|
Krb5NameElement credName = null; |
|
|
|
if (cPrinc != null) { |
|
String fullName = cPrinc.getName(); |
|
credName = Krb5NameElement.getInstance(fullName, |
|
Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL); |
|
client = new KerberosPrincipal(fullName); |
|
} |
|
|
|
if (cAPrinc != null) { |
|
clientAlias = new KerberosPrincipal(cAPrinc.getName()); |
|
} |
|
|
|
// XXX Compare name to credName |
|
|
|
if (sPrinc != null) { |
|
server = |
|
new KerberosPrincipal(sPrinc.getName(), |
|
KerberosPrincipal.KRB_NT_SRV_INST); |
|
} |
|
|
|
if (sAPrinc != null) { |
|
serverAlias = new KerberosPrincipal(sAPrinc.getName()); |
|
} |
|
|
|
return new Krb5InitCredential(credName, |
|
delegatedCred, |
|
delegatedCred.getEncoded(), |
|
client, |
|
clientAlias, |
|
server, |
|
serverAlias, |
|
sessionKey.getBytes(), |
|
sessionKey.getEType(), |
|
delegatedCred.getFlags(), |
|
delegatedCred.getAuthTime(), |
|
delegatedCred.getStartTime(), |
|
delegatedCred.getEndTime(), |
|
delegatedCred.getRenewTill(), |
|
delegatedCred.getClientAddresses()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final GSSNameSpi getName() throws GSSException { |
|
return name; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getInitLifetime() throws GSSException { |
|
Date d = getEndTime(); |
|
if (d == null) { |
|
return 0; |
|
} |
|
|
|
long retVal = d.getTime() - System.currentTimeMillis(); |
|
return (int)(retVal/1000); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getAcceptLifetime() throws GSSException { |
|
return 0; |
|
} |
|
|
|
public boolean isInitiatorCredential() throws GSSException { |
|
return true; |
|
} |
|
|
|
public boolean isAcceptorCredential() throws GSSException { |
|
return false; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final Oid getMechanism() { |
|
return Krb5MechFactory.GSS_KRB5_MECH_OID; |
|
} |
|
|
|
public final java.security.Provider getProvider() { |
|
return Krb5MechFactory.PROVIDER; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
Credentials getKrb5Credentials() { |
|
return krb5Credentials; |
|
} |
|
|
|
/* |
|
* XXX Call to this.refresh() should refresh the locally cached copy |
|
* of krb5Credentials also. |
|
*/ |
|
|
|
|
|
|
|
*/ |
|
public void dispose() throws GSSException { |
|
try { |
|
destroy(); |
|
} catch (javax.security.auth.DestroyFailedException e) { |
|
GSSException gssException = |
|
new GSSException(GSSException.FAILURE, -1, |
|
"Could not destroy credentials - " + e.getMessage()); |
|
gssException.initCause(e); |
|
} |
|
} |
|
|
|
// XXX call to this.destroy() should destroy the locally cached copy |
|
// of krb5Credentials and then call super.destroy(). |
|
|
|
private static KerberosTicket getTgt(GSSCaller caller, Krb5NameElement name, |
|
int initLifetime) |
|
throws GSSException { |
|
|
|
final String clientPrincipal; |
|
|
|
|
|
|
|
|
|
*/ |
|
if (name != null) { |
|
clientPrincipal = (name.getKrb5PrincipalName()).getName(); |
|
} else { |
|
clientPrincipal = null; |
|
} |
|
|
|
final AccessControlContext acc = AccessController.getContext(); |
|
|
|
try { |
|
final GSSCaller realCaller = (caller == GSSCaller.CALLER_UNKNOWN) |
|
? GSSCaller.CALLER_INITIATE |
|
: caller; |
|
return AccessController.doPrivileged( |
|
new PrivilegedExceptionAction<KerberosTicket>() { |
|
public KerberosTicket run() throws Exception { |
|
// It's OK to use null as serverPrincipal. TGT is almost |
|
|
|
return Krb5Util.getInitialTicket( |
|
realCaller, |
|
clientPrincipal, acc); |
|
}}); |
|
} catch (PrivilegedActionException e) { |
|
GSSException ge = |
|
new GSSException(GSSException.NO_CRED, -1, |
|
"Attempt to obtain new INITIATE credentials failed!" + |
|
" (" + e.getMessage() + ")"); |
|
ge.initCause(e.getException()); |
|
throw ge; |
|
} |
|
} |
|
|
|
@Override |
|
public GSSCredentialSpi impersonate(GSSNameSpi name) throws GSSException { |
|
try { |
|
Krb5NameElement kname = (Krb5NameElement)name; |
|
Credentials newCred = Credentials.acquireS4U2selfCreds( |
|
kname.getKrb5PrincipalName(), krb5Credentials); |
|
return new Krb5ProxyCredential(this, kname, newCred.getTicket()); |
|
} catch (IOException | KrbException ke) { |
|
GSSException ge = |
|
new GSSException(GSSException.FAILURE, -1, |
|
"Attempt to obtain S4U2self credentials failed!"); |
|
ge.initCause(ke); |
|
throw ge; |
|
} |
|
} |
|
} |