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

org.owasp.esapi.reference.validation.StringValidationRule Maven / Gradle / Ivy

Go to download

The Enterprise Security API (ESAPI) project is an OWASP project to create simple strong security controls for every web platform. Security controls are not simple to build. You can read about the hundreds of pitfalls for unwary developers on the OWASP website. By providing developers with a set of strong controls, we aim to eliminate some of the complexity of creating secure web applications. This can result in significant cost savings across the SDLC.

There is a newer version: 2.5.5.0
Show newest version
/**
 * OWASP Enterprise Security API (ESAPI)
 *
 * This file is part of the Open Web Application Security Project (OWASP)
 * Enterprise Security API (ESAPI) project. For details, please see
 * http://www.owasp.org/index.php/ESAPI.
 *
 * Copyright (c) 2007 - The OWASP Foundation
 *
 * The ESAPI is published by OWASP under the BSD license. You should read and accept the
 * LICENSE before you use, modify, and/or redistribute this software.
 *
 * @author Jeff Williams Aspect Security
 * @created 2007
 */
package org.owasp.esapi.reference.validation;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.owasp.esapi.ESAPI;
import org.owasp.esapi.Encoder;
import org.owasp.esapi.EncoderConstants;
import org.owasp.esapi.Logger;
import org.owasp.esapi.StringUtilities;
import org.owasp.esapi.errors.ValidationException;
import org.owasp.esapi.util.NullSafe;


/**
 * A validator performs syntax and possibly semantic validation of a single
 * piece of data from an untrusted source.
 *
 * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security
 * @since June 1, 2007
 * @see org.owasp.esapi.Validator
 *
 * http://en.wikipedia.org/wiki/Whitelist
 */
public class StringValidationRule extends BaseValidationRule {
    private static final Logger LOGGER = ESAPI.getLogger(StringValidationRule.class);
    protected List whitelistPatterns = new ArrayList();
    protected List blacklistPatterns = new ArrayList();
    protected int minLength = 0;
    protected int maxLength = Integer.MAX_VALUE;
    private boolean canonicalizeInput = true;

    public StringValidationRule( String typeName ) {
        super( typeName );
    }

    public StringValidationRule( String typeName, Encoder encoder ) {
        super( typeName, encoder );
    }

    public StringValidationRule( String typeName, Encoder encoder, String whitelistPattern ) {
        super( typeName, encoder );
        addWhitelistPattern( whitelistPattern );
    }

    /**
     * @throws IllegalArgumentException if pattern is null
     */
    public void addWhitelistPattern( String pattern ) {
        if (pattern == null) {
            throw new IllegalArgumentException("Pattern cannot be null");
        }
        try {
            whitelistPatterns.add( Pattern.compile( pattern ) );
        } catch( PatternSyntaxException e ) {
            throw new IllegalArgumentException( "Validation misconfiguration, problem with specified pattern: " + pattern, e );
        }
    }

    /**
     * @throws IllegalArgumentException if p is null
     */
    public void addWhitelistPattern( Pattern p ) {
        if (p == null) {
            throw new IllegalArgumentException("Pattern cannot be null");
        }
        whitelistPatterns.add( p );
    }

    /**
     * @throws IllegalArgumentException if pattern is null
     */
    public void addBlacklistPattern( String pattern ) {
        if (pattern == null) {
            throw new IllegalArgumentException("Pattern cannot be null");
        }
        try {
            blacklistPatterns.add( Pattern.compile( pattern ) );
        } catch( PatternSyntaxException e ) {
            throw new IllegalArgumentException( "Validation misconfiguration, problem with specified pattern: " + pattern, e );
        }
    }

    /**
     * @throws IllegalArgumentException if p is null
     */
    public void addBlacklistPattern( Pattern p ) {
        if (p == null) {
            throw new IllegalArgumentException("Pattern cannot be null");
        }
        blacklistPatterns.add( p );
    }

    public void setMinimumLength( int length ) {
        minLength = length;
    }


    public void setMaximumLength( int length ) {
        maxLength = length;
    }

    public void setCanonicalize(boolean canonicalize) {
        this.canonicalizeInput = canonicalize;
    }

    /**
     * checks input against whitelists.
     * @param context The context to include in exception messages
     * @param input the input to check
     * @param orig A origional input to include in exception
     *    messages. This is not included if it is the same as
     *    input.
     * @return input upon a successful check
     * @throws ValidationException if the check fails.
     */
    private String checkWhitelist(String context, String input, String orig) throws ValidationException
    {
        // check whitelist patterns
        for (Pattern p : whitelistPatterns) {
            if ( !p.matcher(input).matches() ) {
                throw new ValidationException( context + ": Invalid input. Please conform to regex " + p.pattern() + ( maxLength == Integer.MAX_VALUE ? "" : " with a maximum length of " + maxLength ), "Invalid input: context=" + context + ", type(" + getTypeName() + ")=" + p.pattern() + ", input=" + input + (NullSafe.equals(orig,input) ? "" : ", orig=" + orig), context );
            }
        }

        return input;
    }

