/*******************************************************************************
* Copyright (c) 2007, Dave Whitla
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
package au.net.ocean.httpclient.auth.spnego;
import au.net.ocean.security.auth.gss.GSSMechanism;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
import org.apache.commons.httpclient.auth.InvalidCredentialsException;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
/**
* Created by dwhitla at Apr 18, 2007 9:16:20 PM
*
* @author <a href="mailto:dave.whitla@ocean.net.au">Dave Whitla</a>
* @version $Id: SPNegoCredentials.java 0 Apr 18, 2007 9:16:20 PM dwhitla $
*/
public abstract class SPNegoCredentials implements Credentials {
private GSSContext gssContext;
private Subject subject;
private String jaasContext;
public SPNegoCredentials(String jaasContext) {
this.jaasContext = jaasContext;
}
protected abstract GSSMechanism getMechanism();
public abstract String getPrincipal();
public abstract String getPassword();
public abstract String getRealm();
public GSSContext getGSSContext() {
return gssContext;
}
public void createGSSContext(final String servicePrincipal) throws PrivilegedActionException, GSSException {
GSSMechanism mechanism = getMechanism();
GSSName clientName = mechanism.createGSSName(getPrincipal());
GSSName serviceName = mechanism.createGSSName(servicePrincipal);
gssContext = (GSSContext) Subject.doAs(subject, new CreateGSSContextAction(clientName, serviceName));
}
public void closeGSSContext() throws GSSException {
gssContext.dispose();
}
protected void login() throws LoginException {
LoginContext loginContext = new LoginContext(jaasContext, getCallbackHandler());
loginContext.login();
subject = loginContext.getSubject();
}
private CallbackHandler getCallbackHandler() {
return new SPNegoCallbackHandler(this);
}
public class CreateGSSContextAction implements PrivilegedExceptionAction<GSSContext> {
private GSSName clientName;
private GSSName serviceName;
public CreateGSSContextAction(GSSName clientName, GSSName serviceName) {
this.clientName = clientName;
this.serviceName = serviceName;
}
public GSSContext run() throws Exception {
GSSManager gssManager = GSSManager.getInstance();
GSSMechanism mechanism = getMechanism();
try {
GSSCredential clientCredential = gssManager.createCredential(
clientName, GSSCredential.DEFAULT_LIFETIME, mechanism.getOid(), GSSCredential.INITIATE_ONLY);
//return gssManager.createContext(clientCredential);
return gssManager.createContext(serviceName, mechanism.getOid(), clientCredential, GSSContext.DEFAULT_LIFETIME);
} catch (GSSException e) {
switch (e.getMajor()) {
case GSSException.BAD_NAME:
case GSSException.CREDENTIALS_EXPIRED:
throw new InvalidCredentialsException(e.getMessage(), e);
case GSSException.BAD_MECH:
case GSSException.BAD_NAMETYPE:
case GSSException.NO_CRED:
throw new CredentialsNotAvailableException(e.getMessage(), e);
case GSSException.FAILURE:
default:
throw e;
}
}
}
}
}