Author: markt
Date: Tue Mar 29 20:05:04 2011
New Revision: 1086706
URL: http://svn.apache.org/viewvc?rev=1086706&view=rev
Log:
Part 2 of SPNEGO/Windows authentication support.
Authorisation support. Works essentially the same way as CLIENT-CERT, i.e. the
Realm doesn't actually authenticate the user but it does create the Principal
and add the roles.
Modified:
tomcat/trunk/java/org/apache/catalina/Realm.java
tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
tomcat/trunk/java/org/apache/catalina/realm/CombinedRealm.java
tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties
tomcat/trunk/java/org/apache/catalina/realm/LockOutRealm.java
tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java
Modified: tomcat/trunk/java/org/apache/catalina/Realm.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Realm.java?rev=1086706&r1=1086705&r2=1086706&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Realm.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Realm.java Tue Mar 29 20:05:04 2011
@@ -26,6 +26,7 @@ import java.security.cert.X509Certificat
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.deploy.SecurityConstraint;
+import org.ietf.jgss.GSSContext;
/**
* A <b>Realm</b> is a read-only facade for an underlying security realm
* used to authenticate individual users, and identify the security roles
@@ -110,7 +111,16 @@ public interface Realm {
* Return the Principal associated with the specified chain of X509
* client certificates. If there is none, return <code>null</code>.
*
- * @param certs Array of client certificates, with the first one in
+ * @param certs The gssContext processed by the {@link Authenticator}.
+ */
+ public Principal authenticate(GSSContext gssContext);
+
+
+ /**
+ * Return the Principal associated with the specified {@link GSSContext}.
+ * If there is none, return <code>null</code>.
+ *
+ * @param gssContext Array of client certificates, with the first one in
* the array being the certificate of the client itself.
*/
public Principal authenticate(X509Certificate certs[]);
Modified:
tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java?rev=1086706&r1=1086705&r2=1086706&view=diff
==============================================================================
---
tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
(original)
+++
tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
Tue Mar 29 20:05:04 2011
@@ -33,10 +33,10 @@ import javax.security.auth.login.LoginCo
import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletResponse;
+import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Request;
import org.apache.catalina.deploy.LoginConfig;
-import org.apache.catalina.realm.GenericPrincipal;
import org.apache.catalina.startup.Bootstrap;
import org.apache.catalina.util.Base64;
import org.apache.juli.logging.Log;
@@ -47,7 +47,7 @@ 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;
+
/**
* A SPNEGO authenticator that uses the SPENGO/Kerberos support built in to
Java
@@ -208,7 +208,8 @@ public class SpnegoAuthenticator extends
try {
principal = Subject.doAs(serviceSubject,
- new KerberosAuthAction(decoded.getBytes(),
response));
+ new KerberosAuthAction(decoded.getBytes(),
+ response, context));
} catch (PrivilegedActionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -235,10 +236,13 @@ public class SpnegoAuthenticator extends
private byte[] inToken;
private HttpServletResponse resp;
+ private Context context;
- public KerberosAuthAction(byte[] inToken, HttpServletResponse resp) {
+ public KerberosAuthAction(byte[] inToken, HttpServletResponse resp,
+ Context context) {
this.inToken = inToken;
this.resp = resp;
+ this.context = context;
}
@Override
@@ -246,7 +250,7 @@ public class SpnegoAuthenticator extends
// Assume the GSSContext is stateless
// TODO: Confirm this assumption
- GSSContext context =
+ GSSContext gssContext =
GSSManager.getInstance().createContext((GSSCredential) null);
Principal principal = null;
@@ -256,26 +260,19 @@ public class SpnegoAuthenticator extends
}
byte[] outToken =
- context.acceptSecContext(inToken, 0, inToken.length);
+ gssContext.acceptSecContext(inToken, 0, inToken.length);
if (outToken == null) {
throw new GSSException(GSSException.DEFECTIVE_TOKEN);
}
- GSSName initiatorName = context.getSrcName();
-
- if (context.isEstablished()) {
- // TODO This (and a lot of the surrounding code) needs to move
- // to RealmBase so authorisation will work. This is just a
quick
- // hack to get authentication working.
- principal = new GenericPrincipal(initiatorName.toString(),
null);
- }
+ principal = context.getRealm().authenticate(gssContext);
// Send response token on success and failure
resp.setHeader("WWW-Authenticate", "Negotiate "
+ Base64.encode(outToken));
- context.dispose();
+ gssContext.dispose();
return principal;
}
}
Modified: tomcat/trunk/java/org/apache/catalina/realm/CombinedRealm.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/CombinedRealm.java?rev=1086706&r1=1086705&r2=1086706&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/CombinedRealm.java (original)
+++ tomcat/trunk/java/org/apache/catalina/realm/CombinedRealm.java Tue Mar 29
20:05:04 2011
@@ -31,6 +31,9 @@ import org.apache.catalina.LifecycleExce
import org.apache.catalina.Realm;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSName;
/**
* Realm implementation that contains one or more realms. Authentication is
@@ -264,6 +267,53 @@ public class CombinedRealm extends Realm
return authenticatedUser;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Principal authenticate(GSSContext gssContext) {
+ if (gssContext.isEstablished()) {
+ Principal authenticatedUser = null;
+ String username = null;
+
+ GSSName name = null;
+ try {
+ name = gssContext.getSrcName();
+ } catch (GSSException e) {
+ log.warn(sm.getString("realmBase.gssNameFail"), e);
+ return null;
+ }
+
+ username = name.toString();
+
+ for (Realm realm : realms) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("combinedRealm.authStart",
+ username, realm.getInfo()));
+ }
+
+ authenticatedUser = realm.authenticate(gssContext);
+
+ if (authenticatedUser == null) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("combinedRealm.authFail",
+ username, realm.getInfo()));
+ }
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("combinedRealm.authSucess",
+ username, realm.getInfo()));
+ }
+ break;
+ }
+ }
+ return authenticatedUser;
+ }
+
+ // Fail in all other cases
+ return null;
+ }
+
@Override
protected String getName() {
return name;
Modified: tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties?rev=1086706&r1=1086705&r2=1086706&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties
(original)
+++ tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties Tue Mar
29 20:05:04 2011
@@ -73,6 +73,7 @@ realmBase.notAuthenticated=Configuration
realmBase.notStarted=This Realm has not yet been started
realmBase.authenticateFailure=Username {0} NOT successfully authenticated
realmBase.authenticateSuccess=Username {0} successfully authenticated
+realmBase.gssNameFail=Failed to extract name from established GSSContext
userDatabaseRealm.authenticateError=Login configuration error authenticating
username {0}
userDatabaseRealm.lookup=Exception looking up UserDatabase under key {0}
userDatabaseRealm.noDatabase=No UserDatabase component found under key {0}
Modified: tomcat/trunk/java/org/apache/catalina/realm/LockOutRealm.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/LockOutRealm.java?rev=1086706&r1=1086705&r2=1086706&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/LockOutRealm.java (original)
+++ tomcat/trunk/java/org/apache/catalina/realm/LockOutRealm.java Tue Mar 29
20:05:04 2011
@@ -26,6 +26,9 @@ import java.util.concurrent.atomic.Atomi
import org.apache.catalina.LifecycleException;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSName;
/**
* This class extends the CombinedRealm (hence it can wrap other Realms) to
@@ -219,6 +222,46 @@ public class LockOutRealm extends Combin
/**
+ * {@inheritDoc}
+ */
+ @Override
+ public Principal authenticate(GSSContext gssContext) {
+ if (gssContext.isEstablished()) {
+ String username = null;
+ GSSName name = null;
+ try {
+ name = gssContext.getSrcName();
+ } catch (GSSException e) {
+ log.warn(sm.getString("realmBase.gssNameFail"), e);
+ return null;
+ }
+
+ username = name.toString();
+
+ if (isLocked(username)) {
+ // Trying to authenticate a locked user is an automatic failure
+ registerAuthFailure(username);
+
+ log.warn(sm.getString("lockOutRealm.authLockedUser",
username));
+ return null;
+ }
+
+ Principal authenticatedUser = super.authenticate(gssContext);
+
+ if (authenticatedUser == null) {
+ registerAuthFailure(username);
+ } else {
+ registerAuthSuccess(username);
+ }
+ return authenticatedUser;
+ }
+
+ // Fail in all other cases
+ return null;
+ }
+
+
+ /**
* Unlock the specified username. This will remove all records of
* authentication failures for this user.
*
Modified: tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java?rev=1086706&r1=1086705&r2=1086706&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java (original)
+++ tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java Tue Mar 29
20:05:04 2011
@@ -54,6 +54,9 @@ import org.apache.catalina.util.MD5Encod
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSName;
/**
* Simple implementation of <b>Realm</b> that reads an XML file to configure
@@ -418,6 +421,29 @@ public abstract class RealmBase extends
/**
+ * {@inheritDoc}
+ */
+ @Override
+ public Principal authenticate(GSSContext gssContext) {
+ if (gssContext.isEstablished()) {
+ GSSName name = null;
+ try {
+ name = gssContext.getSrcName();
+ } catch (GSSException e) {
+ log.warn(sm.getString("realmBase.gssNameFail"), e);
+ }
+
+ if (name!= null) {
+ return getPrincipal(name.toString());
+ }
+ }
+
+ // Fail in all other cases
+ return null;
+ }
+
+
+ /**
* Execute a periodic task, such as reloading, etc. This method will be
* invoked inside the classloading context of this container. Unexpected
* throwables will be caught and logged.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]