securitytokenvalidator.java

### File Source: securitytokenvalidator.java

             /*
        P/P   *  Method: net.sourceforge.pebble.web.security.SecurityTokenValidator__static_init
              *
              *  Postconditions:
              *    random == &new SecureRandom(SecurityTokenValidator__static_init#1)
              *    new SecureRandom(SecurityTokenValidator__static_init#1) num objects == 1
              */
         1  /*
         2   * Copyright (c) 2003-2005, Simon Brown
         3   * All rights reserved.
         4   *
         5   * Redistribution and use in source and binary forms, with or without
         6   * modification, are permitted provided that the following conditions are met:
         7   *
         8   *   - Redistributions of source code must retain the above copyright
         9   *     notice, this list of conditions and the following disclaimer.
        10   *
        11   *   - Redistributions in binary form must reproduce the above copyright
        12   *     notice, this list of conditions and the following disclaimer in
        13   *     the documentation and/or other materials provided with the
        14   *     distribution.
        15   *
        16   *   - Neither the name of Pebble nor the names of its contributors may
        17   *     be used to endorse or promote products derived from this software
        18   *     without specific prior written permission.
        19   *
        20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
        21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
        24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        30   * POSSIBILITY OF SUCH DAMAGE.
        31   */
        32  package net.sourceforge.pebble.web.security;
        33
        34  import net.sourceforge.pebble.web.action.Action;
        35
             /*
        P/P   *  Method: void net.sourceforge.pebble.web.security.SecurityTokenValidator()
              */
        36  import javax.servlet.http.Cookie;
        37  import javax.servlet.http.HttpServletRequest;
        38  import javax.servlet.http.HttpServletResponse;
        39  import java.security.SecureRandom;
        40
        41  /**
        42   * Checks requests for a security token
        43   *
        44   * @author James Roper
        45   */
        46  public class SecurityTokenValidator {
        47
        48    /**
        49     * the security token name
        50     */
        51    public static final String PEBBLE_SECURITY_TOKEN_PARAMETER = "pebbleSecurityToken";
        52
        53    /**
        54     * the header for bypassing security token checks
        55     */
        56    private static final String PEBBLE_SECURITY_TOKEN_HEADER = "X-Pebble-Token";
        57
        58    /**
        59     * the value the header should be for not checking
        60     */
        61    private static final String PEBBLE_SECURITY_TOKEN_HEADER_NOCHECK = "nocheck";
        62
        63    /**
        64     * For generating secure tokens
        65     */
        66    private static final SecureRandom random = new SecureRandom();
        67
        68    /**
        69     * Validate the security token for this request, if necessary, setting up the security token cookie if it doesn't
        70     * exist
        71     *
        72     * @param request The request to validate
        73     * @param response The response
        74     * @param action The action to validate
        75     * @return true if the request can proceed, false if not
        76     */
        77    public boolean validateSecurityToken(HttpServletRequest request, HttpServletResponse response, Action action) {
        78      // First, ensure that there is a security token, for future requests
                 /*
        P/P       *  Method: bool validateSecurityToken(HttpServletRequest, HttpServletResponse, Action)
                  *
                  *  Preconditions:
                  *    action != null
                  *    (soft) request != null
                  *
                  *  Presumptions:
                  *    ensureSecurityTokenExists(...)@79 != null
                  *
                  *  Postconditions:
                  *    init'ed(return_value)
                  *
                  *  Test Vectors:
                  *    java.lang.String:equals(...)@83: {0}, {1}
                  */
        79      String token = ensureSecurityTokenExists(request, response);
        80      if (shouldValidate(action, request)) {
        81        // Check for the header is there... XSRF attacks can't set custom headers, so if this header is there,
        82        // it must be safe
        83        if (PEBBLE_SECURITY_TOKEN_HEADER_NOCHECK.equals(request.getHeader(PEBBLE_SECURITY_TOKEN_HEADER))) {
        84          return true;
        85        }
        86        // We must validate the token
        87        String requestToken = request.getParameter(PEBBLE_SECURITY_TOKEN_PARAMETER);
        88        // Compare token to cookie
        89        return token.equals(requestToken);
        90      } else {
        91        return true;
        92      }
        93    }
        94
        95    private boolean shouldValidate(Action action, HttpServletRequest request)
        96    {
                 /*
        P/P       *  Method: bool shouldValidate(Action, HttpServletRequest)
                  *
                  *  Preconditions:
                  *    action != null
                  *
                  *  Presumptions:
                  *    java.lang.Object:getClass(...)@97 != null
                  *
                  *  Postconditions:
                  *    init'ed(return_value)
                  *
                  *  Test Vectors:
                  *    java.lang.Class:getAnnotation(...)@97: Addr_Set{null}, Inverse{null}
                  */
        97      RequireSecurityToken annotation = action.getClass().getAnnotation(RequireSecurityToken.class);
        98      if (annotation != null) {
        99        // Check for a condition
       100        Class<? extends SecurityTokenValidatorCondition> condition = annotation.value();
       101        if (condition != null && condition != NullSecurityTokenValidatorCondition.class) {
       102          // Instantiate condition
       103          try {
       104            return condition.newInstance().shouldValidate(request);
       105          } catch (IllegalAccessException iae) {
       106            throw new RuntimeException("Could not instantiate " + condition);
       107          } catch (InstantiationException ie) {
       108            throw new RuntimeException("Could not instantiate " + condition);
       109          }
       110        }
       111        // Otherwise, with no condition we should return validate
       112        return true;
       113      } else {
       114        // We have no annotation, don't validate
       115        return false;
       116      }
       117    }
       118
       119    private String ensureSecurityTokenExists(HttpServletRequest request, HttpServletResponse response) {
       120      String token = (String) request.getAttribute(PEBBLE_SECURITY_TOKEN_PARAMETER);
       121      if (token != null) {
       122        // We've already configured it for this request
       123        return token;
       124      }
       125      String contextPath = request.getContextPath();
       126      Cookie[] cookies = request.getCookies();
       127      if (cookies != null) {
       128        for (Cookie cookie : cookies) {
       129          if (PEBBLE_SECURITY_TOKEN_PARAMETER.equals(cookie.getName())) {
       130            if (contextPath != null && contextPath.length() > 0) {
       131              if (contextPath.equals(cookie.getPath())) {
       132                token = cookie.getValue();
       133                break;
       134              }
       135            } else {
       136              token = cookie.getValue();
       137              break;
       138            }
       139          }
       140        }
       141      }
       142      // No cookie, generate a token at least 12 characters long
       143      if (token == null) {
       144        token = "";
       145        while (token.length() < 12) {
       146          token += Long.toHexString(random.nextLong());
       147        }
       148        // Set the cookie
       149        Cookie cookie = new Cookie(PEBBLE_SECURITY_TOKEN_PARAMETER, token);
       150        // Non persistent
       151        cookie.setMaxAge(-1);
       152        cookie.setPath(contextPath);
       153        response.addCookie(cookie);
       154      }
       155      // Set it as a request attribute so the security token tag can find it
       156      request.setAttribute(PEBBLE_SECURITY_TOKEN_PARAMETER, token);
       157      return token;
       158    }
       159
       160  }

SofCheck Inspector Build Version : 2.22510

securitytokenvalidator.java | 2010-Jun-25 19:40:32
securitytokenvalidator.class | 2010-Jul-19 20:23:38