You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2015/03/18 15:19:14 UTC

svn commit: r1667558 - in /tomcat/tc8.0.x/trunk: ./ java/org/apache/catalina/ java/org/apache/catalina/authenticator/ java/org/apache/catalina/connector/ java/org/apache/catalina/realm/ java/org/apache/coyote/ java/org/apache/coyote/ajp/ webapps/docs/ ...

Author: markt
Date: Wed Mar 18 14:19:14 2015
New Revision: 1667558

URL: http://svn.apache.org/r1667558
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=57708
Implement a new feature for AJP connectors - Tomcat Authorization
If configured (it is disabled by default) Tomcat will take an authenticated user name from the AJP protocol and use the appropriate Realm for the request to authorize (i.e. add roles) to that user.
Based on a patch by Graham Leggett.

Modified:
    tomcat/tc8.0.x/trunk/   (props changed)
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/Realm.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/BasicAuthenticator.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/LocalStrings.properties
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/NonLoginAuthenticator.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/LocalStrings.properties
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/realm/CombinedRealm.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java
    tomcat/tc8.0.x/trunk/java/org/apache/coyote/Request.java
    tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
    tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
    tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml
    tomcat/tc8.0.x/trunk/webapps/docs/config/ajp.xml
    tomcat/tc8.0.x/trunk/webapps/docs/security-howto.xml
    tomcat/tc8.0.x/trunk/webapps/docs/windows-auth-howto.xml

Propchange: tomcat/tc8.0.x/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Mar 18 14:19:14 2015
@@ -1 +1 @@
-/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640083-1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642233,1642280,1642554,1642564,1642595,1642606,1642668,1642679,1642697,1642699,1642766,1643002,1643045,1643054-1643055,1643066,1643121,1643128,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323,1643365-1643366,1643370-1643371,1643465,1643474,1643536,1643570,1643634,1643649,1643651,1643654,1643675,1643731,1643733-1643734,1643761,1643766,1643814,1643937,1643963,1644017,1644169,1644201-1644203,1644321,1644323,1644516,1644523,1644529,1644535,1644730,1644768,1644784-1644785,1644790,1644793,1644815,1644884,1644886,1644890,1644892
 ,1644910,1644924,1644929-1644930,1644935,1644989,1645011,1645247,1645355,1645357-1645358,1645455,1645465,1645469,1645471,1645473,1645475,1645486-1645488,1645626,1645641,1645685,1645743,1645763,1645951-1645953,1645955,1645993,1646098-1646106,1646178,1646220,1646302,1646304,1646420,1646470-1646471,1646476,1646559,1646717-1646723,1646773,1647026,1647042,1647530,1647655,1648304,1648815,1648907,1650081,1650365,1651116,1651120,1651280,1651470,1652938,1652970,1653041,1653471,1653550,1653574,1653797,1653815-1653816,1653819,1653840,1653857,1653888,1653972,1654013,1654030,1654050,1654123,1654148,1654159,1654513,1654515,1654517,1654522,1654524,1654725,1654735,1654766,1654785,1654851-1654852,1654978,1655122-1655124,1655126-1655127,1655129-1655130,1655132-1655133,1655312,1655438,1655441,1655454,1655558,1656087,1656299,1656319,1656331,1656345,1656350,1656590,1656648-1656650,1656657,1657041,1657054,1657374,1657492,1657510,1657565,1657580,1657584,1657586,1657589,1657592,1657607,1657609,1657682,1657
 907,1658207,1658734,1658781,1658790,1658799,1658802,1658804,1658833,1658840,1658966,1659043,1659053,1659059,1659188-1659189,1659216,1659263,1659293,1659304,1659306-1659307,1659382,1659384,1659428,1659471,1659486,1659505,1659516,1659521,1659524,1659559,1659562,1659803,1659806,1659814,1659833,1659862,1659905,1659919,1659948,1659967,1659983-1659984,1660060,1660074,1660077,1660133,1660168,1660331-1660332,1660353,1660358,1660924,1661386,1661867,1661972,1661990,1662200,1662308-1662309,1662548,1662614,1662736,1662985,1662988-1662989,1663264,1663277,1663298,1663324,1663534,1663562,1663676,1663715,1663754,1663768,1663772,1663781,1663893,1663995,1664143,1664163,1664174,1664301,1664317,1664347,1664657,1664659,1664710,1664863-1664864,1664866,1665085,1665292,1665559,1665653,1665661,1665672,1665694,1665697,1665736,1665779,1665976-1665977,1665980-1665981,1665985-1665986,1665989,1665998,1666004,1666008,1666013,1666017,1666024,1666116,1666386-1666387,1666494,1666496,1666552,1666569,1666579,1666637,1
 666649,1666757,1666966,1666972,1666985,1666995,1666997,1667292,1667402,1667406
