|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.jgss.krb5; |
|
|
|
import org.ietf.jgss.*; |
|
import sun.security.jgss.GSSUtil; |
|
import sun.security.jgss.GSSCaller; |
|
import sun.security.jgss.spi.*; |
|
import javax.security.auth.kerberos.ServicePermission; |
|
import java.security.Provider; |
|
import java.util.Vector; |
|
|
|
/** |
|
* Krb5 Mechanism plug in for JGSS |
|
* This is the properties object required by the JGSS framework. |
|
* All mechanism specific information is defined here. |
|
* |
|
* @author Mayank Upadhyay |
|
*/ |
|
|
|
public final class Krb5MechFactory implements MechanismFactory { |
|
|
|
private static final boolean DEBUG = Krb5Util.DEBUG; |
|
|
|
static final Provider PROVIDER = |
|
new sun.security.jgss.SunProvider(); |
|
|
|
static final Oid GSS_KRB5_MECH_OID = |
|
createOid("1.2.840.113554.1.2.2"); |
|
|
|
static final Oid NT_GSS_KRB5_PRINCIPAL = |
|
createOid("1.2.840.113554.1.2.2.1"); |
|
|
|
private static Oid[] nameTypes = |
|
new Oid[] { GSSName.NT_USER_NAME, |
|
GSSName.NT_HOSTBASED_SERVICE, |
|
GSSName.NT_EXPORT_NAME, |
|
NT_GSS_KRB5_PRINCIPAL}; |
|
|
|
final private GSSCaller caller; |
|
|
|
private static Krb5CredElement getCredFromSubject(GSSNameSpi name, |
|
boolean initiate) |
|
throws GSSException { |
|
Vector<Krb5CredElement> creds = |
|
GSSUtil.searchSubject(name, GSS_KRB5_MECH_OID, initiate, |
|
(initiate ? |
|
Krb5InitCredential.class : |
|
Krb5AcceptCredential.class)); |
|
|
|
Krb5CredElement result = ((creds == null || creds.isEmpty()) ? |
|
null : creds.firstElement()); |
|
|
|
|
|
if (result != null) { |
|
if (initiate) { |
|
checkInitCredPermission((Krb5NameElement) result.getName()); |
|
} else { |
|
checkAcceptCredPermission |
|
((Krb5NameElement) result.getName(), name); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
public Krb5MechFactory(GSSCaller caller) { |
|
this.caller = caller; |
|
} |
|
|
|
public GSSNameSpi getNameElement(String nameStr, Oid nameType) |
|
throws GSSException { |
|
return Krb5NameElement.getInstance(nameStr, nameType); |
|
} |
|
|
|
public GSSNameSpi getNameElement(byte[] name, Oid nameType) |
|
throws GSSException { |
|
// At this point, even an exported name is stripped down to safe |
|
// bytes only |
|
|
|
return Krb5NameElement.getInstance(new String(name), nameType); |
|
} |
|
|
|
public GSSCredentialSpi getCredentialElement(GSSNameSpi name, |
|
int initLifetime, int acceptLifetime, |
|
int usage) throws GSSException { |
|
|
|
if (name != null && !(name instanceof Krb5NameElement)) { |
|
name = Krb5NameElement.getInstance(name.toString(), |
|
name.getStringNameType()); |
|
} |
|
|
|
Krb5CredElement credElement = getCredFromSubject |
|
(name, (usage != GSSCredential.ACCEPT_ONLY)); |
|
|
|
if (credElement == null) { |
|
if (usage == GSSCredential.INITIATE_ONLY || |
|
usage == GSSCredential.INITIATE_AND_ACCEPT) { |
|
credElement = Krb5InitCredential.getInstance |
|
(caller, (Krb5NameElement) name, initLifetime); |
|
credElement = Krb5ProxyCredential.tryImpersonation( |
|
caller, (Krb5InitCredential)credElement); |
|
checkInitCredPermission |
|
((Krb5NameElement) credElement.getName()); |
|
} else if (usage == GSSCredential.ACCEPT_ONLY) { |
|
credElement = |
|
Krb5AcceptCredential.getInstance(caller, |
|
(Krb5NameElement) name); |
|
checkAcceptCredPermission |
|
((Krb5NameElement) credElement.getName(), name); |
|
} else |
|
throw new GSSException(GSSException.FAILURE, -1, |
|
"Unknown usage mode requested"); |
|
} |
|
return credElement; |
|
} |
|
|
|
public static void checkInitCredPermission(Krb5NameElement name) { |
|
SecurityManager sm = System.getSecurityManager(); |
|
if (sm != null) { |
|
String realm = (name.getKrb5PrincipalName()).getRealmAsString(); |
|
String tgsPrincipal = |
|
new String("krbtgt/" + realm + '@' + realm); |
|
ServicePermission perm = |
|
new ServicePermission(tgsPrincipal, "initiate"); |
|
try { |
|
sm.checkPermission(perm); |
|
} catch (SecurityException e) { |
|
if (DEBUG) { |
|
System.out.println("Permission to initiate" + |
|
"kerberos init credential" + e.getMessage()); |
|
} |
|
throw e; |
|
} |
|
} |
|
} |
|
|
|
public static void checkAcceptCredPermission(Krb5NameElement name, |
|
GSSNameSpi originalName) { |
|
SecurityManager sm = System.getSecurityManager(); |
|
if (sm != null && name != null) { |
|
ServicePermission perm = new ServicePermission |
|
(name.getKrb5PrincipalName().getName(), "accept"); |
|
try { |
|
sm.checkPermission(perm); |
|
} catch (SecurityException e) { |
|
if (originalName == null) { |
|
|
|
e = new SecurityException("No permission to acquire " |
|
+ "Kerberos accept credential"); |
|
// Don't call e.initCause() with caught exception |
|
} |
|
throw e; |
|
} |
|
} |
|
} |
|
|
|
public GSSContextSpi getMechanismContext(GSSNameSpi peer, |
|
GSSCredentialSpi myInitiatorCred, int lifetime) |
|
throws GSSException { |
|
if (peer != null && !(peer instanceof Krb5NameElement)) { |
|
peer = Krb5NameElement.getInstance(peer.toString(), |
|
peer.getStringNameType()); |
|
} |
|
|
|
if (myInitiatorCred == null) { |
|
myInitiatorCred = getCredentialElement(null, lifetime, 0, |
|
GSSCredential.INITIATE_ONLY); |
|
} |
|
return new Krb5Context(caller, (Krb5NameElement)peer, |
|
(Krb5CredElement)myInitiatorCred, lifetime); |
|
} |
|
|
|
public GSSContextSpi getMechanismContext(GSSCredentialSpi myAcceptorCred) |
|
throws GSSException { |
|
|
|
if (myAcceptorCred == null) { |
|
myAcceptorCred = getCredentialElement(null, 0, |
|
GSSCredential.INDEFINITE_LIFETIME, GSSCredential.ACCEPT_ONLY); |
|
} |
|
return new Krb5Context(caller, (Krb5CredElement)myAcceptorCred); |
|
} |
|
|
|
public GSSContextSpi getMechanismContext(byte[] exportedContext) |
|
throws GSSException { |
|
return new Krb5Context(caller, exportedContext); |
|
} |
|
|
|
|
|
public final Oid getMechanismOid() { |
|
return GSS_KRB5_MECH_OID; |
|
} |
|
|
|
public Provider getProvider() { |
|
return PROVIDER; |
|
} |
|
|
|
public Oid[] getNameTypes() { |
|
|
|
return nameTypes; |
|
} |
|
|
|
private static Oid createOid(String oidStr) { |
|
Oid retVal = null; |
|
try { |
|
retVal = new Oid(oidStr); |
|
} catch (GSSException e) { |
|
// Should not happen! |
|
} |
|
return retVal; |
|
} |
|
} |