Bug 53801 - Nondeterministic behaviour of security constraints
Nondeterministic behaviour of security constraints
Status: RESOLVED FIXED
Product: Tomcat 7
Classification: Unclassified
Component: Servlet & JSP API
7.0.29
PC All
: P2 normal (vote)
: ---
Assigned To: Tomcat Developers Mailing List
:
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2012-08-30 09:14 UTC by Matteo Casalino
Modified: 2012-08-30 23:04 UTC (History)
0 users



Attachments
test web application that reproduces the issue (2.42 KB, application/octet-stream)
2012-08-30 09:14 UTC, Matteo Casalino
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Matteo Casalino 2012-08-30 09:14:42 UTC
Created attachment 29303 [details]
test web application that reproduces the issue

I'm experiencing a weird behaviour with certain combinations of security constraints having
the following pattern:
(i) one security constraint applies to (at least) two overlapping URL patterns ending in /*,
where one is more specific than the other (e.g., /a/* and /a/b/*)
(ii) a second security constraint applies only to the less specific URL pattern (e.g. /a/*),
and
(iii) the two security constraints apply to different (possibly overlapping) sets of methods.

One such example is as follows:

<servlet-mapping>
  <servlet-name>test</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>
<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>test</realm-name>
</login-config>

<security-constraint>
  <web-resource-collection>
    <web-resource-name/>
      <url-pattern>/a/*</url-pattern>
      <url-pattern>/a/b/*</url-pattern>
      <http-method>POST</http-method>
  </web-resource-collection>
</security-constraint>

<security-constraint>
  <web-resource-collection>
    <web-resource-name/>
      <url-pattern>/a/*</url-pattern>
        <http-method>GET</http-method>
    </web-resource-collection>
    <auth-constraint/>
</security-constraint>

The problem occurs for HTTP requests matching to the most specific URL pattern (in the above
example, /a/b, /a/b/c, etc.), but on methods other than the ones mentioned in the first security
constraint (in the above example, GET).

For instance, each time I deploy a web application with the above-mentioned deployment descriptor
in Tomcat, or each time I redeploy it or restart the server in case it is already deployed,
I get randomly either of the two following behaviours:

1) "GET /a/b" requests are allowed, i.e. no authentication is required
2) "GET /a/b" requests are denied, i.e. the response requires authentication (HTTP 401)

Notice that the behaviour remains then constant until I restart the server or re-deploy the
application. Also, adding arbitrary roles in either of the two auth-constraints, does not
seem to change the result.

According to the Java Servlet Specification, 1) is the correct behaviour. In fact, such requests
shall be allowed to any (possibly unauthenticated) users, because the constraint with the
most specific pattern (the first one) matches to the request, but it does not mention the
method of the request (GET).

I tested several different combinations of security constraints, but this issue seems to occur
only with those of this kind.


Please find attached a WAR that produces the above behaviour.

Here are some HTTP requests I tested together with the expected and actual results:

HTTP Request      Expected HTTP Response    Observed Behaviour
GET /test/a       403                       Always correct
GET /test/b       200                       Always correct
GET /test/a/b     200                       Sometimes incorrect (401 is given)
GET /test/a/b/    200                       Sometimes incorrect (401 is given)
GET /test/a/b/c   200                       Sometimes incorrect (401 is given)
Comment 1 Mark Thomas 2012-08-30 23:04:30 UTC
Thanks for the report. The issue has been fixed in trunk and 7.0.x and will be included in 7.0.30 onwards.

The reason for the intermittent nature was that it depended on the order the security constraints were processed which in turn depended on the order the constraints were returned from a HashSet which varied.