PageRenderTime 19ms CodeModel.GetById 7ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/hudson-core/src/main/java/hudson/security/csrf/CrumbIssuer.java

http://github.com/hudson/hudson
Java | 155 lines | 64 code | 18 blank | 73 comment | 10 complexity | 3d3fb1a39b3bd4e3a51cb363b75c3238 MD5 | raw file
  1/**
  2 * Copyright (c) 2008-2009 Yahoo! Inc.
  3 * All rights reserved.
  4 * The copyrights to the contents of this file are licensed under the MIT License (http://www.opensource.org/licenses/mit-license.php)
  5 */
  6package hudson.security.csrf;
  7
  8import javax.servlet.ServletRequest;
  9
 10import org.kohsuke.stapler.Stapler;
 11import org.kohsuke.stapler.export.Exported;
 12import org.kohsuke.stapler.export.ExportedBean;
 13
 14import hudson.DescriptorExtensionList;
 15import hudson.ExtensionPoint;
 16import hudson.model.Api;
 17import hudson.model.Describable;
 18import hudson.model.Descriptor;
 19import hudson.model.Hudson;
 20import hudson.util.MultipartFormDataParser;
 21
 22/**
 23 * A CrumbIssuer represents an algorithm to generate a nonce value, known as a
 24 * crumb, to counter cross site request forgery exploits. Crumbs are typically
 25 * hashes incorporating information that uniquely identifies an agent that sends
 26 * a request, along with a guarded secret so that the crumb value cannot be
 27 * forged by a third party.
 28 *
 29 * @author dty
 30 * @see http://en.wikipedia.org/wiki/XSRF
 31 */
 32@ExportedBean
 33public abstract class CrumbIssuer implements Describable<CrumbIssuer>, ExtensionPoint {
 34
 35    private static final String CRUMB_ATTRIBUTE = CrumbIssuer.class.getName() + "_crumb";
 36
 37    /**
 38     * Get the name of the request parameter the crumb will be stored in. Exposed
 39     * here for the remote API.
 40     */
 41    @Exported
 42    public String getCrumbRequestField() {
 43        return getDescriptor().getCrumbRequestField();
 44    }
 45
 46    /**
 47     * Get a crumb value based on user specific information in the current request.
 48     * Intended for use only by the remote API.
 49     * @return
 50     */
 51    @Exported
 52    public String getCrumb() {
 53        return getCrumb(Stapler.getCurrentRequest());
 54    }
 55
 56    /**
 57     * Get a crumb value based on user specific information in the request.
 58     * @param request
 59     * @return
 60     */
 61    public String getCrumb(ServletRequest request) {
 62        String crumb = null;
 63        if (request != null) {
 64            crumb = (String) request.getAttribute(CRUMB_ATTRIBUTE);
 65        }
 66        if (crumb == null) {
 67            crumb = issueCrumb(request, getDescriptor().getCrumbSalt());
 68            if (request != null) {
 69                if ((crumb != null) && crumb.length()>0) {
 70                    request.setAttribute(CRUMB_ATTRIBUTE, crumb);
 71                } else {
 72                    request.removeAttribute(CRUMB_ATTRIBUTE);
 73                }
 74            }
 75        }
 76
 77        return crumb;
 78    }
 79
 80    /**
 81     * Create a crumb value based on user specific information in the request.
 82     * The crumb should be generated by building a cryptographic hash of:
 83     * <ul>
 84     *  <li>relevant information in the request that can uniquely identify the client
 85     *  <li>the salt value
 86     *  <li>an implementation specific guarded secret.
 87     * </ul>
 88     *
 89     * @param request
 90     * @param salt
 91     * @return
 92     */
 93    protected abstract String issueCrumb(ServletRequest request, String salt);
 94
 95    /**
 96     * Get a crumb from a request parameter and validate it against other data
 97     * in the current request. The salt and request parameter that is used is
 98     * defined by the current configuration.
 99     *
100     * @param request
101     * @return
102     */
103    public boolean validateCrumb(ServletRequest request) {
104        CrumbIssuerDescriptor<CrumbIssuer> desc = getDescriptor();
105        String crumbField = desc.getCrumbRequestField();
106        String crumbSalt = desc.getCrumbSalt();
107
108        return validateCrumb(request, crumbSalt, request.getParameter(crumbField));
109    }
110
111    /**
112     * Get a crumb from multipart form data and validate it against other data
113     * in the current request. The salt and request parameter that is used is
114     * defined by the current configuration.
115     *
116     * @param request
117     * @param parser
118     * @return
119     */
120    public boolean validateCrumb(ServletRequest request, MultipartFormDataParser parser) {
121        CrumbIssuerDescriptor<CrumbIssuer> desc = getDescriptor();
122        String crumbField = desc.getCrumbRequestField();
123        String crumbSalt = desc.getCrumbSalt();
124
125        return validateCrumb(request, crumbSalt, parser.get(crumbField));
126    }
127
128    /**
129     * Validate a previously created crumb against information in the current request.
130     *
131     * @param request
132     * @param salt
133     * @param crumb The previously generated crumb to validate against information in the current request
134     * @return
135     */
136    public abstract boolean validateCrumb(ServletRequest request, String salt, String crumb);
137
138    /**
139     * Access global configuration for the crumb issuer.
140     */
141    public CrumbIssuerDescriptor<CrumbIssuer> getDescriptor() {
142        return (CrumbIssuerDescriptor<CrumbIssuer>) Hudson.getInstance().getDescriptorOrDie(getClass());
143    }
144
145    /**
146     * Returns all the registered {@link CrumbIssuer} descriptors.
147     */
148    public static DescriptorExtensionList<CrumbIssuer, Descriptor<CrumbIssuer>> all() {
149        return Hudson.getInstance().<CrumbIssuer, Descriptor<CrumbIssuer>>getDescriptorList(CrumbIssuer.class);
150    }
151
152    public Api getApi() {
153        return new Api(this);
154    }
155}