Package hudson.security.csrf

Source Code of hudson.security.csrf.CrumbIssuer

/**
* Copyright (c) 2008-2009 Yahoo! Inc.
* All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
package hudson.security.csrf;

import javax.servlet.ServletRequest;

import hudson.init.Initializer;
import jenkins.model.Jenkins;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.WebApp;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;

import hudson.DescriptorExtensionList;
import hudson.ExtensionPoint;
import hudson.model.Api;
import hudson.model.Describable;
import hudson.model.Descriptor;
import hudson.util.MultipartFormDataParser;

/**
* A CrumbIssuer represents an algorithm to generate a nonce value, known as a
* crumb, to counter cross site request forgery exploits. Crumbs are typically
* hashes incorporating information that uniquely identifies an agent that sends
* a request, along with a guarded secret so that the crumb value cannot be
* forged by a third party.
*
* @author dty
* @see http://en.wikipedia.org/wiki/XSRF
*/
@ExportedBean
public abstract class CrumbIssuer implements Describable<CrumbIssuer>, ExtensionPoint {

    private static final String CRUMB_ATTRIBUTE = CrumbIssuer.class.getName() + "_crumb";

    /**
     * Get the name of the request parameter the crumb will be stored in. Exposed
     * here for the remote API.
     */
    @Exported
    public String getCrumbRequestField() {
        return getDescriptor().getCrumbRequestField();
    }

    /**
     * Get a crumb value based on user specific information in the current request.
     * Intended for use only by the remote API.
     * @return
     */
    @Exported
    public String getCrumb() {
        return getCrumb(Stapler.getCurrentRequest());
    }

    /**
     * Get a crumb value based on user specific information in the request.
     * @param request
     * @return
     */
    public String getCrumb(ServletRequest request) {
        String crumb = null;
        if (request != null) {
            crumb = (String) request.getAttribute(CRUMB_ATTRIBUTE);
        }
        if (crumb == null) {
            crumb = issueCrumb(request, getDescriptor().getCrumbSalt());
            if (request != null) {
                if ((crumb != null) && crumb.length()>0) {
                    request.setAttribute(CRUMB_ATTRIBUTE, crumb);
                } else {
                    request.removeAttribute(CRUMB_ATTRIBUTE);
                }
            }
        }

        return crumb;
    }

    /**
     * Create a crumb value based on user specific information in the request.
     * The crumb should be generated by building a cryptographic hash of:
     * <ul>
     <li>relevant information in the request that can uniquely identify the client
     *  <li>the salt value
     *  <li>an implementation specific guarded secret.
     * </ul>
     *
     * @param request
     * @param salt
     * @return
     */
    protected abstract String issueCrumb(ServletRequest request, String salt);

    /**
     * Get a crumb from a request parameter and validate it against other data
     * in the current request. The salt and request parameter that is used is
     * defined by the current configuration.
     *
     * @param request
     * @return
     */
    public boolean validateCrumb(ServletRequest request) {
        CrumbIssuerDescriptor<CrumbIssuer> desc = getDescriptor();
        String crumbField = desc.getCrumbRequestField();
        String crumbSalt = desc.getCrumbSalt();

        return validateCrumb(request, crumbSalt, request.getParameter(crumbField));
    }

    /**
     * Get a crumb from multipart form data and validate it against other data
     * in the current request. The salt and request parameter that is used is
     * defined by the current configuration.
     *
     * @param request
     * @param parser
     * @return
     */
    public boolean validateCrumb(ServletRequest request, MultipartFormDataParser parser) {
        CrumbIssuerDescriptor<CrumbIssuer> desc = getDescriptor();
        String crumbField = desc.getCrumbRequestField();
        String crumbSalt = desc.getCrumbSalt();

        return validateCrumb(request, crumbSalt, parser.get(crumbField));
    }

    /**
     * Validate a previously created crumb against information in the current request.
     *
     * @param request
     * @param salt
     * @param crumb The previously generated crumb to validate against information in the current request
     * @return
     */
    public abstract boolean validateCrumb(ServletRequest request, String salt, String crumb);

    /**
     * Access global configuration for the crumb issuer.
     */
    public CrumbIssuerDescriptor<CrumbIssuer> getDescriptor() {
        return (CrumbIssuerDescriptor<CrumbIssuer>) Jenkins.getInstance().getDescriptorOrDie(getClass());
    }

    /**
     * Returns all the registered {@link CrumbIssuer} descriptors.
     */
    public static DescriptorExtensionList<CrumbIssuer, Descriptor<CrumbIssuer>> all() {
        return Jenkins.getInstance().<CrumbIssuer, Descriptor<CrumbIssuer>>getDescriptorList(CrumbIssuer.class);
    }

    public Api getApi() {
        return new Api(this);
    }

    /**
     * Sets up Stapler to use our crumb issuer.
     */
    @Initializer
    public static void initStaplerCrumbIssuer() {
        WebApp.get(Jenkins.getInstance().servletContext).setCrumbIssuer(new org.kohsuke.stapler.CrumbIssuer() {
            @Override
            public String issueCrumb(StaplerRequest request) {
                CrumbIssuer ci = Jenkins.getInstance().getCrumbIssuer();
                return ci!=null ? ci.getCrumb(request) : DEFAULT.issueCrumb(request);
            }

            @Override
            public void validateCrumb(StaplerRequest request, String submittedCrumb) {
                CrumbIssuer ci = Jenkins.getInstance().getCrumbIssuer();
                if (ci==null) {
                    DEFAULT.validateCrumb(request,submittedCrumb);
                } else {
                    if (!ci.validateCrumb(request, ci.getDescriptor().getCrumbSalt(), submittedCrumb))
                        throw new SecurityException("Crumb didn't match");
                }
            }
        });
    }
}
TOP

Related Classes of hudson.security.csrf.CrumbIssuer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.