All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hudson.security.csrf.DefaultCrumbIssuer Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *
 * Copyright (c) 2008-2010 Yahoo! Inc.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors: 
 *
 *   
 *       
 *
 *******************************************************************************/ 

package hudson.security.csrf;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;

import hudson.Extension;
import hudson.model.Hudson;
import hudson.model.ModelObject;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONObject;

import org.springframework.security.Authentication;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;

/**
 * A crumb issuing algorithm based on the request principal and the remote address.
 * 
 * @author dty
 */
public class DefaultCrumbIssuer extends CrumbIssuer {
    
    private transient MessageDigest md;
    private boolean excludeClientIPFromCrumb;

    @DataBoundConstructor
    public DefaultCrumbIssuer(boolean excludeClientIPFromCrumb) {
        try {
            this.md = MessageDigest.getInstance("MD5");
            this.excludeClientIPFromCrumb = excludeClientIPFromCrumb;
        } catch (NoSuchAlgorithmException e) {
            this.md = null;
            this.excludeClientIPFromCrumb = false;
            LOGGER.log(Level.SEVERE, "Can't find MD5", e);
        }
    }

    public boolean isExcludeClientIPFromCrumb() {
        return this.excludeClientIPFromCrumb;
    }
    
    private Object readResolve() {
        try {
            this.md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            this.md = null;
            LOGGER.log(Level.SEVERE, "Can't find MD5", e);
        }
        
        return this;
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    protected String issueCrumb(ServletRequest request, String salt) {
        if (request instanceof HttpServletRequest) {
            if (md != null) {
                HttpServletRequest req = (HttpServletRequest) request;
                StringBuilder buffer = new StringBuilder();
                Authentication a = Hudson.getAuthentication();
                if (a != null) {
                    buffer.append(a.getName());
                }
                buffer.append(';');
                if (!isExcludeClientIPFromCrumb()) {
                    buffer.append(getClientIP(req));
                }

                md.update(buffer.toString().getBytes());
                byte[] crumbBytes = md.digest(salt.getBytes());

                StringBuilder hexString = new StringBuilder();
                for (int i = 0; i < crumbBytes.length; i++) {
                    String hex = Integer.toHexString(0xFF & crumbBytes[i]);
                    if (hex.length() == 1) {
                        hexString.append('0');
                    }
                    hexString.append(hex);
                }
                return hexString.toString();
            }
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean validateCrumb(ServletRequest request, String salt, String crumb) {
        if (request instanceof HttpServletRequest) {
            String newCrumb = issueCrumb(request, salt);
            if ((newCrumb != null) && (crumb != null)) {
                return newCrumb.equals(crumb);
            }
        }
        return false;
    }

    private final String PROXY_HEADER = "X-Forwarded-For";

    private String getClientIP(HttpServletRequest req) {
        String defaultAddress = req.getRemoteAddr();
        String forwarded = req.getHeader(PROXY_HEADER);
        if (forwarded != null) {
	        String[] hopList = forwarded.split(",");
            if (hopList.length >= 1) {
                return hopList[0];
            }
        }
        return defaultAddress;
    }
    
    @Extension
    public static final class DescriptorImpl extends CrumbIssuerDescriptor implements ModelObject {

        public DescriptorImpl() {
            super(Hudson.getInstance().getSecretKey(), System.getProperty("hudson.security.csrf.requestfield", ".crumb"));
            load();
        }

        @Override
        public String getDisplayName() {
            return Messages.DefaultCrumbIssuer_DisplayName();
        }

        @Override
        public DefaultCrumbIssuer newInstance(StaplerRequest req, JSONObject formData) throws FormException {
            return req.bindJSON(DefaultCrumbIssuer.class, formData);
        }
    }
    
    private static final Logger LOGGER = Logger.getLogger(DefaultCrumbIssuer.class.getName());
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy