--- java/org/apache/catalina/Realm.java (revision 1666658)
+++ java/org/apache/catalina/Realm.java (working copy)
@@ -76,6 +76,15 @@
/**
+ * Return the Principal associated with the specified username, if there
+ * is one; otherwise return null
.
+ *
+ * @param username Username of the Principal to look up
+ */
+ public Principal authenticate(String username);
+
+
+ /**
* Return the Principal associated with the specified username and
* credentials, if there is one; otherwise return null
.
*
--- java/org/apache/catalina/authenticator/BasicAuthenticator.java (revision 1666658)
+++ java/org/apache/catalina/authenticator/BasicAuthenticator.java (working copy)
@@ -120,6 +120,21 @@
return true;
}
+ // If we are preauthenticated, run the authorization
+ String remoteUser = (String)
+ request.getCoyoteRequest().getAttribute(Constants.REQ_REMOTE_USER_NOTE);
+ if (remoteUser != null) {
+ if (log.isDebugEnabled())
+ log.debug("Already authenticated '" + remoteUser + "', authorizing");
+ principal = context.getRealm().authenticate(remoteUser);
+ if (principal != null) {
+ register(request, response, principal,
+ HttpServletRequest.BASIC_AUTH, remoteUser, null);
+ return (true);
+ }
+ return (false);
+ }
+
// Validate any credentials already included with this request
String username = null;
String password = null;
--- java/org/apache/catalina/authenticator/Constants.java (revision 1666658)
+++ java/org/apache/catalina/authenticator/Constants.java (working copy)
@@ -85,6 +85,12 @@
public static final String REQ_SSOID_NOTE =
"org.apache.catalina.request.SSOID";
+ /**
+ * The notes key to track the principal name when the user is
+ * pre-authenticated, but where tomcat must perform authorization.
+ */
+ public static final String REQ_REMOTE_USER_NOTE =
+ "org.apache.catalina.request.REMOTE_USER";
// ---------------------------------------------------------- Session Notes
--- java/org/apache/catalina/authenticator/DigestAuthenticator.java (revision 1666658)
+++ java/org/apache/catalina/authenticator/DigestAuthenticator.java (working copy)
@@ -291,6 +291,21 @@
}
*/
+ // If we are preauthenticated, run the authorization
+ String remoteUser = (String)
+ request.getCoyoteRequest().getAttribute(Constants.REQ_REMOTE_USER_NOTE);
+ if (remoteUser != null) {
+ if (log.isDebugEnabled())
+ log.debug("Already authenticated '" + remoteUser + "', authorizing");
+ principal = context.getRealm().authenticate(remoteUser);
+ if (principal != null) {
+ register(request, response, principal,
+ HttpServletRequest.DIGEST_AUTH, remoteUser, null);
+ return (true);
+ }
+ return (false);
+ }
+
// Validate any credentials already included with this request
String authorization = request.getHeader("authorization");
DigestInfo digestInfo = new DigestInfo(getOpaque(), getNonceValidity(),
--- java/org/apache/catalina/authenticator/FormAuthenticator.java (revision 1666658)
+++ java/org/apache/catalina/authenticator/FormAuthenticator.java (working copy)
@@ -184,6 +184,22 @@
}
}
+ // If we are preauthenticated, run the authorization
+ String remoteUser = (String)
+ request.getCoyoteRequest().getAttribute(Constants.REQ_REMOTE_USER_NOTE);
+ if (remoteUser != null) {
+ if (log.isDebugEnabled())
+ log.debug("Already authenticated '" + remoteUser + "', authorizing");
+ principal = context.getRealm().authenticate(remoteUser);
+ if (principal != null) {
+ session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);
+ register(request, response, principal,
+ HttpServletRequest.FORM_AUTH, remoteUser, null);
+ return (true);
+ }
+ return (false);
+ }
+
// Have we authenticated this user before but have caching disabled?
if (!cache) {
session = request.getSessionInternal(true);
--- java/org/apache/catalina/authenticator/SSLAuthenticator.java (revision 1666658)
+++ java/org/apache/catalina/authenticator/SSLAuthenticator.java (working copy)
@@ -98,6 +98,21 @@
return (true);
}
+ // If we are preauthenticated, run the authorization
+ String remoteUser = (String)
+ request.getCoyoteRequest().getAttribute(Constants.REQ_REMOTE_USER_NOTE);
+ if (remoteUser != null) {
+ if (containerLog.isDebugEnabled())
+ containerLog.debug("Already authenticated '" + remoteUser + "', authorizing");
+ principal = context.getRealm().authenticate(remoteUser);
+ if (principal != null) {
+ register(request, response, principal,
+ HttpServletRequest.CLIENT_CERT_AUTH, remoteUser, null);
+ return (true);
+ }
+ return (false);
+ }
+
// NOTE: We don't try to reauthenticate using any existing SSO session,
// because that will only work if the original authentication was
// BASIC or FORM, which are less secure than the CLIENT_CERT auth-type
--- java/org/apache/catalina/authenticator/SpnegoAuthenticator.java (revision 1666658)
+++ java/org/apache/catalina/authenticator/SpnegoAuthenticator.java (working copy)
@@ -167,6 +167,21 @@
}
}
+ // If we are preauthenticated, run the authorization
+ String remoteUser = (String)
+ request.getCoyoteRequest().getAttribute(Constants.REQ_REMOTE_USER_NOTE);
+ if (remoteUser != null) {
+ if (log.isDebugEnabled())
+ log.debug("Already authenticated '" + remoteUser + "', authorizing");
+ principal = context.getRealm().authenticate(remoteUser);
+ if (principal != null) {
+ register(request, response, principal,
+ Constants.SPNEGO_METHOD, remoteUser, null);
+ return (true);
+ }
+ return (false);
+ }
+
MessageBytes authorization =
request.getCoyoteRequest().getMimeHeaders()
.getValue("authorization");
--- java/org/apache/catalina/realm/RealmBase.java (revision 1666658)
+++ java/org/apache/catalina/realm/RealmBase.java (working copy)
@@ -347,6 +347,28 @@
/**
+ * Return the Principal associated with the specified username, if there
+ * is one; otherwise return null
.
+ *
+ * @param username Username of the Principal to look up
+ */
+ @Override
+ public Principal authenticate(String username) {
+
+ if (username == null) {
+ return null;
+ }
+
+ if (containerLog.isTraceEnabled()) {
+ containerLog.trace(sm.getString("realmBase.authenticateSuccess",
+ username));
+ }
+
+ return getPrincipal(username);
+ }
+
+
+ /**
* Return the Principal associated with the specified username and
* credentials, if there is one; otherwise return null
.
*
--- java/org/apache/coyote/ajp/AbstractAjpProcessor.java (revision 1666658)
+++ java/org/apache/coyote/ajp/AbstractAjpProcessor.java (working copy)
@@ -277,6 +277,16 @@
/**
+ * Use Tomcat authorization ?
+ */
+ protected boolean tomcatAuthorization = false;
+ public boolean getTomcatAuthorization() { return tomcatAuthorization; }
+ public void setTomcatAuthorization(boolean tomcatAuthorization) {
+ this.tomcatAuthorization = tomcatAuthorization;
+ }
+
+
+ /**
* Required secret.
*/
protected String requiredSecret = null;
@@ -828,11 +838,17 @@
break;
case Constants.SC_A_REMOTE_USER :
- if (tomcatAuthentication) {
+ if (tomcatAuthorization) {
+ requestHeaderMessage.getBytes(tmpMB);
+ request.setAttribute(
+ org.apache.catalina.authenticator.Constants.REQ_REMOTE_USER_NOTE,
+ tmpMB.toString());
+ }
+ else if (tomcatAuthentication) {
// ignore server
requestHeaderMessage.getBytes(tmpMB);
} else {
- requestHeaderMessage.getBytes(request.getRemoteUser());
+ requestHeaderMessage.getBytes(request.getRemoteUser());
}
break;
--- java/org/apache/coyote/ajp/AbstractAjpProtocol.java (revision 1666658)
+++ java/org/apache/coyote/ajp/AbstractAjpProtocol.java (working copy)
@@ -52,6 +52,13 @@
}
+ protected boolean tomcatAuthorization = false;
+ public boolean getTomcatAuthorization() { return tomcatAuthorization; }
+ public void setTomcatAuthorization(boolean tomcatAuthorization) {
+ this.tomcatAuthorization = tomcatAuthorization;
+ }
+
+
/**
* Required secret.
*/
--- java/org/apache/coyote/ajp/AjpAprProtocol.java (revision 1666658)
+++ java/org/apache/coyote/ajp/AjpAprProtocol.java (working copy)
@@ -146,6 +146,7 @@
AjpAprProcessor processor = new AjpAprProcessor(proto.packetSize, (AprEndpoint)proto.endpoint);
processor.setAdapter(proto.adapter);
processor.setTomcatAuthentication(proto.tomcatAuthentication);
+ processor.setTomcatAuthorization(proto.tomcatAuthorization);
processor.setRequiredSecret(proto.requiredSecret);
processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());
processor.setClientCertProvider(proto.getClientCertProvider());
--- java/org/apache/coyote/ajp/AjpNioProtocol.java (revision 1666658)
+++ java/org/apache/coyote/ajp/AjpNioProtocol.java (working copy)
@@ -172,6 +172,7 @@
AjpNioProcessor processor = new AjpNioProcessor(proto.packetSize, (NioEndpoint)proto.endpoint);
processor.setAdapter(proto.adapter);
processor.setTomcatAuthentication(proto.tomcatAuthentication);
+ processor.setTomcatAuthorization(proto.tomcatAuthorization);
processor.setRequiredSecret(proto.requiredSecret);
processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());
processor.setClientCertProvider(proto.getClientCertProvider());
--- java/org/apache/coyote/ajp/AjpProtocol.java (revision 1666658)
+++ java/org/apache/coyote/ajp/AjpProtocol.java (working copy)
@@ -134,6 +134,7 @@
AjpProcessor processor = new AjpProcessor(proto.packetSize, (JIoEndpoint)proto.endpoint);
processor.setAdapter(proto.adapter);
processor.setTomcatAuthentication(proto.tomcatAuthentication);
+ processor.setTomcatAuthorization(proto.tomcatAuthorization);
processor.setRequiredSecret(proto.requiredSecret);
processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());
processor.setClientCertProvider(proto.getClientCertProvider());
--- webapps/docs/config/ajp.xml (revision 1666658)
+++ webapps/docs/config/ajp.xml (working copy)
@@ -432,9 +432,18 @@
If set to true
, the authentication will be done in Tomcat.
Otherwise, the authenticated principal will be propagated from the native
webserver and used for authorization in Tomcat.
- The default value is true
.
true
. If
+ tomcatAuthorization
is set to true
this
+ attribute has no effect.
+ If set to true
, the authenticated principal will be
+ propagated from the native webserver and considered already authenticated
+ in Tomcat. Authorization will then be performed by Tomcat as normal.
+ The default value is false
.
The tomcatAuthentication attribute is used with the +
The tomcatAuthentication and + tomcatAuthorization attributes are used with the AJP connectors to determine if Tomcat should authenticate the user or if authentication can be delegated to the reverse proxy that will then pass the authenticated username to Tomcat as part of the AJP protocol.
--- webapps/docs/windows-auth-howto.xml (revision 1666658) +++ webapps/docs/windows-auth-howto.xml (working copy) @@ -299,7 +299,9 @@false
.false
. Alternatively, set the
+ tomcatAuthorization attribute to true
to allow Windows to
+ authenticate, while Tomcat performs the authorization.