@Test
  public void testRequestAttributesForAccessLog() throws Exception {
    // PREPARE
    FilterDef filterDef = new FilterDef();
    filterDef.addInitParameter("protocolHeader", "x-forwarded-proto");
    filterDef.addInitParameter("remoteIpHeader", "x-my-forwarded-for");
    filterDef.addInitParameter("httpServerPort", "8080");

    MockHttpServletRequest request = new MockHttpServletRequest();
    request.setRemoteAddr("192.168.0.10");
    request.setHeader("x-my-forwarded-for", "140.211.11.130");
    request.setHeader("x-forwarded-proto", "http");

    // TEST
    HttpServletRequest actualRequest = testRemoteIpFilter(filterDef, request);

    // VERIFY
    Assert.assertEquals(
        "org.apache.catalina.AccessLog.ServerPort",
        Integer.valueOf(8080),
        actualRequest.getAttribute(AccessLog.SERVER_PORT_ATTRIBUTE));

    Assert.assertEquals(
        "org.apache.catalina.AccessLog.RemoteAddr",
        "140.211.11.130",
        actualRequest.getAttribute(AccessLog.REMOTE_ADDR_ATTRIBUTE));

    Assert.assertEquals(
        "org.apache.catalina.AccessLog.RemoteHost",
        "140.211.11.130",
        actualRequest.getAttribute(AccessLog.REMOTE_HOST_ATTRIBUTE));
  }
  @Test
  public void testInvokeNotAllowedRemoteAddr() throws Exception {
    // PREPARE
    FilterDef filterDef = new FilterDef();
    filterDef.addInitParameter("internalProxies", "192\\.168\\.0\\.10|192\\.168\\.0\\.11");
    filterDef.addInitParameter("trustedProxies", "proxy1|proxy2|proxy3");
    filterDef.addInitParameter("remoteIpHeader", "x-forwarded-for");
    filterDef.addInitParameter("proxiesHeader", "x-forwarded-by");

    MockHttpServletRequest request = new MockHttpServletRequest();

    request.setRemoteAddr("not-allowed-internal-proxy");
    request.setRemoteHost("not-allowed-internal-proxy-host");
    request.setHeader("x-forwarded-for", "140.211.11.130, proxy1, proxy2");

    // TEST
    HttpServletRequest actualRequest = testRemoteIpFilter(filterDef, request);

    // VERIFY
    String actualXForwardedFor = actualRequest.getHeader("x-forwarded-for");
    assertEquals(
        "x-forwarded-for must be unchanged", "140.211.11.130, proxy1, proxy2", actualXForwardedFor);

    String actualXForwardedBy = actualRequest.getHeader("x-forwarded-by");
    assertNull("x-forwarded-by must be null", actualXForwardedBy);

    String actualRemoteAddr = actualRequest.getRemoteAddr();
    assertEquals("remoteAddr", "not-allowed-internal-proxy", actualRemoteAddr);

    String actualRemoteHost = actualRequest.getRemoteHost();
    assertEquals("remoteHost", "not-allowed-internal-proxy-host", actualRemoteHost);
  }
 private static FilterInfo getFilterInfo(FilterDef fd) {
   FilterInfo fi = new FilterInfo();
   fi.setFilterName(fd.getFilterName());
   fi.setFilterClass(fd.getFilterClass());
   fi.setFilterDesc(fd.getDescription());
   return fi;
 }
  @Test
  public void testInvokeAllProxiesAreInternal() throws Exception {

    // PREPARE
    FilterDef filterDef = new FilterDef();
    filterDef.addInitParameter("internalProxies", "192\\.168\\.0\\.10|192\\.168\\.0\\.11");
    filterDef.addInitParameter("trustedProxies", "proxy1|proxy2|proxy3");
    filterDef.addInitParameter("remoteIpHeader", "x-forwarded-for");
    filterDef.addInitParameter("proxiesHeader", "x-forwarded-by");

    MockHttpServletRequest request = new MockHttpServletRequest();
    request.setRemoteAddr("192.168.0.10");
    request.setRemoteHost("remote-host-original-value");
    request.addHeader("x-forwarded-for", "140.211.11.130, 192.168.0.10, 192.168.0.11");

    // TEST
    HttpServletRequest actualRequest = testRemoteIpFilter(filterDef, request);

    // VERIFY
    String actualXForwardedFor = actualRequest.getHeader("x-forwarded-for");
    assertNull("all proxies are internal, x-forwarded-for must be null", actualXForwardedFor);

    String actualXForwardedBy = actualRequest.getHeader("x-forwarded-by");
    assertNull("all proxies are internal, x-forwarded-by must be null", actualXForwardedBy);

    String actualRemoteAddr = actualRequest.getRemoteAddr();
    assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr);

    String actualRemoteHost = actualRequest.getRemoteHost();
    assertEquals("remoteHost", "140.211.11.130", actualRemoteHost);
  }
  @Test
  public void testIncomingRequestIsSecuredButProtocolHeaderSaysItIsNotWithDefaultValues()
      throws Exception {
    // PREPARE
    FilterDef filterDef = new FilterDef();
    filterDef.addInitParameter("protocolHeader", "x-forwarded-proto");

    MockHttpServletRequest request = new MockHttpServletRequest();
    request.setRemoteAddr("192.168.0.10");
    request.setSecure(true);
    request.setScheme("https");
    request.setHeader("x-forwarded-for", "140.211.11.130");
    request.setHeader("x-forwarded-proto", "http");

    // TEST
    HttpServletRequest actualRequest = testRemoteIpFilter(filterDef, request);

    // VERIFY
    boolean actualSecure = actualRequest.isSecure();
    assertFalse(
        "request must be unsecured as header x-forwarded-proto said it is http", actualSecure);

    String actualScheme = actualRequest.getScheme();
    assertEquals(
        "scheme must be http as header x-forwarded-proto said it is http", "http", actualScheme);

    String actualRemoteAddr = actualRequest.getRemoteAddr();
    assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr);

    String actualRemoteHost = actualRequest.getRemoteHost();
    assertEquals("remoteHost", "140.211.11.130", actualRemoteHost);
  }
  /** Return a String representation of this object. */
  @Override
  public String toString() {

    StringBuilder sb = new StringBuilder("ApplicationFilterConfig[");
    sb.append("name=");
    sb.append(filterDef.getFilterName());
    sb.append(", filterClass=");
    sb.append(filterDef.getFilterClass());
    sb.append("]");
    return (sb.toString());
  }
  /*
   * Test {@link RemoteIpFilter} in Tomcat standalone server
   */
  @Test
  public void testWithTomcatServer() throws Exception {

    // mostly default configuration : enable "x-forwarded-proto"
    Map<String, String> remoteIpFilterParameter = new HashMap<>();
    remoteIpFilterParameter.put("protocolHeader", "x-forwarded-proto");

    // SETUP
    Tomcat tomcat = getTomcatInstance();
    Context root = tomcat.addContext("", TEMP_DIR);

    FilterDef filterDef = new FilterDef();
    filterDef.getParameterMap().putAll(remoteIpFilterParameter);
    filterDef.setFilterClass(RemoteIpFilter.class.getName());
    filterDef.setFilterName(RemoteIpFilter.class.getName());

    root.addFilterDef(filterDef);

    FilterMap filterMap = new FilterMap();
    filterMap.setFilterName(RemoteIpFilter.class.getName());
    filterMap.addURLPattern("*");
    root.addFilterMap(filterMap);

    MockHttpServlet mockServlet = new MockHttpServlet();

    Tomcat.addServlet(root, mockServlet.getClass().getName(), mockServlet);
    root.addServletMapping("/test", mockServlet.getClass().getName());

    getTomcatInstance().start();

    // TEST
    HttpURLConnection httpURLConnection =
        (HttpURLConnection)
            new URL("http://localhost:" + tomcat.getConnector().getLocalPort() + "/test")
                .openConnection();
    String expectedRemoteAddr = "my-remote-addr";
    httpURLConnection.addRequestProperty("x-forwarded-for", expectedRemoteAddr);
    httpURLConnection.addRequestProperty("x-forwarded-proto", "https");

    // VALIDATE

    Assert.assertEquals(HttpURLConnection.HTTP_OK, httpURLConnection.getResponseCode());
    HttpServletRequest request = mockServlet.getRequest();
    Assert.assertNotNull(request);

    // VALIDATE X-FOWARDED-FOR
    Assert.assertEquals(expectedRemoteAddr, request.getRemoteAddr());
    Assert.assertEquals(expectedRemoteAddr, request.getRemoteHost());

    // VALIDATE X-FORWARDED-PROTO
    Assert.assertTrue(request.isSecure());
    Assert.assertEquals("https", request.getScheme());
    Assert.assertEquals(443, request.getServerPort());
  }
  public List getApplicationFilterMaps(Context context) {
    FilterMap[] fms = context.findFilterMaps();
    List filterMaps = new ArrayList(fms.length);
    for (int i = 0; i < fms.length; i++) {
      if (fms[i] != null) {
        String dm;
        switch (fms[i].getDispatcherMapping()) {
          case FilterMap.ERROR:
            dm = "ERROR";
            break;
          case FilterMap.FORWARD:
            dm = "FORWARD";
            break;
            // case FilterMap.FORWARD_ERROR: dm = "FORWARD,ERROR"; break;
          case FilterMap.INCLUDE:
            dm = "INCLUDE";
            break;
            // case FilterMap.INCLUDE_ERROR: dm = "INCLUDE,ERROR"; break;
            // case FilterMap.INCLUDE_ERROR_FORWARD: dm = "INCLUDE,ERROR,FORWARD"; break;
            // case FilterMap.INCLUDE_FORWARD: dm = "INCLUDE,FORWARD"; break;
          case FilterMap.REQUEST:
            dm = "REQUEST";
            break;
            // case FilterMap.REQUEST_ERROR: dm = "REQUEST,ERROR"; break;
            // case FilterMap.REQUEST_ERROR_FORWARD: dm = "REQUEST,ERROR,FORWARD"; break;
            // case FilterMap.REQUEST_ERROR_FORWARD_INCLUDE: dm = "REQUEST,ERROR,FORWARD,INCLUDE";
            // break;
            // case FilterMap.REQUEST_ERROR_INCLUDE: dm = "REQUEST,ERROR,INCLUDE"; break;
            // case FilterMap.REQUEST_FORWARD: dm = "REQUEST,FORWARD"; break;
            // case FilterMap.REQUEST_INCLUDE: dm = "REQUEST,INCLUDE"; break;
            // case FilterMap.REQUEST_FORWARD_INCLUDE: dm = "REQUEST,FORWARD,INCLUDE"; break;
          default:
            dm = "";
        }

        String filterClass = "";
        org.apache.tomcat.util.descriptor.web.FilterDef fd =
            context.findFilterDef(fms[i].getFilterName());
        if (fd != null) {
          filterClass = fd.getFilterClass();
        }

        List filterMappings = getFilterMappings(fms[i], dm, filterClass);
        filterMaps.addAll(filterMappings);
      }
    }
    return filterMaps;
  }
  /**
   * Construct a new ApplicationFilterConfig for the specified filter definition.
   *
   * @param context The context with which we are associated
   * @param filterDef Filter definition for which a FilterConfig is to be constructed
   * @exception ClassCastException if the specified class does not implement the <code>
   *     javax.servlet.Filter</code> interface
   * @exception ClassNotFoundException if the filter class cannot be found
   * @exception IllegalAccessException if the filter class cannot be publicly instantiated
   * @exception InstantiationException if an exception occurs while instantiating the filter object
   * @exception ServletException if thrown by the filter's init() method
   * @throws NamingException
   * @throws InvocationTargetException
   */
  ApplicationFilterConfig(Context context, FilterDef filterDef)
      throws ClassCastException, ClassNotFoundException, IllegalAccessException,
          InstantiationException, ServletException, InvocationTargetException, NamingException {

    super();

    this.context = context;
    this.filterDef = filterDef;
    // Allocate a new filter instance if necessary
    if (filterDef.getFilter() == null) {
      getFilter();
    } else {
      this.filter = filterDef.getFilter();
      getInstanceManager().newInstance(filter);
      initFilter();
    }
  }
  /**
   * Return an <code>Enumeration</code> of the names of the initialization parameters for this
   * Filter.
   */
  @Override
  public Enumeration<String> getInitParameterNames() {
    Map<String, String> map = filterDef.getParameterMap();

    if (map == null) {
      return Collections.enumeration(emptyString);
    }

    return Collections.enumeration(map.keySet());
  }
  /**
   * Return a <code>String</code> containing the value of the named initialization parameter, or
   * <code>null</code> if the parameter does not exist.
   *
   * @param name Name of the requested initialization parameter
   */
  @Override
  public String getInitParameter(String name) {

    Map<String, String> map = filterDef.getParameterMap();
    if (map == null) {
      return (null);
    }

    return map.get(name);
  }
  /** Release the Filter instance associated with this FilterConfig, if there is one. */
  void release() {

    unregisterJMX();

    if (this.filter != null) {
      try {
        if (Globals.IS_SECURITY_ENABLED) {
          try {
            SecurityUtil.doAsPrivilege("destroy", filter);
          } finally {
            SecurityUtil.remove(filter);
          }
        } else {
          filter.destroy();
        }
      } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        context
            .getLogger()
            .error(
                sm.getString(
                    "applicationFilterConfig.release",
                    filterDef.getFilterName(),
                    filterDef.getFilterClass()),
                t);
      }
      if (!context.getIgnoreAnnotations()) {
        try {
          ((StandardContext) context).getInstanceManager().destroyInstance(this.filter);
        } catch (Exception e) {
          Throwable t = ExceptionUtils.unwrapInvocationTargetException(e);
          ExceptionUtils.handleThrowable(t);
          context.getLogger().error("ApplicationFilterConfig.preDestroy", t);
        }
      }
    }
    this.filter = null;
  }
  @Test
  public void testInvokeUntrustedProxyInTheChain() throws Exception {
    // PREPARE
    FilterDef filterDef = new FilterDef();
    filterDef.addInitParameter("internalProxies", "192\\.168\\.0\\.10|192\\.168\\.0\\.11");
    filterDef.addInitParameter("trustedProxies", "proxy1|proxy2|proxy3");
    filterDef.addInitParameter("remoteIpHeader", "x-forwarded-for");
    filterDef.addInitParameter("proxiesHeader", "x-forwarded-by");

    MockHttpServletRequest request = new MockHttpServletRequest();

    request.setRemoteAddr("192.168.0.10");
    request.setRemoteHost("remote-host-original-value");
    request.setHeader("x-forwarded-for", "140.211.11.130, proxy1, untrusted-proxy, proxy2");

    // TEST
    HttpServletRequest actualRequest = testRemoteIpFilter(filterDef, request);

    // VERIFY
    String actualXForwardedFor = actualRequest.getHeader("x-forwarded-for");
    assertEquals(
        "ip/host before untrusted-proxy must appear in x-forwarded-for",
        "140.211.11.130, proxy1",
        actualXForwardedFor);

    String actualXForwardedBy = actualRequest.getHeader("x-forwarded-by");
    assertEquals(
        "ip/host after untrusted-proxy must appear in  x-forwarded-by",
        "proxy2",
        actualXForwardedBy);

    String actualRemoteAddr = actualRequest.getRemoteAddr();
    assertEquals("remoteAddr", "untrusted-proxy", actualRemoteAddr);

    String actualRemoteHost = actualRequest.getRemoteHost();
    assertEquals("remoteHost", "untrusted-proxy", actualRemoteHost);
  }
  /**
   * Return the application Filter we are configured for.
   *
   * @exception ClassCastException if the specified class does not implement the <code>
   *     javax.servlet.Filter</code> interface
   * @exception ClassNotFoundException if the filter class cannot be found
   * @exception IllegalAccessException if the filter class cannot be publicly instantiated
   * @exception InstantiationException if an exception occurs while instantiating the filter object
   * @exception ServletException if thrown by the filter's init() method
   * @throws NamingException
   * @throws InvocationTargetException
   */
  Filter getFilter()
      throws ClassCastException, ClassNotFoundException, IllegalAccessException,
          InstantiationException, ServletException, InvocationTargetException, NamingException {

    // Return the existing filter instance, if any
    if (this.filter != null) return (this.filter);

    // Identify the class loader we will be using
    String filterClass = filterDef.getFilterClass();
    this.filter = (Filter) getInstanceManager().newInstance(filterClass);

    initFilter();

    return (this.filter);
  }
  private HttpServletRequest testRemoteIpFilter(FilterDef filterDef, Request request)
      throws LifecycleException, IOException, ServletException {
    Tomcat tomcat = getTomcatInstance();
    Context root = tomcat.addContext("", TEMP_DIR);

    RemoteIpFilter remoteIpFilter = new RemoteIpFilter();
    filterDef.setFilterClass(RemoteIpFilter.class.getName());
    filterDef.setFilter(remoteIpFilter);
    filterDef.setFilterName(RemoteIpFilter.class.getName());
    root.addFilterDef(filterDef);

    FilterMap filterMap = new FilterMap();
    filterMap.setFilterName(RemoteIpFilter.class.getName());
    filterMap.addURLPattern("*");
    root.addFilterMap(filterMap);

    getTomcatInstance().start();

    MockFilterChain filterChain = new MockFilterChain();

    // TEST
    remoteIpFilter.doFilter(request, new Response(), filterChain);
    return filterChain.getRequest();
  }
  private void registerJMX() {
    String parentName = context.getName();
    if (!parentName.startsWith("/")) {
      parentName = "/" + parentName;
    }

    String hostName = context.getParent().getName();
    hostName = (hostName == null) ? "DEFAULT" : hostName;

    // domain == engine name
    String domain = context.getParent().getParent().getName();

    String webMod = "//" + hostName + parentName;
    String onameStr = null;
    String filterName = filterDef.getFilterName();
    if (Util.objectNameValueNeedsQuote(filterName)) {
      filterName = ObjectName.quote(filterName);
    }
    if (context instanceof StandardContext) {
      StandardContext standardContext = (StandardContext) context;
      onameStr =
          domain
              + ":j2eeType=Filter,WebModule="
              + webMod
              + ",name="
              + filterName
              + ",J2EEApplication="
              + standardContext.getJ2EEApplication()
              + ",J2EEServer="
              + standardContext.getJ2EEServer();
    } else {
      onameStr = domain + ":j2eeType=Filter,name=" + filterName + ",WebModule=" + webMod;
    }
    try {
      oname = new ObjectName(onameStr);
      Registry.getRegistry(null, null).registerComponent(this, oname, null);
    } catch (Exception ex) {
      log.info(
          sm.getString(
              "applicationFilterConfig.jmxRegisterFail", getFilterClass(), getFilterName()),
          ex);
    }
  }
 /** Return the name of the filter we are configuring. */
 @Override
 public String getFilterName() {
   return (filterDef.getFilterName());
 }
 public Map<String, String> getFilterInitParameterMap() {
   return Collections.unmodifiableMap(filterDef.getParameterMap());
 }
 /** Return the class of the filter we are configuring. */
 public String getFilterClass() {
   return filterDef.getFilterClass();
 }