[jboss-cvs] JBossAS SVN: r109516 - projects/security/security-negotiation/branches/dlofthouse/SECURITY-132/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Sat Nov 27 13:52:54 EST 2010
Author: darran.lofthouse at jboss.com
Date: 2010-11-27 13:52:54 -0500 (Sat, 27 Nov 2010)
New Revision: 109516
Modified:
projects/security/security-negotiation/branches/dlofthouse/SECURITY-132/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/SPNEGOLoginModule.java
Log:
Add implementation to SPNEGO Login Module to delegate to additional domain.
Modified: projects/security/security-negotiation/branches/dlofthouse/SECURITY-132/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/SPNEGOLoginModule.java
===================================================================
--- projects/security/security-negotiation/branches/dlofthouse/SECURITY-132/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/SPNEGOLoginModule.java 2010-11-27 18:00:06 UTC (rev 109515)
+++ projects/security/security-negotiation/branches/dlofthouse/SECURITY-132/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/SPNEGOLoginModule.java 2010-11-27 18:52:54 UTC (rev 109516)
@@ -30,6 +30,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
@@ -42,7 +43,6 @@
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.Oid;
import org.jboss.security.SimpleGroup;
-import org.jboss.security.auth.spi.AbstractServerLoginModule;
import org.jboss.security.negotiation.NegotiationMessage;
import org.jboss.security.negotiation.common.CommonLoginModule;
import org.jboss.security.negotiation.common.NegotiationContext;
@@ -60,17 +60,42 @@
public class SPNEGOLoginModule extends CommonLoginModule
{
- private static final String SPNEGO = "SPNEGO";
+ /*
+ * Configuration Option Constants
+ */
+ // If true drop the @REALM from the identity.
private static final String REMOVE_REALM_FROM_PRINCIPAL = "removeRealmFromPrincipal";
+ // The security domain to authenticate to obtain the servers identity.
+ private static final String SERVER_SECURITY_DOMAIN = "serverSecurityDomain";
+
+ // The security domain to delegate username/password authentication to.
+ private static final String USERNAME_PASSWORD_DOMAIN = "usernamePasswordDomain";
+
+ /*
+ * General Constants
+ */
+
+ private static final String SPNEGO = "SPNEGO";
+
private static final Oid kerberos = KERBEROS_V5;
+ /*
+ * Configuration Options
+ */
+
+ private boolean removeRealmFromPrincipal;
+
// TODO - Pick a name for a default domain?
private String serverSecurityDomain;
- private boolean removeRealmFromPrincipal;
+ private String usernamePasswordDomain;
+ /*
+ * Module State
+ */
+
private LoginContext serverLoginContext = null;
@Override
@@ -80,15 +105,21 @@
super.initialize(subject, callbackHandler, sharedState, options);
String temp;
// Which security domain to authenticate the server.
- serverSecurityDomain = (String) options.get("serverSecurityDomain");
- if (log.isDebugEnabled())
- log.debug("serverSecurityDomain=" + serverSecurityDomain);
+ serverSecurityDomain = (String) options.get(SERVER_SECURITY_DOMAIN);
+ // Which security domain to delegate username/password authentication to.
+ usernamePasswordDomain = (String) options.get(USERNAME_PASSWORD_DOMAIN);
temp = (String) options.get(REMOVE_REALM_FROM_PRINCIPAL);
removeRealmFromPrincipal = Boolean.valueOf(temp);
if (removeRealmFromPrincipal == false && principalClassName == null)
{
principalClassName = KerberosPrincipal.class.getName();
}
+ if (log.isDebugEnabled())
+ {
+ log.debug("removeRealmFromPrincipal=" + removeRealmFromPrincipal);
+ log.debug("serverSecurityDomain=" + serverSecurityDomain);
+ log.debug("usernamePasswordDomain=" + usernamePasswordDomain);
+ }
}
@Override
@@ -103,7 +134,94 @@
super.loginOk = false;
+ Object result = innerLogin();
+
+ if (TRACE)
+ log.trace("Result - " + result);
+
+ if (result instanceof Boolean)
+ {
+ if (Boolean.TRUE.equals(result))
+ {
+ super.loginOk = true;
+ if (getUseFirstPass() == true)
+ {
+ Principal identity = getIdentity();
+ String userName = identity.getName();
+ if (log.isDebugEnabled())
+ log.debug("Storing username '" + userName + "' and empty password");
+ // Add the username and a null password to the shared state map
+ sharedState.put("javax.security.auth.login.name", identity);
+ sharedState.put("javax.security.auth.login.password", "");
+ }
+ }
+ }
+ else if (result instanceof Exception)
+ {
+ Exception e = (Exception) result;
+ log.error("Unable to authenticate", e);
+ throw new LoginException("Unable to authenticate - " + e.getMessage());
+ }
+
+ if (TRACE)
+ log.trace("super.loginOk " + super.loginOk);
+ if (super.loginOk == true)
+ {
+ return true;
+ }
+ else
+ {
+ throw new LoginException("Continuation Required.");
+ }
+
+ }
+
+ protected Object innerLogin() throws LoginException
+ {
NegotiationContext negotiationContext = NegotiationContext.getCurrentNegotiationContext();
+
+ if (negotiationContext == null)
+ {
+ if (usernamePasswordDomain == null)
+ {
+ throw new LoginException("No NegotiationContext and no usernamePasswordDomain defined.");
+ }
+
+ return usernamePasswordLogin();
+ }
+ else
+ {
+ return spnegoLogin(negotiationContext);
+ }
+
+ }
+
+ private Object usernamePasswordLogin() throws LoginException
+ {
+ log.debug("Falling back to username/password authentication");
+
+ LoginContext lc = new LoginContext(usernamePasswordDomain, callbackHandler);
+ lc.login();
+
+ Subject userSubject = lc.getSubject();
+ Set principals = userSubject.getPrincipals();
+ if (principals.isEmpty())
+ {
+ throw new LoginException("No principal returned after login.");
+ }
+ else if (principals.size() > 1)
+ {
+ log.warn("Multiple principals returned, using first principal in set.");
+ }
+
+ Principal identity = (Principal) principals.iterator().next();
+ setIdentity(identity);
+
+ return Boolean.TRUE;
+ }
+
+ private Object spnegoLogin(NegotiationContext negotiationContext) throws LoginException
+ {
NegotiationMessage requestMessage = negotiationContext.getRequestMessage();
if (requestMessage instanceof SPNEGOMessage == false)
{
@@ -118,33 +236,7 @@
AcceptSecContext action = new AcceptSecContext(negotiationContext);
Object result = Subject.doAs(server, action);
- if (TRACE)
- log.trace("Result - " + result);
-
- if (result instanceof Boolean)
- {
- if (Boolean.TRUE.equals(result))
- {
- super.loginOk = true;
- if (getUseFirstPass() == true)
- {
- Principal identity = getIdentity();
- String userName = identity.getName();
- if (log.isDebugEnabled())
- log.debug("Storing username '" + userName + "' and empty password");
- // Add the username and a null password to the shared state map
- sharedState.put("javax.security.auth.login.name", identity);
- sharedState.put("javax.security.auth.login.password", "");
- }
- }
- }
- else if (result instanceof Exception)
- {
- Exception e = (Exception) result;
- log.error("Unable to authenticate", e);
- throw new LoginException("Unable to authenticate - " + e.getMessage());
- }
-
+ return result;
}
finally
{
@@ -155,18 +247,8 @@
}
}
- if (TRACE)
- log.trace("super.loginOk " + super.loginOk);
- if (super.loginOk == true)
- {
- return true;
- }
- else
- {
- throw new LoginException("Continuation Required.");
- }
-
}
+
@Override
protected Principal createIdentity(final String username) throws Exception
More information about the jboss-cvs-commits
mailing list