    /**
     * checks input against whitelists.
     * @param context The context to include in exception messages
     * @param input the input to check
     * @return input upon a successful check
     * @throws ValidationException if the check fails.
     */
    private String checkWhitelist(String context, String input) throws ValidationException
    {
        return checkWhitelist(context, input, input);
    }

    /**
     * checks input against blacklists.
     * @param context The context to include in exception messages
     * @param input the input to check
     * @param orig A origional input to include in exception
     *    messages. This is not included if it is the same as
     *    input.
     * @return input upon a successful check
     * @throws ValidationException if the check fails.
     */
    private String checkBlacklist(String context, String input, String orig) throws ValidationException
    {
        // check blacklist patterns
        for (Pattern p : blacklistPatterns) {
            if ( p.matcher(input).matches() ) {
                throw new ValidationException( context + ": Invalid input. Dangerous input matching " + p.pattern() + " detected.", "Dangerous input: context=" + context + ", type(" + getTypeName() + ")=" + p.pattern() + ", input=" + input + (NullSafe.equals(orig,input) ? "" : ", orig=" + orig), context );
            }
        }

        return input;
    }

    /**
     * checks input against blacklists.
     * @param context The context to include in exception messages
     * @param input the input to check
     * @return input upon a successful check
     * @throws ValidationException if the check fails.
     */
    private String checkBlacklist(String context, String input) throws ValidationException
    {
        return checkBlacklist(context, input, input);
    }

    /**
     * checks input lengths
     * @param context The context to include in exception messages
     * @param input the input to check
     * @param orig A origional input to include in exception
     *    messages. This is not included if it is the same as
     *    input.
     * @return input upon a successful check
     * @throws ValidationException if the check fails.
     */
    private String checkLength(String context, String input, String orig) throws ValidationException
    {
        if (input.length() < minLength) {
            throw new ValidationException( context + ": Invalid input. The minimum length of " + minLength + " characters was not met.", "Input does not meet the minimum length of " + minLength + " by " + (minLength - input.length()) + " characters: context=" + context + ", type=" + getTypeName() + "), input=" + input + (NullSafe.equals(input,orig) ? "" : ", orig=" + orig), context );
        }

        if (input.length() > maxLength) {
            throw new ValidationException( context + ": Invalid input. The maximum length of " + maxLength + " characters was exceeded.", "Input exceeds maximum allowed length of " + maxLength + " by " + (input.length()-maxLength) + " characters: context=" + context + ", type=" + getTypeName() + ", orig=" + orig +", input=" + input, context );
        }

        return input;
    }

    /**
     * checks input lengths
     * @param context The context to include in exception messages
     * @param input the input to check
     * @return input upon a successful check
     * @throws ValidationException if the check fails.
     */
    private String checkLength(String context, String input) throws ValidationException
    {
        return checkLength(context, input, input);
    }

    /**
     * checks input emptiness
     * @param context The context to include in exception messages
     * @param input the input to check
     * @param orig A origional input to include in exception
     *    messages. This is not included if it is the same as
     *    input.
     * @return input upon a successful check
     * @throws ValidationException if the check fails.
     */
    private String checkEmpty(String context, String input, String orig) throws ValidationException
    {
        if(!StringUtilities.isEmpty(input))
            return input;
        if(allowNull)
            return null;
        throw new ValidationException( context + ": Input required.", "Input required: context=" + context + "), input=" + input + (NullSafe.equals(input,orig) ? "" : ", orig=" + orig), context );
    }

    /**
     * checks input emptiness
     * @param context The context to include in exception messages
     * @param input the input to check
     * @return input upon a successful check
     * @throws ValidationException if the check fails.
     */
    private String checkEmpty(String context, String input) throws ValidationException
    {
        return checkEmpty(context, input, input);
    }

    /**
     * {@inheritDoc}
     */
    public String getValid( String context, String input ) throws ValidationException
    {
        String data = null;

        // check for empty/null
        if(checkEmpty(context, input) == null)
            return null;

        // check length
        checkLength(context, input);

        // canonicalize
        if (canonicalizeInput) {
            data = encoder.canonicalize(input);
        } else {
            String message = String.format("Input validation excludes canonicalization.  Context: %s   Input: %s", context, input);
            LOGGER.warning(Logger.SECURITY_AUDIT, message);
            data = input;
        }

        // check whitelist patterns
        checkWhitelist(context, data, input);

        // check blacklist patterns
        checkBlacklist(context, data, input);

        // validation passed
        return data;
    }

    /**
     * {@inheritDoc}
     */
    @Override
        public String sanitize( String context, String input ) {
            return whitelist( input, EncoderConstants.CHAR_ALPHANUMERICS );
        }


}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy