/*
 *
 * Paros and its related class files.
 * 
 * Paros is an HTTP/HTTPS proxy for assessing web application security.
 * Copyright (C) 2003-2004 Chinotec Technologies Company
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the Clarified Artistic License
 * as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * Clarified Artistic License for more details.
 * 
 * You should have received a copy of the Clarified Artistic License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package org.parosproxy.paros.core.scanner.plugin;

import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.parosproxy.paros.core.scanner.AbstractAppParamPlugin;
import org.parosproxy.paros.core.scanner.Alert;
import org.parosproxy.paros.core.scanner.Category;
import org.parosproxy.paros.network.HttpMessage;


/**
 *
 * To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
public class TestInjectionCRLF extends AbstractAppParamPlugin {

	private static Random	staticRandomGenerator = 	new Random();
	private String randomString = "Tamper=" + Long.toString(Math.abs(staticRandomGenerator.nextLong()));
	private String cookieTamper1 = "Set-cookie:%20" + randomString;
	private String cookieTamper2 = "%0D%0ASet-cookie:%20" + randomString;
	private String cookieTamper3 = "%0ASet-cookie:%20" + randomString;
	private String cookieTamper4 = "%0D%0ASet-cookie:%20" + randomString + "%0D%0A";

	// should not be changed to static as Global may not be ready
	private String[] PARAM_LIST = {cookieTamper1, cookieTamper2, cookieTamper3, cookieTamper3};
	
	private Pattern patternCookieTamper = Pattern.compile("Set-cookie: " + randomString, PATTERN_PARAM);


    /* (non-Javadoc)
     * @see com.proofsecure.paros.core.scanner.Plugin#getId()
     */
    public int getId() {
        return 40001;
    }

    /* (non-Javadoc)
     * @see com.proofsecure.paros.core.scanner.Plugin#getName()
     */
    public String getName() {
        return "CRLF injection";
    }



    /* (non-Javadoc)
     * @see com.proofsecure.paros.core.scanner.Plugin#getDependency()
     */
    public String[] getDependency() {
        return null;
    }

    /* (non-Javadoc)
     * @see com.proofsecure.paros.core.scanner.Plugin#getDescription()
     */
    public String getDescription() {
        
        String msg = "Cookie can be set via CRLF injection.  It may also be possible to set arbitrary HTTP response header." + CRLF
        + "In addition, by carefully crafting the injected response using cross-site script, cache poisiong vulnerability may also exist.";
        return msg;
    }

    /* (non-Javadoc)
     * @see com.proofsecure.paros.core.scanner.Plugin#getCategory()
     */
    public int getCategory() {
        return Category.INJECTION;
    }

    /* (non-Javadoc)
     * @see com.proofsecure.paros.core.scanner.Plugin#getSolution()
     */
    public String getSolution() {
        return "Type check the submitted parameter carefully.  Do not allow CRLF to be injected by filtering CRLF.";
        
    }

    /* (non-Javadoc)
     * @see com.proofsecure.paros.core.scanner.Plugin#getReference()
     */
    public String getReference() {
        String msg = "http://www.sanctuminc.com/pdf/whitepaper_httpresponse.pdf" + CRLF
        + "http://webappfirewall.com/lib/crlf-injection.txtnull";
        
        return msg;
    }

    /* (non-Javadoc)
     * @see com.proofsecure.paros.core.scanner.AbstractPlugin#init()
     */
    public void init() {
 
    }
    
    public void scan(HttpMessage msg, String param, String value) {

		String bingoQuery = null;
		String displayURI = null;
		String newQuery = null;		
		
		// loop parameters

		for (int i=0; i<PARAM_LIST.length; i++) {
			msg = getNewMsg();
			bingoQuery = setParameter(msg, param, PARAM_LIST[i]);
			try {
                sendAndReceive(msg, false);
    			if (checkResult(msg, bingoQuery)) {
    			    return;
    			}

            } catch (Exception e) {
            }    

		}

		
	}

	private boolean checkResult(HttpMessage msg, String query) {
	    // no need to bother if response OK or not.
//	    if (msg.getResponseHeader().getStatusCode() != HttpStatusCode.OK
//			&& !HttpStatusCode.isServerError(msg.getResponseHeader().getStatusCode())) {
//			return false;
//		}
		
		Matcher matcher = patternCookieTamper.matcher(msg.getResponseHeader().toString());
		if (matcher.find()) {
			bingo(Alert.RISK_MEDIUM, Alert.WARNING, null, query, "", msg);
			return true;
		}
		
		return false;
		
	}

}
