    1   /* Copyright 2004, 2005 Acegi Technology Pty Limited
    2    *
    3    * Licensed under the Apache License, Version 2.0 (the "License");
    4    * you may not use this file except in compliance with the License.
    5    * You may obtain a copy of the License at
    6    *
    7    *     http://www.apache.org/licenses/LICENSE-2.0
    8    *
    9    * Unless required by applicable law or agreed to in writing, software
    10   * distributed under the License is distributed on an "AS IS" BASIS,
    11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12   * See the License for the specific language governing permissions and
    13   * limitations under the License.
    14   */
    15
    16  package org.acegisecurity.ui.x509;
    17
    18  import junit.framework.TestCase;
    19
    20  import org.acegisecurity.Authentication;
    21  import org.acegisecurity.AuthenticationManager;
    22  import org.acegisecurity.BadCredentialsException;
    23  import org.acegisecurity.MockAuthenticationManager;
    24  import org.acegisecurity.context.SecurityContextHolder;
    25  import org.acegisecurity.providers.x509.X509AuthenticationToken;
    26  import org.acegisecurity.providers.x509.X509TestUtils;
    27  import org.acegisecurity.ui.AbstractProcessingFilter;
    28  import org.acegisecurity.util.MockFilterChain;
    29
    30  import org.springframework.mock.web.MockHttpServletRequest;
    31  import org.springframework.mock.web.MockHttpServletResponse;
    32
    33  import java.security.cert.X509Certificate;
    34
    35  import javax.servlet.FilterChain;
    36  import javax.servlet.ServletException;
    37
    38
    39  /***
    40   * Tests {@link org.acegisecurity.ui.x509.X509ProcessingFilter}.
    41   *
    42   * @author Luke Taylor
    43   * @version $Id: X509ProcessingFilterTests.java,v 1.9 2005/11/17 00:55:49 benalex Exp $
    44   */
    45  public class X509ProcessingFilterTests extends TestCase {
    46      //~ Constructors ===========================================================
    47
    48      public X509ProcessingFilterTests() {
    49          super();
    50      }
    51
    52      public X509ProcessingFilterTests(String arg0) {
    53          super(arg0);
    54      }
    55
    56      //~ Methods ================================================================
    57
    58      public final void setUp() throws Exception {
    59          super.setUp();
    60      }
    61
    62      public void tearDown() {
    63          SecurityContextHolder.getContext().setAuthentication(null);
    64      }
    65
    66      public void testAuthenticationIsNullWithNoCertificate()
    67          throws Exception {
    68          MockHttpServletRequest request = new MockHttpServletRequest();
    69          MockHttpServletResponse response = new MockHttpServletResponse();
    70          FilterChain chain = new MockFilterChain(true);
    71
    72          AuthenticationManager authMgr = new MockX509AuthenticationManager();
    73          X509ProcessingFilter filter = new X509ProcessingFilter();
    74
    75          filter.setAuthenticationManager(authMgr);
    76
    77          SecurityContextHolder.getContext().setAuthentication(null);
    78          filter.doFilter(request, response, chain);
    79
    80          Object lastException = request.getSession().getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY);
    81
    82          assertNull("Authentication should be null",
    83              SecurityContextHolder.getContext().getAuthentication());
    84          assertTrue("BadCredentialsException should have been thrown",
    85              lastException instanceof BadCredentialsException);
    86      }
    87
    88      public void testDoFilterWithNonHttpServletRequestDetected()
    89          throws Exception {
    90          X509ProcessingFilter filter = new X509ProcessingFilter();
    91
    92          try {
    93              filter.doFilter(null, new MockHttpServletResponse(),
    94                  new MockFilterChain(false));
    95              fail("Should have thrown ServletException");
    96          } catch (ServletException expected) {
    97              assertEquals("Can only process HttpServletRequest",
    98                  expected.getMessage());
    99          }
    100     }
    101
    102     public void testDoFilterWithNonHttpServletResponseDetected()
    103         throws Exception {
    104         X509ProcessingFilter filter = new X509ProcessingFilter();
    105
    106         try {
    107             filter.doFilter(new MockHttpServletRequest(null, null), null,
    108                 new MockFilterChain(false));
    109             fail("Should have thrown ServletException");
    110         } catch (ServletException expected) {
    111             assertEquals("Can only process HttpServletResponse",
    112                 expected.getMessage());
    113         }
    114     }
    115
    116     public void testFailedAuthentication() throws Exception {
    117         MockHttpServletRequest request = new MockHttpServletRequest();
    118         MockHttpServletResponse response = new MockHttpServletResponse();
    119         FilterChain chain = new MockFilterChain(true);
    120
    121         request.setAttribute("javax.servlet.request.X509Certificate",
    122             new X509Certificate[] {X509TestUtils.buildTestCertificate()});
    123
    124         AuthenticationManager authMgr = new MockAuthenticationManager(false);
    125
    126         SecurityContextHolder.getContext().setAuthentication(null);
    127
    128         X509ProcessingFilter filter = new X509ProcessingFilter();
    129
    130         filter.setAuthenticationManager(authMgr);
    131         filter.afterPropertiesSet();
    132         filter.init(null);
    133         filter.doFilter(request, response, chain);
    134         filter.destroy();
    135
    136         Authentication result = SecurityContextHolder.getContext()
    137                                                      .getAuthentication();
    138
    139         assertNull(result);
    140     }
    141
    142     public void testNeedsAuthenticationManager() throws Exception {
    143         X509ProcessingFilter filter = new X509ProcessingFilter();
    144
    145         try {
    146             filter.afterPropertiesSet();
    147             fail("Expected IllegalArgumentException");
    148         } catch (IllegalArgumentException failed) {
    149             // ignored
    150         }
    151     }
    152
    153     public void testNormalOperation() throws Exception {
    154         MockHttpServletRequest request = new MockHttpServletRequest();
    155         MockHttpServletResponse response = new MockHttpServletResponse();
    156         FilterChain chain = new MockFilterChain(true);
    157
    158         request.setAttribute("javax.servlet.request.X509Certificate",
    159             new X509Certificate[] {X509TestUtils.buildTestCertificate()});
    160
    161         AuthenticationManager authMgr = new MockX509AuthenticationManager();
    162
    163         SecurityContextHolder.getContext().setAuthentication(null);
    164
    165         X509ProcessingFilter filter = new X509ProcessingFilter();
    166
    167         filter.setAuthenticationManager(authMgr);
    168         filter.afterPropertiesSet();
    169         filter.init(null);
    170         filter.doFilter(request, response, chain);
    171         filter.destroy();
    172
    173         Authentication result = SecurityContextHolder.getContext()
    174                                                      .getAuthentication();
    175
    176         assertNotNull(result);
    177     }
    178
    179     //~ Inner Classes ==========================================================
    180
    181     private static class MockX509AuthenticationManager
    182         implements AuthenticationManager {
    183         public Authentication authenticate(Authentication a) {
    184             if (!(a instanceof X509AuthenticationToken)) {
    185                 TestCase.fail("Needed an X509Authentication token but found "
    186                     + a);
    187             }
    188
    189             if (a.getCredentials() == null) {
    190                 throw new BadCredentialsException(
    191                     "Mock authentication manager rejecting null certificate");
    192             }
    193
    194             return a;
    195         }
    196     }
    197 }