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]

Reply via email to