|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.jgss; |
|
|
|
import org.ietf.jgss.*; |
|
import sun.security.jgss.spi.*; |
|
import java.util.*; |
|
import com.sun.security.jgss.*; |
|
import sun.security.jgss.spnego.SpNegoCredElement; |
|
|
|
public class GSSCredentialImpl implements ExtendedGSSCredential { |
|
|
|
private GSSManagerImpl gssManager = null; |
|
private boolean destroyed = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private Hashtable<SearchKey, GSSCredentialSpi> hashtable = null; |
|
|
|
|
|
private GSSCredentialSpi tempCred = null; |
|
|
|
GSSCredentialImpl(GSSManagerImpl gssManager, int usage) |
|
throws GSSException { |
|
this(gssManager, null, GSSCredential.DEFAULT_LIFETIME, |
|
(Oid[]) null, usage); |
|
} |
|
|
|
GSSCredentialImpl(GSSManagerImpl gssManager, GSSName name, |
|
int lifetime, Oid mech, int usage) |
|
throws GSSException { |
|
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID; |
|
|
|
init(gssManager); |
|
add(name, lifetime, lifetime, mech, usage); |
|
} |
|
|
|
GSSCredentialImpl(GSSManagerImpl gssManager, GSSName name, |
|
int lifetime, Oid mechs[], int usage) |
|
throws GSSException { |
|
init(gssManager); |
|
boolean defaultList = false; |
|
if (mechs == null) { |
|
mechs = gssManager.getMechs(); |
|
defaultList = true; |
|
} |
|
|
|
for (int i = 0; i < mechs.length; i++) { |
|
try { |
|
add(name, lifetime, lifetime, mechs[i], usage); |
|
} catch (GSSException e) { |
|
if (defaultList) { |
|
|
|
GSSUtil.debug("Ignore " + e + " while acquring cred for " |
|
+ mechs[i]); |
|
//e.printStackTrace(); |
|
} else throw e; |
|
} |
|
} |
|
if ((hashtable.size() == 0) || (usage != getUsage())) |
|
throw new GSSException(GSSException.NO_CRED); |
|
} |
|
|
|
|
|
public GSSCredentialImpl(GSSManagerImpl gssManager, |
|
GSSCredentialSpi mechElement) throws GSSException { |
|
|
|
init(gssManager); |
|
int usage = GSSCredential.ACCEPT_ONLY; |
|
if (mechElement.isInitiatorCredential()) { |
|
if (mechElement.isAcceptorCredential()) { |
|
usage = GSSCredential.INITIATE_AND_ACCEPT; |
|
} else { |
|
usage = GSSCredential.INITIATE_ONLY; |
|
} |
|
} |
|
SearchKey key = new SearchKey(mechElement.getMechanism(), |
|
usage); |
|
tempCred = mechElement; |
|
hashtable.put(key, tempCred); |
|
|
|
if (!GSSUtil.isSpNegoMech(mechElement.getMechanism())) { |
|
key = new SearchKey(GSSUtil.GSS_SPNEGO_MECH_OID, usage); |
|
hashtable.put(key, new SpNegoCredElement(mechElement)); |
|
} |
|
} |
|
|
|
void init(GSSManagerImpl gssManager) { |
|
this.gssManager = gssManager; |
|
hashtable = new Hashtable<SearchKey, GSSCredentialSpi>( |
|
gssManager.getMechs().length); |
|
} |
|
|
|
public void dispose() throws GSSException { |
|
if (!destroyed) { |
|
GSSCredentialSpi element; |
|
Enumeration<GSSCredentialSpi> values = hashtable.elements(); |
|
while (values.hasMoreElements()) { |
|
element = values.nextElement(); |
|
element.dispose(); |
|
} |
|
destroyed = true; |
|
} |
|
} |
|
|
|
public GSSCredential impersonate(GSSName name) throws GSSException { |
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
Oid mech = tempCred.getMechanism(); |
|
GSSNameSpi nameElement = (name == null ? null : |
|
((GSSNameImpl)name).getElement(mech)); |
|
GSSCredentialSpi cred = tempCred.impersonate(nameElement); |
|
return (cred == null ? |
|
null : new GSSCredentialImpl(gssManager, cred)); |
|
} |
|
|
|
public GSSName getName() throws GSSException { |
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
return GSSNameImpl.wrapElement(gssManager, tempCred.getName()); |
|
} |
|
|
|
public GSSName getName(Oid mech) throws GSSException { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
|
|
SearchKey key = null; |
|
GSSCredentialSpi element = null; |
|
|
|
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID; |
|
|
|
key = new SearchKey(mech, GSSCredential.INITIATE_ONLY); |
|
element = hashtable.get(key); |
|
|
|
if (element == null) { |
|
key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY); |
|
element = hashtable.get(key); |
|
} |
|
|
|
if (element == null) { |
|
key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT); |
|
element = hashtable.get(key); |
|
} |
|
|
|
if (element == null) { |
|
throw new GSSExceptionImpl(GSSException.BAD_MECH, mech); |
|
} |
|
|
|
return GSSNameImpl.wrapElement(gssManager, element.getName()); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getRemainingLifetime() throws GSSException { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
|
|
SearchKey tempKey; |
|
GSSCredentialSpi tempCred; |
|
int tempLife = 0, tempInitLife = 0, tempAcceptLife = 0; |
|
int min = INDEFINITE_LIFETIME; |
|
|
|
for (Enumeration<SearchKey> e = hashtable.keys(); |
|
e.hasMoreElements(); ) { |
|
tempKey = e.nextElement(); |
|
tempCred = hashtable.get(tempKey); |
|
if (tempKey.getUsage() == INITIATE_ONLY) |
|
tempLife = tempCred.getInitLifetime(); |
|
else if (tempKey.getUsage() == ACCEPT_ONLY) |
|
tempLife = tempCred.getAcceptLifetime(); |
|
else { |
|
tempInitLife = tempCred.getInitLifetime(); |
|
tempAcceptLife = tempCred.getAcceptLifetime(); |
|
tempLife = (tempInitLife < tempAcceptLife ? |
|
tempInitLife: |
|
tempAcceptLife); |
|
} |
|
if (min > tempLife) |
|
min = tempLife; |
|
} |
|
|
|
return min; |
|
} |
|
|
|
public int getRemainingInitLifetime(Oid mech) throws GSSException { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
|
|
GSSCredentialSpi element = null; |
|
SearchKey key = null; |
|
boolean found = false; |
|
int max = 0; |
|
|
|
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID; |
|
|
|
key = new SearchKey(mech, GSSCredential.INITIATE_ONLY); |
|
element = hashtable.get(key); |
|
|
|
if (element != null) { |
|
found = true; |
|
if (max < element.getInitLifetime()) |
|
max = element.getInitLifetime(); |
|
} |
|
|
|
key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT); |
|
element = hashtable.get(key); |
|
|
|
if (element != null) { |
|
found = true; |
|
if (max < element.getInitLifetime()) |
|
max = element.getInitLifetime(); |
|
} |
|
|
|
if (!found) { |
|
throw new GSSExceptionImpl(GSSException.BAD_MECH, mech); |
|
} |
|
|
|
return max; |
|
|
|
} |
|
|
|
public int getRemainingAcceptLifetime(Oid mech) throws GSSException { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
|
|
GSSCredentialSpi element = null; |
|
SearchKey key = null; |
|
boolean found = false; |
|
int max = 0; |
|
|
|
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID; |
|
|
|
key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY); |
|
element = hashtable.get(key); |
|
|
|
if (element != null) { |
|
found = true; |
|
if (max < element.getAcceptLifetime()) |
|
max = element.getAcceptLifetime(); |
|
} |
|
|
|
key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT); |
|
element = hashtable.get(key); |
|
|
|
if (element != null) { |
|
found = true; |
|
if (max < element.getAcceptLifetime()) |
|
max = element.getAcceptLifetime(); |
|
} |
|
|
|
if (!found) { |
|
throw new GSSExceptionImpl(GSSException.BAD_MECH, mech); |
|
} |
|
|
|
return max; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getUsage() throws GSSException { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
|
|
SearchKey tempKey; |
|
boolean initiate = false; |
|
boolean accept = false; |
|
|
|
for (Enumeration<SearchKey> e = hashtable.keys(); |
|
e.hasMoreElements(); ) { |
|
tempKey = e.nextElement(); |
|
if (tempKey.getUsage() == INITIATE_ONLY) |
|
initiate = true; |
|
else if (tempKey.getUsage() == ACCEPT_ONLY) |
|
accept = true; |
|
else |
|
return INITIATE_AND_ACCEPT; |
|
} |
|
if (initiate) { |
|
if (accept) |
|
return INITIATE_AND_ACCEPT; |
|
else |
|
return INITIATE_ONLY; |
|
} else |
|
return ACCEPT_ONLY; |
|
} |
|
|
|
public int getUsage(Oid mech) throws GSSException { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
|
|
GSSCredentialSpi element = null; |
|
SearchKey key = null; |
|
boolean initiate = false; |
|
boolean accept = false; |
|
|
|
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID; |
|
|
|
key = new SearchKey(mech, GSSCredential.INITIATE_ONLY); |
|
element = hashtable.get(key); |
|
|
|
if (element != null) { |
|
initiate = true; |
|
} |
|
|
|
key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY); |
|
element = hashtable.get(key); |
|
|
|
if (element != null) { |
|
accept = true; |
|
} |
|
|
|
key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT); |
|
element = hashtable.get(key); |
|
|
|
if (element != null) { |
|
initiate = true; |
|
accept = true; |
|
} |
|
|
|
if (initiate && accept) |
|
return GSSCredential.INITIATE_AND_ACCEPT; |
|
else if (initiate) |
|
return GSSCredential.INITIATE_ONLY; |
|
else if (accept) |
|
return GSSCredential.ACCEPT_ONLY; |
|
else { |
|
throw new GSSExceptionImpl(GSSException.BAD_MECH, mech); |
|
} |
|
} |
|
|
|
public Oid[] getMechs() throws GSSException { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
Vector<Oid> result = new Vector<Oid>(hashtable.size()); |
|
|
|
for (Enumeration<SearchKey> e = hashtable.keys(); |
|
e.hasMoreElements(); ) { |
|
SearchKey tempKey = e.nextElement(); |
|
result.addElement(tempKey.getMech()); |
|
} |
|
return result.toArray(new Oid[0]); |
|
} |
|
|
|
public void add(GSSName name, int initLifetime, int acceptLifetime, |
|
Oid mech, int usage) throws GSSException { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID; |
|
|
|
SearchKey key = new SearchKey(mech, usage); |
|
if (hashtable.containsKey(key)) { |
|
throw new GSSExceptionImpl(GSSException.DUPLICATE_ELEMENT, |
|
"Duplicate element found: " + |
|
getElementStr(mech, usage)); |
|
} |
|
|
|
// XXX If not instance of GSSNameImpl then throw exception |
|
|
|
GSSNameSpi nameElement = (name == null ? null : |
|
((GSSNameImpl)name).getElement(mech)); |
|
|
|
tempCred = gssManager.getCredentialElement(nameElement, |
|
initLifetime, |
|
acceptLifetime, |
|
mech, |
|
usage); |
|
/* |
|
* Not all mechanisms support the concept of one credential element |
|
* that can be used for both initiating and accepting a context. In |
|
* the event that an application requests usage INITIATE_AND_ACCEPT |
|
* for a credential from such a mechanism, the GSS framework will |
|
* need to obtain two different credential elements from the |
|
* mechanism, one that will have usage INITIATE_ONLY and another |
|
* that will have usage ACCEPT_ONLY. The mechanism will help the |
|
* GSS-API realize this by returning a credential element with |
|
* usage INITIATE_ONLY or ACCEPT_ONLY prompting it to make another |
|
* call to getCredentialElement, this time with the other usage |
|
* mode. |
|
*/ |
|
|
|
if (tempCred != null) { |
|
if (usage == GSSCredential.INITIATE_AND_ACCEPT && |
|
(!tempCred.isAcceptorCredential() || |
|
!tempCred.isInitiatorCredential())) { |
|
|
|
int currentUsage; |
|
int desiredUsage; |
|
|
|
if (!tempCred.isInitiatorCredential()) { |
|
currentUsage = GSSCredential.ACCEPT_ONLY; |
|
desiredUsage = GSSCredential.INITIATE_ONLY; |
|
} else { |
|
currentUsage = GSSCredential.INITIATE_ONLY; |
|
desiredUsage = GSSCredential.ACCEPT_ONLY; |
|
} |
|
|
|
key = new SearchKey(mech, currentUsage); |
|
hashtable.put(key, tempCred); |
|
|
|
tempCred = gssManager.getCredentialElement(nameElement, |
|
initLifetime, |
|
acceptLifetime, |
|
mech, |
|
desiredUsage); |
|
|
|
key = new SearchKey(mech, desiredUsage); |
|
hashtable.put(key, tempCred); |
|
} else { |
|
hashtable.put(key, tempCred); |
|
} |
|
} |
|
} |
|
|
|
public boolean equals(Object another) { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
|
|
if (this == another) { |
|
return true; |
|
} |
|
|
|
if (!(another instanceof GSSCredentialImpl)) { |
|
return false; |
|
} |
|
|
|
// NOTE: The specification does not define the criteria to compare |
|
// credentials. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int hashCode() { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
|
|
// NOTE: The specification does not define the criteria to compare |
|
// credentials. |
|
|
|
|
|
|
|
*/ |
|
return 1; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public GSSCredentialSpi getElement(Oid mechOid, boolean initiate) |
|
throws GSSException { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
|
|
SearchKey key; |
|
GSSCredentialSpi element; |
|
|
|
if (mechOid == null) { |
|
|
|
|
|
|
|
*/ |
|
mechOid = ProviderList.DEFAULT_MECH_OID; |
|
key = new SearchKey(mechOid, |
|
initiate? INITIATE_ONLY : ACCEPT_ONLY); |
|
element = hashtable.get(key); |
|
if (element == null) { |
|
key = new SearchKey(mechOid, INITIATE_AND_ACCEPT); |
|
element = hashtable.get(key); |
|
if (element == null) { |
|
|
|
|
|
|
|
*/ |
|
Object[] elements = hashtable.entrySet().toArray(); |
|
for (int i = 0; i < elements.length; i++) { |
|
element = (GSSCredentialSpi) |
|
((Map.Entry)elements[i]).getValue(); |
|
if (element.isInitiatorCredential() == initiate) |
|
break; |
|
} // for loop |
|
} |
|
} |
|
} else { |
|
|
|
if (initiate) |
|
key = new SearchKey(mechOid, INITIATE_ONLY); |
|
else |
|
key = new SearchKey(mechOid, ACCEPT_ONLY); |
|
|
|
element = hashtable.get(key); |
|
|
|
if (element == null) { |
|
key = new SearchKey(mechOid, INITIATE_AND_ACCEPT); |
|
element = hashtable.get(key); |
|
} |
|
} |
|
|
|
if (element == null) |
|
throw new GSSExceptionImpl(GSSException.NO_CRED, |
|
"No credential found for: " + |
|
getElementStr(mechOid, |
|
initiate? INITIATE_ONLY : ACCEPT_ONLY)); |
|
return element; |
|
} |
|
|
|
Set<GSSCredentialSpi> getElements() { |
|
HashSet<GSSCredentialSpi> retVal = |
|
new HashSet<GSSCredentialSpi>(hashtable.size()); |
|
Enumeration<GSSCredentialSpi> values = hashtable.elements(); |
|
while (values.hasMoreElements()) { |
|
GSSCredentialSpi o = values.nextElement(); |
|
retVal.add(o); |
|
} |
|
return retVal; |
|
} |
|
|
|
private static String getElementStr(Oid mechOid, int usage) { |
|
String displayString = mechOid.toString(); |
|
if (usage == GSSCredential.INITIATE_ONLY) { |
|
displayString = |
|
displayString.concat(" usage: Initiate"); |
|
} else if (usage == GSSCredential.ACCEPT_ONLY) { |
|
displayString = |
|
displayString.concat(" usage: Accept"); |
|
} else { |
|
displayString = |
|
displayString.concat(" usage: Initiate and Accept"); |
|
} |
|
return displayString; |
|
} |
|
|
|
public String toString() { |
|
|
|
if (destroyed) { |
|
throw new IllegalStateException("This credential is " + |
|
"no longer valid"); |
|
} |
|
|
|
GSSCredentialSpi element = null; |
|
StringBuffer buffer = new StringBuffer("[GSSCredential: "); |
|
Object[] elements = hashtable.entrySet().toArray(); |
|
for (int i = 0; i < elements.length; i++) { |
|
try { |
|
buffer.append('\n'); |
|
element = (GSSCredentialSpi) |
|
((Map.Entry)elements[i]).getValue(); |
|
buffer.append(element.getName()); |
|
buffer.append(' '); |
|
buffer.append(element.getMechanism()); |
|
buffer.append(element.isInitiatorCredential() ? |
|
" Initiate" : ""); |
|
buffer.append(element.isAcceptorCredential() ? |
|
" Accept" : ""); |
|
buffer.append(" ["); |
|
buffer.append(element.getClass()); |
|
buffer.append(']'); |
|
} catch (GSSException e) { |
|
// skip to next element |
|
} |
|
} |
|
buffer.append(']'); |
|
return buffer.toString(); |
|
} |
|
|
|
static class SearchKey { |
|
private Oid mechOid = null; |
|
private int usage = GSSCredential.INITIATE_AND_ACCEPT; |
|
public SearchKey(Oid mechOid, int usage) { |
|
|
|
this.mechOid = mechOid; |
|
this.usage = usage; |
|
} |
|
public Oid getMech() { |
|
return mechOid; |
|
} |
|
public int getUsage() { |
|
return usage; |
|
} |
|
public boolean equals(Object other) { |
|
if (! (other instanceof SearchKey)) |
|
return false; |
|
SearchKey that = (SearchKey) other; |
|
return ((this.mechOid.equals(that.mechOid)) && |
|
(this.usage == that.usage)); |
|
} |
|
public int hashCode() { |
|
return mechOid.hashCode(); |
|
} |
|
} |
|
|
|
} |