diff --git a/pom.xml b/pom.xml index 8e4b926e4..d5c5c1f2a 100644 --- a/pom.xml +++ b/pom.xml @@ -168,6 +168,11 @@ + + javax.validation + validation-api + 2.0.1.Final + xom xom @@ -398,6 +403,19 @@ ${version.jmh} test + + org.hibernate.validator + hibernate-validator + 6.2.5.Final + test + + + org.glassfish + javax.el + 3.0.0 + test + + diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidCreditCard.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidCreditCard.java new file mode 100644 index 000000000..00ccb793b --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidCreditCard.java @@ -0,0 +1,35 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidCreditCardValidator.class) +@Documented +public @interface ValidCreditCard { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidCreditCardValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidCreditCardValidator.java new file mode 100644 index 000000000..ec1105fd2 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidCreditCardValidator.java @@ -0,0 +1,35 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidCreditCardValidator implements ConstraintValidator{ + + private String context; + private boolean allowNull; + + @Override + public void initialize(ValidCreditCard validCreditCard) { + context = validCreditCard.context(); + allowNull = validCreditCard.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + boolean valid = ESAPI.validator().isValidCreditCard(context, input, allowNull, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDate.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDate.java new file mode 100644 index 000000000..7ccae19c3 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDate.java @@ -0,0 +1,42 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidDateValidator.class) +@Documented +public @interface ValidDate { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + //Invalid type DateFormat for the annotation attribute ValidDate.format; + //only primitive type, String, Class, annotation, enumeration are permitted or 1-dimensional arrays thereof + //DateFormat format(); + + int dateStyle(); + + String locale(); + + boolean allowNull(); +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDateValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDateValidator.java new file mode 100644 index 000000000..1e09df5b6 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDateValidator.java @@ -0,0 +1,57 @@ +package org.owasp.esapi.reference.validation.annotations; + +import java.text.DateFormat; +import java.util.Locale; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidDateValidator implements ConstraintValidator{ + + private String context; + private int dateStyle; + private String localeString; + private boolean allowNull; + + @Override + public void initialize(ValidDate validDate) { + context = validDate.context(); + dateStyle = validDate.dateStyle(); + localeString = validDate.locale(); + allowNull = validDate.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + Locale locale = toLocale(localeString); + DateFormat dateFormat = DateFormat.getDateInstance(dateStyle, locale); + + ValidationErrorList errorList = new ValidationErrorList(); + boolean valid = ESAPI.validator().isValidDate(context, input, dateFormat, allowNull, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } + + private static Locale toLocale(String localeValue) { + if (localeValue == null) { + return Locale.getDefault(); + } + String normalized = localeValue.trim(); + if (normalized.isEmpty()) { + return Locale.getDefault(); + } + Locale locale = Locale.forLanguageTag(normalized.replace('_', '-')); + return Locale.ROOT.equals(locale) ? Locale.getDefault() : locale; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDirectoryPath.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDirectoryPath.java new file mode 100644 index 000000000..c5e199c7d --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDirectoryPath.java @@ -0,0 +1,37 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidDirectoryPathValidator.class) +@Documented +public @interface ValidDirectoryPath { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + String parent(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDirectoryPathValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDirectoryPathValidator.java new file mode 100644 index 000000000..c6990c678 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDirectoryPathValidator.java @@ -0,0 +1,40 @@ +package org.owasp.esapi.reference.validation.annotations; + +import java.io.File; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidDirectoryPathValidator implements ConstraintValidator{ + + private String context; + private String parentString; + private boolean allowNull; + + @Override + public void initialize(ValidDirectoryPath validDirectoryPath) { + context = validDirectoryPath.context(); + parentString = validDirectoryPath.parent(); + allowNull = validDirectoryPath.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + File parent = new File(parentString); + boolean valid = ESAPI.validator().isValidDirectoryPath(context, input, parent, allowNull, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDouble.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDouble.java new file mode 100644 index 000000000..c141e87f9 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDouble.java @@ -0,0 +1,39 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidDoubleValidator.class) +@Documented +public @interface ValidDouble { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + double minValue(); + + double maxValue(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDoubleValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDoubleValidator.java new file mode 100644 index 000000000..ee81211bf --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidDoubleValidator.java @@ -0,0 +1,39 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidDoubleValidator implements ConstraintValidator{ + + private String context; + private double minValue; + private double maxValue; + private boolean allowNull; + + @Override + public void initialize(ValidDouble validDouble) { + context = validDouble.context(); + minValue = validDouble.minValue(); + maxValue = validDouble.maxValue(); + allowNull = validDouble.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + boolean valid = ESAPI.validator().isValidDouble(context, input, minValue, maxValue, allowNull, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileContent.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileContent.java new file mode 100644 index 000000000..39cb2242f --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileContent.java @@ -0,0 +1,37 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidFileContentValidator.class) +@Documented +public @interface ValidFileContent { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + int maxBytes(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileContentValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileContentValidator.java new file mode 100644 index 000000000..bf7dd966b --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileContentValidator.java @@ -0,0 +1,37 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidFileContentValidator implements ConstraintValidator{ + + private String context; + private int maxBytes; + private boolean allowNull; + + @Override + public void initialize(ValidFileContent validFileContent) { + context = validFileContent.context(); + maxBytes = validFileContent.maxBytes(); + allowNull = validFileContent.allowNull(); + } + + @Override + public boolean isValid(byte[] input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + boolean valid = ESAPI.validator().isValidFileContent(context, input, maxBytes, allowNull, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileName.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileName.java new file mode 100644 index 000000000..365926335 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileName.java @@ -0,0 +1,37 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidFileNameValidator.class) +@Documented +public @interface ValidFileName { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + String[] allowedExtensions() default {}; + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileNameValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileNameValidator.java new file mode 100644 index 000000000..5bcbe4278 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileNameValidator.java @@ -0,0 +1,47 @@ +package org.owasp.esapi.reference.validation.annotations; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidFileNameValidator implements ConstraintValidator{ + + private String context; + private String[] allowedExtensions; + private boolean allowNull; + + @Override + public void initialize(ValidFileName validFileName) { + context = validFileName.context(); + allowedExtensions = validFileName.allowedExtensions(); + allowNull = validFileName.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + boolean valid; + if(allowedExtensions.length == 0){ + valid = ESAPI.validator().isValidFileName(context, input, allowNull, errorList); + } else { + List allowedExtensionsList = new ArrayList<>(Arrays.asList(allowedExtensions)); + valid = ESAPI.validator().isValidFileName(context, input, allowedExtensionsList, allowNull, errorList); + } + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileUpload.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileUpload.java new file mode 100644 index 000000000..3edf41381 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileUpload.java @@ -0,0 +1,43 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidFileUploadValidator.class) +@Documented +public @interface ValidFileUpload { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + String directoryPath(); + + String fileName(); + + String parent(); + + int maxBytes(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileUploadValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileUploadValidator.java new file mode 100644 index 000000000..757206eca --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidFileUploadValidator.java @@ -0,0 +1,46 @@ +package org.owasp.esapi.reference.validation.annotations; + +import java.io.File; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidFileUploadValidator implements ConstraintValidator{ + + private String context; + private String directoryPath; + private String fileName; + private String parentString; + private int maxBytes; + private boolean allowNull; + + @Override + public void initialize(ValidFileUpload validFileUpload) { + context = validFileUpload.context(); + directoryPath = validFileUpload.directoryPath(); + fileName = validFileUpload.fileName(); + parentString = validFileUpload.parent(); + maxBytes = validFileUpload.maxBytes(); + allowNull = validFileUpload.allowNull(); + } + + @Override + public boolean isValid(byte[] input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + File parent = new File(parentString); + boolean valid = ESAPI.validator().isValidFileUpload(context, directoryPath, fileName, parent, input, maxBytes, allowNull, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidHTTPRequestParameterSet.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidHTTPRequestParameterSet.java new file mode 100644 index 000000000..a2cb9e911 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidHTTPRequestParameterSet.java @@ -0,0 +1,43 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidHTTPRequestParameterSetValidator.class) +@Documented +public @interface ValidHTTPRequestParameterSet { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + //Invalid type Set for the annotation attribute ValidHTTPRequestParameters.requiredNames; + //only primitive type, String, Class, annotation, enumeration are permitted or 1-dimensional arrays thereof + //Set requiredNames(); + + String[] requiredNames(); + + String[] optionalNames(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidHTTPRequestParameterSetValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidHTTPRequestParameterSetValidator.java new file mode 100644 index 000000000..100f2213f --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidHTTPRequestParameterSetValidator.java @@ -0,0 +1,49 @@ +package org.owasp.esapi.reference.validation.annotations; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidHTTPRequestParameterSetValidator implements ConstraintValidator{ + + private String context; + private String[] requiredNames; + private String[] optionalNames; + private boolean allowNull; + + @Override + public void initialize(ValidHTTPRequestParameterSet validHTTPRequestParameters) { + context = validHTTPRequestParameters.context(); + requiredNames = validHTTPRequestParameters.requiredNames(); + optionalNames = validHTTPRequestParameters.optionalNames(); + allowNull = validHTTPRequestParameters.allowNull(); + } + + @Override + public boolean isValid(HttpServletRequest input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + if (allowNull && input.getParameterMap().isEmpty()) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + Set requiredNamesSet = new HashSet<>(Arrays.asList(requiredNames)); + Set optionalNamesSet = new HashSet<>(Arrays.asList(optionalNames)); + boolean valid = ESAPI.validator().isValidHTTPRequestParameterSet(context, input, requiredNamesSet, optionalNamesSet, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidInteger.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidInteger.java new file mode 100644 index 000000000..7754e2dde --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidInteger.java @@ -0,0 +1,39 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidIntegerValidator.class) +@Documented +public @interface ValidInteger { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + int minValue(); + + int maxValue(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidIntegerValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidIntegerValidator.java new file mode 100644 index 000000000..c669c8dc0 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidIntegerValidator.java @@ -0,0 +1,39 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidIntegerValidator implements ConstraintValidator{ + + private String context; + private int minValue; + private int maxValue; + private boolean allowNull; + + @Override + public void initialize(ValidInteger validInteger) { + context = validInteger.context(); + minValue = validInteger.minValue(); + maxValue = validInteger.maxValue(); + allowNull = validInteger.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + boolean valid = ESAPI.validator().isValidInteger(context, input, minValue, maxValue, allowNull, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidListItem.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidListItem.java new file mode 100644 index 000000000..8ddd81850 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidListItem.java @@ -0,0 +1,41 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidListItemValidator.class) +@Documented +public @interface ValidListItem { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + // Invalid type List for the annotation attribute ValidListItem.list; + // only primitive type, String, Class, annotation, enumeration are permitted or 1-dimensional arrays thereof + //List list(); + + String[] list(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidListItemValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidListItemValidator.java new file mode 100644 index 000000000..2a3aa0fbe --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidListItemValidator.java @@ -0,0 +1,44 @@ +package org.owasp.esapi.reference.validation.annotations; + +import java.util.Arrays; +import java.util.List; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidListItemValidator implements ConstraintValidator{ + + private String context; + private String[] listArray; + private boolean allowNull; + + @Override + public void initialize(ValidListItem validListItem) { + context = validListItem.context(); + listArray = validListItem.list(); + allowNull = validListItem.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + if (allowNull && input.isEmpty()) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + List list = Arrays.asList(listArray); + boolean valid = ESAPI.validator().isValidListItem(context, input, list, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidNumber.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidNumber.java new file mode 100644 index 000000000..5d6298d9a --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidNumber.java @@ -0,0 +1,39 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidNumberValidator.class) +@Documented +public @interface ValidNumber { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + long minValue(); + + long maxValue(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidNumberValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidNumberValidator.java new file mode 100644 index 000000000..eac3a973d --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidNumberValidator.java @@ -0,0 +1,39 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidNumberValidator implements ConstraintValidator{ + + private String context; + private long minValue; + private long maxValue; + private boolean allowNull; + + @Override + public void initialize(ValidNumber validNumber) { + context = validNumber.context(); + minValue = validNumber.minValue(); + maxValue = validNumber.maxValue(); + allowNull = validNumber.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + boolean valid = ESAPI.validator().isValidNumber(context, input, minValue, maxValue, allowNull, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidPrintable.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidPrintable.java new file mode 100644 index 000000000..8a4923d18 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidPrintable.java @@ -0,0 +1,37 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = {ValidPrintableValidator.class, ValidPrintableStringValidator.class}) +@Documented +public @interface ValidPrintable { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + int maxLength(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidPrintableStringValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidPrintableStringValidator.java new file mode 100644 index 000000000..631d52a9e --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidPrintableStringValidator.java @@ -0,0 +1,37 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ESAPI; +import org.owasp.esapi.ValidationErrorList; + + +public class ValidPrintableStringValidator implements ConstraintValidator{ + + private String context; + private int maxLength; + private boolean allowNull; + + @Override + public void initialize(ValidPrintable validPrintable) { + context = validPrintable.context(); + maxLength = validPrintable.maxLength(); + allowNull = validPrintable.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + boolean valid = ESAPI.validator().isValidPrintable(context, input, maxLength, allowNull, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidPrintableValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidPrintableValidator.java new file mode 100644 index 000000000..355a9fb84 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidPrintableValidator.java @@ -0,0 +1,37 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidPrintableValidator implements ConstraintValidator{ + + private String context; + private int maxLength; + private boolean allowNull; + + @Override + public void initialize(ValidPrintable validPrintable) { + context = validPrintable.context(); + maxLength = validPrintable.maxLength(); + allowNull = validPrintable.allowNull(); + } + + @Override + public boolean isValid(char[] input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + boolean valid = ESAPI.validator().isValidPrintable(context, input, maxLength, allowNull, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidRedirectLocation.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidRedirectLocation.java new file mode 100644 index 000000000..2869ecbeb --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidRedirectLocation.java @@ -0,0 +1,35 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidRedirectLocationValidator.class) +@Documented +public @interface ValidRedirectLocation { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidRedirectLocationValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidRedirectLocationValidator.java new file mode 100644 index 000000000..c1b0693fc --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidRedirectLocationValidator.java @@ -0,0 +1,35 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidRedirectLocationValidator implements ConstraintValidator{ + + private String context; + private boolean allowNull; + + @Override + public void initialize(ValidRedirectLocation validRedirectLocation) { + context = validRedirectLocation.context(); + allowNull = validRedirectLocation.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + boolean valid = ESAPI.validator().isValidRedirectLocation(context, input, allowNull, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidSafeHTML.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidSafeHTML.java new file mode 100644 index 000000000..221ff4853 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidSafeHTML.java @@ -0,0 +1,37 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidSafeHTMLValidator.class) +@Documented +public @interface ValidSafeHTML { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + int maxLength(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidSafeHTMLValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidSafeHTMLValidator.java new file mode 100644 index 000000000..6e5fb9756 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidSafeHTMLValidator.java @@ -0,0 +1,38 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidSafeHTMLValidator implements ConstraintValidator{ + + private String context; + private int maxLength; + private boolean allowNull; + + @Override + public void initialize(ValidSafeHTML validSafeHTML) { + context = validSafeHTML.context(); + maxLength = validSafeHTML.maxLength(); + allowNull = validSafeHTML.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + ESAPI.validator().getValidSafeHTML(context, input, maxLength, allowNull, errorList); + boolean valid = errorList.isEmpty(); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidString.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidString.java new file mode 100644 index 000000000..9a91ff7a2 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidString.java @@ -0,0 +1,43 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidStringValidator.class) +@Documented +public @interface ValidString { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + String type() default "SafeString"; + + int maxLength(); + + boolean allowNull(); + + boolean canonicalize() default true; + +} + + diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidStringValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidStringValidator.java new file mode 100644 index 000000000..9d2c96aa5 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidStringValidator.java @@ -0,0 +1,41 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidStringValidator implements ConstraintValidator{ + + private String context; + private String type; + private int maxLength; + private boolean allowNull; + private boolean canonicalize; + + @Override + public void initialize(ValidString validString) { + context = validString.context(); + type = validString.type(); + maxLength = validString.maxLength(); + allowNull = validString.allowNull(); + canonicalize = validString.canonicalize(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + ValidationErrorList errorList = new ValidationErrorList(); + boolean valid = ESAPI.validator().isValidInput(context, input, type, maxLength, allowNull, canonicalize, errorList); + + if(!valid){ + ValidationUtil.addViolations(errorList, constraintValidatorContext); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidURI.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidURI.java new file mode 100644 index 000000000..2041210f7 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidURI.java @@ -0,0 +1,35 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidURIValidator.class) +@Documented +public @interface ValidURI { + + String message() default "Invalid URI"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String context(); + + boolean allowNull(); + +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidURIValidator.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidURIValidator.java new file mode 100644 index 000000000..f7c842ee6 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidURIValidator.java @@ -0,0 +1,41 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.ESAPI; + + +public class ValidURIValidator implements ConstraintValidator{ + + private String context; + private boolean allowNull; + + @Override + public void initialize(ValidURI validURI) { + context = validURI.context(); + allowNull = validURI.allowNull(); + } + + @Override + public boolean isValid(String input, ConstraintValidatorContext constraintValidatorContext) { + if (input == null) { + return true; + } + //isValidURI has no method signature that accepts a ValidationErrorList + //ValidationErrorList errorList = new ValidationErrorList(); + boolean valid = ESAPI.validator().isValidURI(context, input, allowNull); + + if (!valid) { + constraintValidatorContext.disableDefaultConstraintViolation(); + String message = constraintValidatorContext.getDefaultConstraintMessageTemplate(); + if (message == null || message.isEmpty()) { + message = "Invalid URI"; + } + constraintValidatorContext.buildConstraintViolationWithTemplate(message).addConstraintViolation(); + } + + return valid; + } +} diff --git a/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidationUtil.java b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidationUtil.java new file mode 100644 index 000000000..20bd35950 --- /dev/null +++ b/src/main/java/org/owasp/esapi/reference/validation/annotations/ValidationUtil.java @@ -0,0 +1,23 @@ +package org.owasp.esapi.reference.validation.annotations; + +import javax.validation.ConstraintValidatorContext; + +import org.owasp.esapi.ValidationErrorList; +import org.owasp.esapi.errors.ValidationException; + +public class ValidationUtil { + + private ValidationUtil(){} + + public static void addViolations(ValidationErrorList errorList, ConstraintValidatorContext constraintValidatorContext){ + constraintValidatorContext.disableDefaultConstraintViolation(); + for (ValidationException vex : errorList.errors()) { + String errorMessage = vex.getUserMessage(); + if (errorMessage == null || errorMessage.isEmpty()) { + errorMessage = constraintValidatorContext.getDefaultConstraintMessageTemplate(); + } + constraintValidatorContext.buildConstraintViolationWithTemplate(errorMessage).addConstraintViolation(); + } + } + +} diff --git a/src/test/java/org/owasp/esapi/reference/validation/annotations/ValidationAnnotationsTest.java b/src/test/java/org/owasp/esapi/reference/validation/annotations/ValidationAnnotationsTest.java new file mode 100644 index 000000000..4f653c7c0 --- /dev/null +++ b/src/test/java/org/owasp/esapi/reference/validation/annotations/ValidationAnnotationsTest.java @@ -0,0 +1,446 @@ +package org.owasp.esapi.reference.validation.annotations; + +import static org.junit.Assert.assertEquals; +import static org.owasp.esapi.PropNames.DISABLE_INTRUSION_DETECTION; + +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolation; +import javax.validation.Valid; +import javax.validation.Validation; +import javax.validation.Validator; + +import org.junit.After; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import org.owasp.esapi.ESAPI; +import org.owasp.esapi.SecurityConfiguration; +import org.owasp.esapi.SecurityConfigurationWrapper; +import org.owasp.esapi.http.MockHttpServletRequest; + +public class ValidationAnnotationsTest { + private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("win"); + private static final String WINDOWS_ROOT = "C:\\"; + private static final String UNIX_ROOT = "/"; + + private static class ConfOverride extends SecurityConfigurationWrapper { + ConfOverride(SecurityConfiguration orig) { + super(orig); + } + + @Override + public Boolean getBooleanProp(String propName) { + if (DISABLE_INTRUSION_DETECTION.equals(propName)) { + return Boolean.TRUE; + } + return super.getBooleanProp(propName); + } + } + + private Validator validator; + + @Before + public void setUp() { + ESAPI.override(new ConfOverride(ESAPI.securityConfiguration())); + validator = Validation.buildDefaultValidatorFactory().getValidator(); + } + + @After + public void tearDown() { + ESAPI.override(null); + } + + @Test + public void testValidCreditCard() { + CreditCardBean bean = new CreditCardBean("1234 9876 0000 0008"); + assertViolations(bean, 0); + bean.number = "4417 1234 5678 9112"; + assertViolations(bean, 1); + } + + @Test + public void testValidDate() { + String validDate = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US).format(new Date(0)); + DateBean bean = new DateBean(validDate); + assertViolations(bean, 0); + bean.value = "not-a-date"; + assertViolations(bean, 1); + } + + @Test + public void testValidDirectoryPath() { + if (IS_WINDOWS) { + Assume.assumeTrue(isSystemDriveC()); + DirectoryPathWindowsBean bean = new DirectoryPathWindowsBean(WINDOWS_ROOT); + assertViolations(bean, 0); + bean.path = WINDOWS_ROOT + "does-not-exist"; + assertViolations(bean, 1); + } else { + DirectoryPathUnixBean bean = new DirectoryPathUnixBean(UNIX_ROOT); + assertViolations(bean, 0); + bean.path = UNIX_ROOT + "does-not-exist"; + assertViolations(bean, 1); + } + } + + @Test + public void testValidDouble() { + DoubleBean bean = new DoubleBean("1.0"); + assertViolations(bean, 0); + bean.value = "ridiculous"; + assertViolations(bean, 1); + } + + @Test + public void testValidFileContent() { + FileContentBean bean = new FileContentBean("12345".getBytes(StandardCharsets.UTF_8)); + assertViolations(bean, 0); + bean.content = "123456".getBytes(StandardCharsets.UTF_8); + assertViolations(bean, 1); + } + + @Test + public void testValidFileName() { + FileNameBean bean = new FileNameBean("test.txt"); + assertViolations(bean, 0); + bean.name = "test.exe"; + assertViolations(bean, 1); + } + + @Test + public void testValidFileUpload() { + if (IS_WINDOWS) { + Assume.assumeTrue(isSystemDriveC()); + FileUploadWindowsBean bean = new FileUploadWindowsBean("12345".getBytes(StandardCharsets.UTF_8)); + assertViolations(bean, 0); + bean.content = "123456".getBytes(StandardCharsets.UTF_8); + assertViolations(bean, 1); + } else { + FileUploadUnixBean bean = new FileUploadUnixBean("12345".getBytes(StandardCharsets.UTF_8)); + assertViolations(bean, 0); + bean.content = "123456".getBytes(StandardCharsets.UTF_8); + assertViolations(bean, 1); + } + } + + @Test + public void testValidInteger() { + IntegerBean bean = new IntegerBean("5"); + assertViolations(bean, 0); + bean.value = "20"; + assertViolations(bean, 1); + } + + @Test + public void testValidListItem() { + ListItemBean bean = new ListItemBean("red"); + assertViolations(bean, 0); + bean.value = "blue"; + assertViolations(bean, 1); + } + + @Test + public void testValidNumber() { + NumberBean bean = new NumberBean("10"); + assertViolations(bean, 0); + bean.value = "1000"; + assertViolations(bean, 1); + } + + @Test + public void testValidPrintableChars() { + PrintableCharsBean bean = new PrintableCharsBean("Hello".toCharArray()); + assertViolations(bean, 0); + bean.value = "Hi\n".toCharArray(); + assertViolations(bean, 1); + } + + @Test + public void testValidPrintableString() { + PrintableStringBean bean = new PrintableStringBean("Hello"); + assertViolations(bean, 0); + bean.value = "Hi\n"; + assertViolations(bean, 1); + } + + @Test + public void testValidRedirectLocation() { + RedirectBean bean = new RedirectBean("/test/ok"); + assertViolations(bean, 0); + bean.value = "http://example.com"; + assertViolations(bean, 1); + } + + @Test + public void testValidSafeHTML() { + SafeHtmlBean bean = new SafeHtmlBean("Jeff"); + assertViolations(bean, 0); + bean.value = "Test. "; + assertViolations(bean, 1); + } + + @Test + public void testValidURI() { + UriBean bean = new UriBean("http://example.com"); + assertViolations(bean, 0); + bean.value = "javascript:alert(1)"; + assertViolations(bean, 1); + } + + @Test + public void testValidString() { + Person person = new Person("John"); + assertViolations(person, 0); + } + + @Test + public void testInvalidStringType() { + Person person = new Person("John