billbarker 2003/12/10 21:50:39 Modified: catalina/src/share/org/apache/catalina Realm.java catalina/src/share/org/apache/catalina/authenticator AuthenticatorBase.java catalina/src/share/org/apache/catalina/realm RealmBase.java Log: First attempt to get Tomcat compliant with the Servlet 2.4 Spec for AA. This one isn't very efficient (but not much worse than it was before :). Longer term, I'm looking to modify the j-t-c mapper to be able to return a Collection of mapped objects, and use that. In that case it could also be used for Filter mappings. This version is just to get a Spec compliant version out there that can be tested. Reported By: Philippe Leothaud <[EMAIL PROTECTED]> Revision Changes Path 1.6 +6 -6 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Realm.java Index: Realm.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Realm.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- Realm.java 2 Sep 2003 21:22:05 -0000 1.5 +++ Realm.java 11 Dec 2003 05:50:39 -0000 1.6 @@ -192,7 +192,7 @@ */ public boolean hasResourcePermission(HttpRequest request, HttpResponse response, - SecurityConstraint constraint, + SecurityConstraint [] constraint, Context context) throws IOException; @@ -221,7 +221,7 @@ */ public boolean hasUserDataPermission(HttpRequest request, HttpResponse response, - SecurityConstraint constraint) + SecurityConstraint []constraint) throws IOException; /** 1.15 +35 -42 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java Index: AuthenticatorBase.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- AuthenticatorBase.java 24 Nov 2003 16:46:56 -0000 1.14 +++ AuthenticatorBase.java 11 Dec 2003 05:50:39 -0000 1.15 @@ -526,27 +526,22 @@ } int i; - for(i=0; i < constraints.length; i++) { - if (log.isDebugEnabled()) { - log.debug(" Subject to constraint " + constraints[i]); - } - // Enforce any user data constraint for this security constraint + // Enforce any user data constraint for this security constraint + if (log.isDebugEnabled()) { + log.debug(" Calling hasUserDataPermission()"); + } + if (!realm.hasUserDataPermission(hrequest, hresponse, + constraints)) { if (log.isDebugEnabled()) { - log.debug(" Calling hasUserDataPermission()"); - } - if (!realm.hasUserDataPermission(hrequest, hresponse, - constraints[i])) { - if (log.isDebugEnabled()) { - log.debug(" Failed hasUserDataPermission() test"); - } - /* - * ASSERT: Authenticator already set the appropriate - * HTTP status code, so we do not have to do anything special - */ - return; + log.debug(" Failed hasUserDataPermission() test"); } + /* + * ASSERT: Authenticator already set the appropriate + * HTTP status code, so we do not have to do anything special + */ + return; } - + for(i=0; i < constraints.length; i++) { // Authenticate based upon the specified login configuration if (constraints[i].getAuthConstraint()) { @@ -563,30 +558,28 @@ * special */ return; + } else { + break; } } - - // Perform access control based on the specified role(s) - if (constraints[i].getAuthConstraint()) { - if (log.isDebugEnabled()) { - log.debug(" Calling accessControl()"); - } - if (!realm.hasResourcePermission(hrequest, hresponse, - constraints[i], - this.context)) { - if (log.isDebugEnabled()) { - log.debug(" Failed accessControl() test"); - } - /* - * ASSERT: AccessControl method has already set the - * appropriate HTTP status code, so we do not have to do - * anything special - */ - return; - } + } + if (log.isDebugEnabled()) { + log.debug(" Calling accessControl()"); + } + if (!realm.hasResourcePermission(hrequest, hresponse, + constraints, + this.context)) { + if (log.isDebugEnabled()) { + log.debug(" Failed accessControl() test"); } + /* + * ASSERT: AccessControl method has already set the + * appropriate HTTP status code, so we do not have to do + * anything special + */ + return; } - + // Any and all specified constraints have been satisfied if (log.isDebugEnabled()) { log.debug(" Successfully passed all security constraints"); 1.20 +199 -60 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm/RealmBase.java Index: RealmBase.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm/RealmBase.java,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- RealmBase.java 9 Dec 2003 01:54:33 -0000 1.19 +++ RealmBase.java 11 Dec 2003 05:50:39 -0000 1.20 @@ -92,6 +92,7 @@ import org.apache.catalina.core.ContainerBase; import org.apache.catalina.deploy.LoginConfig; import org.apache.catalina.deploy.SecurityConstraint; +import org.apache.catalina.deploy.SecurityCollection; import org.apache.catalina.util.HexUtils; import org.apache.catalina.util.LifecycleSupport; import org.apache.catalina.util.MD5Encoder; @@ -462,30 +463,159 @@ uri = uri.substring(contextPath.length()); String method = hreq.getMethod(); - for (int i = 0; i < constraints.length; i++) { + int i; + for (i = 0; i < constraints.length; i++) { + SecurityCollection [] collection = constraints[i].findCollections(); + if (log.isDebugEnabled()) log.debug(" Checking constraint '" + constraints[i] + "' against " + method + " " + uri + " --> " + constraints[i].included(uri, method)); - if (constraints[i].included(uri, method)) { - if(results == null) { - results = new ArrayList(); + for(int j=0; j < collection.length; j++){ + if(collection[j].findMethod(method)) { + String [] patterns = collection[j].findPatterns(); + for(int k=0; k < patterns.length; k++) { + if(uri.equals(patterns[k])) { + if(results == null) { + results = new ArrayList(); + } + results.add(constraints[i]); + } + } } - results.add(constraints[i]); } } - - // No applicable security constraint was found - if (log.isDebugEnabled()) - log.debug(" No applicable constraint located"); - if(results == null) + if(results != null) { + return resultsToArray(results); + } + int longest = -1; + String testURI = uri; + if(uri.endsWith("/")) { + testURI = uri.substring(0,uri.length()-1); + } + for (i = 0; i < constraints.length; i++) { + SecurityCollection [] collection = constraints[i].findCollections(); + + if (log.isDebugEnabled()) + log.debug(" Checking constraint '" + constraints[i] + + "' against " + method + " " + uri + " --> " + + constraints[i].included(uri, method)); + for(int j=0; j < collection.length; j++){ + if(collection[j].findMethod(method)) { + String [] patterns = collection[j].findPatterns(); + boolean matched = false; + int length = -1; + for(int k=0; k < patterns.length; k++) { + String pattern = patterns[j]; + if(pattern.startsWith("/") && pattern.endsWith("/*") && + pattern.length() >= longest) { + + if(pattern.length() == 0) { + matched = true; + length = pattern.length(); + } else if(testURI.startsWith(pattern)) { + matched = true; + length = pattern.length(); + } + } + } + if(matched) { + if(results == null) { + results = new ArrayList(); + } else if(length > longest) { + results.clear(); + longest = length; + } + results.add(constraints[i]); + break; + } + } + } + } + for (i = 0; i < constraints.length; i++) { + SecurityCollection [] collection = constraints[i].findCollections(); + + if (log.isDebugEnabled()) + log.debug(" Checking constraint '" + constraints[i] + + "' against " + method + " " + uri + " --> " + + constraints[i].included(uri, method)); + boolean matched = false; + for(int j=0; j < collection.length; j++){ + if(collection[j].findMethod(method)) { + String [] patterns = collection[j].findPatterns(); + for(int k=0; k < patterns.length && !matched; k++) { + String pattern = patterns[j]; + if(pattern.startsWith("*.")){ + int slash = testURI.lastIndexOf("/"); + int dot = testURI.lastIndexOf("."); + if(slash >= 0 && dot > slash) { + if(testURI.endsWith(pattern.substring(1))) { + matched = true; + } + } + } + } + } + if(matched) { + if(results == null) { + results = new ArrayList(); + } + results.add(constraints[i]); + break; + } + } + } + if(results != null) { + return resultsToArray(results); + } + for (i = 0; i < constraints.length; i++) { + SecurityCollection [] collection = constraints[i].findCollections(); + + if (log.isDebugEnabled()) + log.debug(" Checking constraint '" + constraints[i] + + "' against " + method + " " + uri + " --> " + + constraints[i].included(uri, method)); + for(int j=0; j < collection.length; j++){ + if(collection[j].findMethod(method)) { + String [] patterns = collection[j].findPatterns(); + boolean matched = false; + for(int k=0; k < patterns.length && !matched; k++) { + String pattern = patterns[j]; + if(pattern.equals("/")){ + matched = true; + } + } + if(matched) { + if(results == null) { + results = new ArrayList(); + } + results.add(constraints[i]); + break; + } + } + } + } + + if(results == null) { + // No applicable security constraint was found + if (log.isDebugEnabled()) + log.debug(" No applicable constraint located"); + } + return resultsToArray(results); + } + + /** + * Convert an ArrayList to a SecurityContraint []. + */ + private SecurityConstraint [] resultsToArray(ArrayList results) { + if(results == null) { return null; - SecurityConstraint [] array = new SecurityConstraint [results.size()]; + } + SecurityConstraint [] array = new SecurityConstraint[results.size()]; results.toArray(array); return array; - } - + /** * Perform access control based on the specified authorization constraint. @@ -501,11 +631,11 @@ */ public boolean hasResourcePermission(HttpRequest request, HttpResponse response, - SecurityConstraint constraint, + SecurityConstraint []constraints, Context context) throws IOException { - if (constraint == null) + if (constraints == null || constraints.length == 0) return (true); // Specifically allow access to the form login and form error pages @@ -536,38 +666,45 @@ // Which user principal have we already authenticated? Principal principal = ((HttpServletRequest) request.getRequest()).getUserPrincipal(); - if (principal == null) { - if (log.isDebugEnabled()) - log.debug(" No user authenticated, cannot grant access"); - ((HttpServletResponse) response.getResponse()).sendError - (HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - sm.getString("realmBase.notAuthenticated")); - return (false); - } + for(int i=0; i < constraints.length; i++) { + SecurityConstraint constraint = constraints[i]; + String roles[] = constraint.findAuthRoles(); + if (roles == null) + roles = new String[0]; - String roles[] = constraint.findAuthRoles(); - if (roles == null) - roles = new String[0]; + if (constraint.getAllRoles()) + return (true); - if (constraint.getAllRoles()) - return (true); + if (log.isDebugEnabled()) + log.debug(" Checking roles " + principal); - if (log.isDebugEnabled()) - log.debug(" Checking roles " + principal); + if (roles.length == 0) { + if(constraint.getAuthConstraint()) { + ((HttpServletResponse) response.getResponse()).sendError + (HttpServletResponse.SC_FORBIDDEN, + sm.getString("realmBase.forbidden")); + if( log.isDebugEnabled() ) log.debug("No roles "); + return (false); // No listed roles means no access at all + } else { + log.debug("Passing all access"); + return (true); + } + } else if (principal == null) { + if (log.isDebugEnabled()) + log.debug(" No user authenticated, cannot grant access"); + ((HttpServletResponse) response.getResponse()).sendError + (HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + sm.getString("realmBase.notAuthenticated")); + return (false); + } - if ((roles.length == 0) && (constraint.getAuthConstraint())) { - ((HttpServletResponse) response.getResponse()).sendError - (HttpServletResponse.SC_FORBIDDEN, - sm.getString("realmBase.forbidden")); - if( log.isDebugEnabled() ) log.debug("No roles "); - return (false); // No listed roles means no access at all - } - for (int i = 0; i < roles.length; i++) { - if (hasRole(principal, roles[i])) - return (true); - if( log.isDebugEnabled() ) - log.debug( "No role found: " + roles[i]); + for (int j = 0; j < roles.length; j++) { + if (hasRole(principal, roles[j])) + return (true); + if( log.isDebugEnabled() ) + log.debug( "No role found: " + roles[j]); + } } // Return a "Forbidden" message denying access to this resource ((HttpServletResponse) response.getResponse()).sendError @@ -627,34 +764,36 @@ */ public boolean hasUserDataPermission(HttpRequest request, HttpResponse response, - SecurityConstraint constraint) + SecurityConstraint []constraints) throws IOException { // Is there a relevant user data constraint? - if (constraint == null) { + if (constraints == null || constraints.length == 0) { if (log.isDebugEnabled()) log.debug(" No applicable security constraint defined"); return (true); } - String userConstraint = constraint.getUserConstraint(); - if (userConstraint == null) { - if (log.isDebugEnabled()) - log.debug(" No applicable user data constraint defined"); - return (true); - } - if (userConstraint.equals(Constants.NONE_TRANSPORT)) { - if (log.isDebugEnabled()) - log.debug(" User data constraint has no restrictions"); - return (true); - } + for(int i=0; i < constraints.length; i++) { + SecurityConstraint constraint = constraints[i]; + String userConstraint = constraint.getUserConstraint(); + if (userConstraint == null) { + if (log.isDebugEnabled()) + log.debug(" No applicable user data constraint defined"); + return (true); + } + if (userConstraint.equals(Constants.NONE_TRANSPORT)) { + if (log.isDebugEnabled()) + log.debug(" User data constraint has no restrictions"); + return (true); + } + } // Validate the request against the user data constraint if (request.getRequest().isSecure()) { if (log.isDebugEnabled()) log.debug(" User data constraint already satisfied"); return (true); } - // Initialize variables we need to determine the appropriate action HttpServletRequest hrequest = (HttpServletRequest) request.getRequest();
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]