+/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640083-1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642233,1642280,1642554,1642564,1642595,1642606,1642668,1642679,1642697,1642699,1642766,1643002,1643045,1643054-1643055,1643066,1643121,1643128,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323,1643365-1643366,1643370-1643371,1643465,1643474,1643536,1643570,1643634,1643649,1643651,1643654,1643675,1643731,1643733-1643734,1643761,1643766,1643814,1643937,1643963,1644017,1644169,1644201-1644203,1644321,1644323,1644516,1644523,1644529,1644535,1644730,1644768,1644784-1644785,1644790,1644793,1644815,1644884,1644886,1644890,1644892
 ,1644910,1644924,1644929-1644930,1644935,1644989,1645011,1645247,1645355,1645357-1645358,1645455,1645465,1645469,1645471,1645473,1645475,1645486-1645488,1645626,1645641,1645685,1645743,1645763,1645951-1645953,1645955,1645993,1646098-1646106,1646178,1646220,1646302,1646304,1646420,1646470-1646471,1646476,1646559,1646717-1646723,1646773,1647026,1647042,1647530,1647655,1648304,1648815,1648907,1650081,1650365,1651116,1651120,1651280,1651470,1652938,1652970,1653041,1653471,1653550,1653574,1653797,1653815-1653816,1653819,1653840,1653857,1653888,1653972,1654013,1654030,1654050,1654123,1654148,1654159,1654513,1654515,1654517,1654522,1654524,1654725,1654735,1654766,1654785,1654851-1654852,1654978,1655122-1655124,1655126-1655127,1655129-1655130,1655132-1655133,1655312,1655438,1655441,1655454,1655558,1656087,1656299,1656319,1656331,1656345,1656350,1656590,1656648-1656650,1656657,1657041,1657054,1657374,1657492,1657510,1657565,1657580,1657584,1657586,1657589,1657592,1657607,1657609,1657682,1657
 907,1658207,1658734,1658781,1658790,1658799,1658802,1658804,1658833,1658840,1658966,1659043,1659053,1659059,1659188-1659189,1659216,1659263,1659293,1659304,1659306-1659307,1659382,1659384,1659428,1659471,1659486,1659505,1659516,1659521,1659524,1659559,1659562,1659803,1659806,1659814,1659833,1659862,1659905,1659919,1659948,1659967,1659983-1659984,1660060,1660074,1660077,1660133,1660168,1660331-1660332,1660353,1660358,1660924,1661386,1661867,1661972,1661990,1662200,1662308-1662309,1662548,1662614,1662736,1662985,1662988-1662989,1663264,1663277,1663298,1663324,1663534,1663562,1663676,1663715,1663754,1663768,1663772,1663781,1663893,1663995,1664143,1664163,1664174,1664301,1664317,1664347,1664657,1664659,1664710,1664863-1664864,1664866,1665085,1665292,1665559,1665653,1665661,1665672,1665694,1665697,1665736,1665779,1665976-1665977,1665980-1665981,1665985-1665986,1665989,1665998,1666004,1666008,1666013,1666017,1666024,1666116,1666386-1666387,1666494,1666496,1666552,1666569,1666579,1666637,1
 666649,1666757,1666966,1666972,1666985,1666995,1666997,1667292,1667402,1667406,1667546

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/Realm.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/Realm.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/Realm.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/Realm.java Wed Mar 18 14:19:14 2015
@@ -76,6 +76,15 @@ public interface Realm {
 
 
     /**
+     * Return the Principal associated with the specified username, if there
+     * is one; otherwise return <code>null</code>.
+     *
+     * @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 <code>null</code>.
      *

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java Wed Mar 18 14:19:14 2015
@@ -40,6 +40,7 @@ import org.apache.catalina.Valve;
 import org.apache.catalina.Wrapper;
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
+import org.apache.catalina.realm.GenericPrincipal;
 import org.apache.catalina.util.SessionIdGeneratorBase;
 import org.apache.catalina.util.StandardSessionIdGenerator;
 import org.apache.catalina.valves.ValveBase;
@@ -687,20 +688,22 @@ public abstract class AuthenticatorBase
      * authenticate the user without requiring further user interaction.
      *
      * @param request The current request
+     * @param response The current response
      * @param useSSO  Should information available from SSO be used to attempt
      *                to authenticate the current user?
      *
      * @return <code>true</code> if the user was authenticated via the cache,
      *         otherwise <code>false</code>
      */
-    protected boolean checkForCachedAuthentication(Request request, boolean useSSO) {
+    protected boolean checkForCachedAuthentication(Request request,
+            HttpServletResponse response, boolean useSSO) {
 
         // Has the user already been authenticated?
         Principal principal = request.getUserPrincipal();
         String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
         if (principal != null) {
             if (log.isDebugEnabled()) {
-                log.debug("Already authenticated '" + principal.getName() + "'");
+                log.debug(sm.getString("authenticator.check.found", principal.getName()));
             }
             // Associate the session with any existing SSO session. Even if
             // useSSO is false, this will ensure coordinated session
@@ -714,8 +717,7 @@ public abstract class AuthenticatorBase
         // Is there an SSO session against which we can try to reauthenticate?
         if (useSSO && ssoId != null) {
             if (log.isDebugEnabled()) {
-                log.debug("SSO Id " + ssoId + " set; attempting " +
-                          "reauthentication");
+                log.debug(sm.getString("authenticator.check.sso", ssoId));
             }
             /* Try to reauthenticate using data cached by SSO.  If this fails,
                either the original SSO logon was of DIGEST or SSL (which
@@ -728,6 +730,31 @@ public abstract class AuthenticatorBase
             }
         }
 
+        // Has the Connector provided a pre-authenticated Principal that now
+        // needs to be authorized?
+        if (request.getCoyoteRequest().getRemoteUserNeedsAuthorization()) {
+            String username = request.getCoyoteRequest().getRemoteUser().toString();
+            if (username != null) {
+                if (log.isDebugEnabled()) {
+                    log.debug(sm.getString("authenticator.check.authorize", username));
+                }
+                Principal authorized = context.getRealm().authenticate(username);
+                if (authorized == null) {
+                    // Realm doesn't recognise user. Create a user with no roles
+                    // from the authenticated user name
+                    if (log.isDebugEnabled()) {
+                        log.debug(sm.getString("authenticator.check.authorizeFail", username));
+                    }
+                    authorized = new GenericPrincipal(username, null,  null);
+                }
+                String authType = request.getAuthType();
+                if (authType == null || authType.length() == 0) {
+                    authType = getAuthMethod();
+                }
+                register(request, response, authorized, authType, username, null);
+                return true;
+            }
+        }
         return false;
     }
 

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/BasicAuthenticator.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/BasicAuthenticator.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/BasicAuthenticator.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/BasicAuthenticator.java Wed Mar 18 14:19:14 2015
@@ -63,7 +63,7 @@ public class BasicAuthenticator extends
     public boolean authenticate(Request request, HttpServletResponse response)
             throws IOException {
 
-        if (checkForCachedAuthentication(request, true)) {
+        if (checkForCachedAuthentication(request, response, true)) {
             return true;
         }
 

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java Wed Mar 18 14:19:14 2015
@@ -205,7 +205,7 @@ public class DigestAuthenticator extends
         // Change to true below to allow previous FORM or BASIC authentications
         // to authenticate users for this webapp
         // TODO make this a configurable attribute (in SingleSignOn??)
-        if (checkForCachedAuthentication(request, false)) {
+        if (checkForCachedAuthentication(request, response, false)) {
             return true;
         }
 

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java Wed Mar 18 14:19:14 2015
@@ -125,7 +125,7 @@ public class FormAuthenticator
     public boolean authenticate(Request request, HttpServletResponse response)
             throws IOException {
 
-        if (checkForCachedAuthentication(request, true)) {
+        if (checkForCachedAuthentication(request, response, true)) {
             return true;
         }
 

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/LocalStrings.properties?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/LocalStrings.properties (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/LocalStrings.properties Wed Mar 18 14:19:14 2015
@@ -15,6 +15,10 @@
 
 authenticator.certificates=No client certificate chain in this request
 authenticator.changeSessionId=Session ID changed on authentication from [{0}] to [{1}]
+authenticator.check.authorize=Authorizing connector provided user [{0}] via Tomcat Realm
+authenticator.check.authorizeFail=Realm did not recognise user [{0}]. Creating a Principal with that name and no roles.
+authenticator.check.found=Already authenticated [{0}]
+authenticator.check.sso=Not authenticated but SSO session ID [{0}] found. Attempting re-authentication.
 authenticator.formlogin=Invalid direct reference to form login page
 authenticator.loginFail=Login failed
 authenticator.manager=Exception initializing trust managers
@@ -23,6 +27,7 @@ authenticator.notContext=Configuration e
 authenticator.requestBodyTooBig=The request body was too large to be cached during the authentication process
 authenticator.sessionExpired=The time allowed for the login process has been exceeded. If you wish to continue you must either click back twice and re-click the link you requested or close and re-open your browser
 authenticator.unauthorized=Cannot authenticate with the provided credentials
+
 digestAuthenticator.cacheRemove=A valid entry has been removed from client nonce cache to make room for new entries. A replay attack is now possible. To prevent the possibility of replay attacks, reduce nonceValidity or increase cnonceCacheSize. Further warnings of this type will be suppressed for 5 minutes.
 
 formAuthenticator.forwardErrorFail=Unexpected error forwarding to error page

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/NonLoginAuthenticator.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/NonLoginAuthenticator.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/NonLoginAuthenticator.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/NonLoginAuthenticator.java Wed Mar 18 14:19:14 2015
@@ -79,7 +79,7 @@ public final class NonLoginAuthenticator
 
         // Don't try and use SSO to authenticate since there is no auth
         // configured for this web application
-        if (checkForCachedAuthentication(request, true)) {
+        if (checkForCachedAuthentication(request, response, true)) {
             return true;
         }
 

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java Wed Mar 18 14:19:14 2015
@@ -57,7 +57,7 @@ public class SSLAuthenticator extends Au
         // Change to true below to allow previous FORM or BASIC authentications
         // to authenticate users for this webapp
         // TODO make this a configurable attribute (in SingleSignOn??)
-        if (checkForCachedAuthentication(request, false)) {
+        if (checkForCachedAuthentication(request, response, false)) {
             return true;
         }
 

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java Wed Mar 18 14:19:14 2015
@@ -128,7 +128,7 @@ public class SpnegoAuthenticator extends
     public boolean authenticate(Request request, HttpServletResponse response)
             throws IOException {
 
-        if (checkForCachedAuthentication(request, true)) {
+        if (checkForCachedAuthentication(request, response, true)) {
             return true;
         }
 

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java Wed Mar 18 14:19:14 2015
@@ -29,9 +29,11 @@ import javax.servlet.SessionTrackingMode
 import javax.servlet.WriteListener;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.catalina.Authenticator;
 import org.apache.catalina.Context;
 import org.apache.catalina.Host;
 import org.apache.catalina.Wrapper;
+import org.apache.catalina.authenticator.AuthenticatorBase;
 import org.apache.catalina.comet.CometEvent;
 import org.apache.catalina.comet.CometEvent.EventType;
 import org.apache.catalina.core.AsyncContextImpl;
@@ -1016,17 +1018,44 @@ public class CoyoteAdapter implements Ad
             return false;
         }
 
-        doConnectorAuthentication(req, request);
+        doConnectorAuthenticationAuthorization(req, request);
 
         return true;
     }
 
 
-    private void doConnectorAuthentication(org.apache.coyote.Request req, Request request) {
+    private void doConnectorAuthenticationAuthorization(org.apache.coyote.Request req, Request request) {
         // Set the remote principal
-        String principal = req.getRemoteUser().toString();
-        if (principal != null) {
-            request.setUserPrincipal(new CoyotePrincipal(principal));
+        String username = req.getRemoteUser().toString();
+        if (username != null) {
+            if (log.isDebugEnabled()) {
+                log.debug(sm.getString("coyoteAdapter.authenticate", username));
+            }
+            if (req.getRemoteUserNeedsAuthorization()) {
+                Authenticator authenticator = request.getContext().getAuthenticator();
+                if (authenticator == null) {
+                    // No security constraints configured for the application so
+                    // no need to authorize the user. Use the CoyotePrincipal to
+                    // provide the authenticated user.
+                    request.setUserPrincipal(new CoyotePrincipal(username));
+                } else if (!(authenticator instanceof AuthenticatorBase)) {
+                    if (log.isDebugEnabled()) {
+                        log.debug(sm.getString("coyoteAdapter.authorize", username));
+                    }
+                    // Custom authenticator that may not trigger authorization.
+                    // Do the authorization here to make sure it is done.
+                    request.setUserPrincipal(
+                            request.getContext().getRealm().authenticate(username));
+                }
+                // If the Authenticator is an instance of AuthenticatorBase then
+                // it will check req.getRemoteUserNeedsAuthorization() and
+                // trigger authorization as necessary. It will also cache the
+                // result preventing excessive calls to the Realm.
+            } else {
+                // The connector isn't configured for authorization. Create a
+                // user without any roles using the supplied user name.
+                request.setUserPrincipal(new CoyotePrincipal(username));
+            }
         }
 
         // Set the authorization type

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/LocalStrings.properties?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/LocalStrings.properties (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/LocalStrings.properties Wed Mar 18 14:19:14 2015
@@ -17,6 +17,8 @@ cometEvent.nullRequest=The event object
 
 coyoteAdapter.accesslogFail=Exception while attempting to add an entry to the access log
 coyoteAdapter.asyncDispatch=Exception while processing an asynchronous request
+coyoteAdapter.authenticate=Authenticated user [{0}] provided by connector
+coyoteAdapter.authorize=Authorizing user [{0}] using Tomcat's Realm
 coyoteAdapter.checkRecycled.request=Encountered a non-recycled request and recycled it forcedly.
 coyoteAdapter.checkRecycled.response=Encountered a non-recycled response and recycled it forcedly.
 coyoteAdapter.debug=The variable [{0}] has value [{1}]

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/realm/CombinedRealm.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/realm/CombinedRealm.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/realm/CombinedRealm.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/realm/CombinedRealm.java Wed Mar 18 14:19:14 2015
@@ -137,6 +137,41 @@ public class CombinedRealm extends Realm
 
 
     /**
+     * Return the Principal associated with the specified user name otherwise
+     * return <code>null</code>.
+     *
+     * @param username User name of the Principal to look up
+     */
+    @Override
+    public Principal authenticate(String username) {
+        Principal authenticatedUser = null;
+
+        for (Realm realm : realms) {
+            if (log.isDebugEnabled()) {
+                log.debug(sm.getString("combinedRealm.authStart", username,
+                        realm.getClass().getName()));
+            }
+
+            authenticatedUser = realm.authenticate(username);
+
+            if (authenticatedUser == null) {
+                if (log.isDebugEnabled()) {
+                    log.debug(sm.getString("combinedRealm.authFail", username,
+                            realm.getClass().getName()));
+                }
+            } else {
+                if (log.isDebugEnabled()) {
+                    log.debug(sm.getString("combinedRealm.authSuccess",
+                            username, realm.getClass().getName()));
+                }
+                break;
+            }
+        }
+        return authenticatedUser;
+    }
+
+
+    /**
      * Return the Principal associated with the specified username and
      * credentials, if there is one; otherwise return <code>null</code>.
      *

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java Wed Mar 18 14:19:14 2015
@@ -416,6 +416,27 @@ public abstract class RealmBase extends
 
 
     /**
+     * Return the Principal associated with the specified username, if there
+     * is one; otherwise return <code>null</code>.
+     *
+     * @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 <code>null</code>.
      *

Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/Request.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/Request.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/coyote/Request.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/Request.java Wed Mar 18 14:19:14 2015
@@ -127,9 +127,10 @@ public final class Request {
     private final ServerCookies serverCookies = new ServerCookies(INITIAL_COOKIE_SIZE);
     private final Parameters parameters = new Parameters();
 
-    private final MessageBytes remoteUser=MessageBytes.newInstance();
-    private final MessageBytes authType=MessageBytes.newInstance();
-    private final HashMap<String,Object> attributes=new HashMap<>();
+    private final MessageBytes remoteUser = MessageBytes.newInstance();
+    private boolean remoteUserNeedsAuthorization = false;
+    private final MessageBytes authType = MessageBytes.newInstance();
+    private final HashMap<String,Object> attributes = new HashMap<>();
 
     private Response response;
     private ActionHook hook;
@@ -415,6 +416,14 @@ public final class Request {
         return remoteUser;
     }
 
+    public boolean getRemoteUserNeedsAuthorization() {
+        return remoteUserNeedsAuthorization;
+    }
+
+    public void setRemoteUserNeedsAuthorization(boolean remoteUserNeedsAuthorization) {
+        this.remoteUserNeedsAuthorization = remoteUserNeedsAuthorization;
+    }
+
     public MessageBytes getAuthType() {
         return authType;
     }
@@ -542,6 +551,7 @@ public final class Request {
 
         instanceId.recycle();
         remoteUser.recycle();
+        remoteUserNeedsAuthorization = false;
         authType.recycle();
         attributes.clear();
 

Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java Wed Mar 18 14:19:14 2015
@@ -318,6 +318,16 @@ public abstract class AbstractAjpProcess
 
 
     /**
+     * Use Tomcat authorization ?
+     */
+    private boolean tomcatAuthorization = false;
+    public boolean getTomcatAuthorization() { return tomcatAuthorization; }
+    public void setTomcatAuthorization(boolean tomcatAuthorization) {
+        this.tomcatAuthorization = tomcatAuthorization;
+    }
+
+
+    /**
      * Required secret.
      */
     protected String requiredSecret = null;
@@ -1270,11 +1280,13 @@ public abstract class AbstractAjpProcess
                 break;
 
             case Constants.SC_A_REMOTE_USER :
-                if (tomcatAuthentication) {
-                    // ignore server
-                    requestHeaderMessage.getBytes(tmpMB);
-                } else {
+                if (tomcatAuthorization || !tomcatAuthentication) {
+                    // Implies tomcatAuthentication == false
                     requestHeaderMessage.getBytes(request.getRemoteUser());
+                    request.setRemoteUserNeedsAuthorization(tomcatAuthorization);
+                } else {
+                    // Ignore user information from reverse proxy
+                    requestHeaderMessage.getBytes(tmpMB);
                 }
                 break;
 

Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java Wed Mar 18 14:19:14 2015
@@ -45,7 +45,7 @@ public abstract class AbstractAjpProtoco
     // ------------------------------------------ managed in the ProtocolHandler
 
     /**
-     * Should authentication be done in the native webserver layer,
+     * Should authentication be done in the native web server layer,
      * or in the Servlet container ?
      */
     protected boolean tomcatAuthentication = true;
@@ -56,6 +56,17 @@ public abstract class AbstractAjpProtoco
 
 
     /**
+     * Should authentication be done in the native web server layer and
+     * authorization in the Servlet container?
+     */
+    private boolean tomcatAuthorization = false;
+    public boolean getTomcatAuthorization() { return tomcatAuthorization; }
+    public void setTomcatAuthorization(boolean tomcatAuthorization) {
+        this.tomcatAuthorization = tomcatAuthorization;
+    }
+
+
+    /**
      * Required secret.
      */
     protected String requiredSecret = null;
@@ -80,6 +91,7 @@ public abstract class AbstractAjpProtoco
     protected void configureProcessor(AbstractAjpProcessor<S> processor) {
         processor.setAdapter(getAdapter());
         processor.setTomcatAuthentication(getTomcatAuthentication());
+        processor.setTomcatAuthorization(getTomcatAuthorization());
         processor.setRequiredSecret(requiredSecret);
         processor.setKeepAliveTimeout(getKeepAliveTimeout());
         processor.setClientCertProvider(getClientCertProvider());

Modified: tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Wed Mar 18 14:19:14 2015
@@ -189,6 +189,14 @@
         Refactor Connector authentication (only used by AJP) into a separate
         method. (markt) 
       </scode>
+      <add>
+        <bug>57708</bug>: Implement a new feature for AJP connectors - Tomcat
+        Authorization. If the new tomcatAuthorization attribute is set to
+        <code>true</code> (it is disabled by default) Tomcat will take an
+        authenticated user name from the AJP protocol and use the appropriate
+        Realm for the request to authorize (i.e. add roles) to that user.
+        (markt)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Jasper">

Modified: tomcat/tc8.0.x/trunk/webapps/docs/config/ajp.xml
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/webapps/docs/config/ajp.xml?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/webapps/docs/config/ajp.xml (original)
+++ tomcat/tc8.0.x/trunk/webapps/docs/config/ajp.xml Wed Mar 18 14:19:14 2015
@@ -435,8 +435,22 @@
     <attribute name="tomcatAuthentication" required="false">
       <p>If set to <code>true</code>, 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 <code>true</code>.</p>
+      webserver and used for authorization in Tomcat. Note that this principal
+      will have no roles associated with it.
+      The default value is <code>true</code>. If
+      <code>tomcatAuthorization</code> is set to <code>true</code> this
+      attribute has no effect.</p>
+    </attribute>
+
+    <attribute name="tomcatAuthorization" required="false">
+      <p>If set to <code>true</code>, the authenticated principal will be
+      propagated from the native webserver and considered already authenticated
+      in Tomcat. If the web application has one or more security constriants,
+      authorization will then be performed by Tomcat and roles asisgned to the
+      authenticated principal. If the appropriate Tomcat Realm for the request
+      does not recognise the provided user name, a Principal will be still be
+      created but it will have no roles. The default value is
+      <code>false</code>.</p>
     </attribute>
 
   </attributes>

Modified: tomcat/tc8.0.x/trunk/webapps/docs/security-howto.xml
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/webapps/docs/security-howto.xml?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/webapps/docs/security-howto.xml (original)
+++ tomcat/tc8.0.x/trunk/webapps/docs/security-howto.xml Wed Mar 18 14:19:14 2015
@@ -287,10 +287,12 @@
          rel="nofollow">Qualys SSL/TLS test</a> is a useful tool for
       configuring these settings.</p>
 
-      <p>The <strong>tomcatAuthentication</strong> attribute is 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.</p>
+      <p>The <strong>tomcatAuthentication</strong> and
+      <strong>tomcatAuthorization</strong> attributes are used with the
+      AJP connectors to determine if Tomcat should handle all authenication and
+      authorisation or if authentication should be delegated to the reverse
+      proxy (the authenticated user name is passed to Tomcat as part of the AJP
+      protocol) with the option for Tomcat to still perform authorization.</p>
 
       <p>The <strong>allowUnsafeLegacyRenegotiation</strong> attribute provides
       a workaround for

Modified: tomcat/tc8.0.x/trunk/webapps/docs/windows-auth-howto.xml
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/webapps/docs/windows-auth-howto.xml?rev=1667558&r1=1667557&r2=1667558&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/webapps/docs/windows-auth-howto.xml (original)
+++ tomcat/tc8.0.x/trunk/webapps/docs/windows-auth-howto.xml Wed Mar 18 14:19:14 2015
@@ -301,7 +301,9 @@ com.sun.security.jgss.krb5.accept {
   <li>Configure IIS to use Windows authentication</li>
   <li>Configure Tomcat to use the authentication user information from IIS by
   setting the tomcatAuthentication attribute on the <a href="config/ajp.html">
-  AJP connector</a> to <code>false</code>.</li>
+  AJP connector</a> to <code>false</code>. Alternatively, set the
+  tomcatAuthorization attribute to <code>true</code> to allow IIS to
+  authenticate, while Tomcat performs the authorization.</li>
   </ol>
   </subsection>
 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org