From bc3bd831c79cc47abae4e6f6481c7338d01b3cf9 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sat, 28 May 2022 16:33:27 -0400 Subject: [PATCH 001/197] Delete unneed log4j import. --- src/examples/java/PersistedEncryptedData.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/examples/java/PersistedEncryptedData.java b/src/examples/java/PersistedEncryptedData.java index a034d0a50..06a0512eb 100644 --- a/src/examples/java/PersistedEncryptedData.java +++ b/src/examples/java/PersistedEncryptedData.java @@ -4,7 +4,6 @@ import org.owasp.esapi.errors.*; import org.owasp.esapi.codecs.*; import javax.servlet.ServletRequest; -import org.apache.log4j.Logger; /** A slightly more complex example showing encoding encrypted data and writing * it out to a file. This is very similar to the example in the ESAPI User From 5ae813538f29762d75d3a615e86fa48f836b5e64 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sat, 28 May 2022 22:32:21 -0400 Subject: [PATCH 002/197] Mark 2 public static variables as deprecated as they are not used. --- .../waf/configuration/AppGuardianConfiguration.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java b/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java index 78140cdfc..8523c2ceb 100644 --- a/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java +++ b/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java @@ -46,12 +46,25 @@ public class AppGuardianConfiguration { public static final int OPERATOR_IN_LIST = 2; public static final int OPERATOR_EXISTS = 3; + //// TODO - Delete these comments and the next 2 declarations on log4j clean-up. /* * We have static copies of the log settings so that the Rule objects * can access them, because they don't have access to the instance of * the configuration object. */ + /** + * @deprecated This {@code LOG_LEVEL} has never actually been used + * internally and this will be deleted when we remove all Log4J 1.x + * references. + */ + @Deprecated public static Level LOG_LEVEL = Level.INFO; + /** + * @deprecated This {@code LOG_DIRECTORY} has never actually been used + * internally and this will be deleted when we remove all Log4J 1.x + * references. + */ + @Deprecated public static String LOG_DIRECTORY = "/WEB-INF/logs"; /* From 85ce010730f878a6420a030fb78f04a71765f9a1 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sun, 29 May 2022 21:14:30 -0400 Subject: [PATCH 003/197] Update versions of 3 plugins. --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 83add7749..d9dde1dda 100644 --- a/pom.xml +++ b/pom.xml @@ -140,7 +140,7 @@ 2.0.9 4.7.0 1.12.0 - 4.6.0.0 + 4.7.0.0 3.0.0-M6 1.8 @@ -426,7 +426,7 @@ org.codehaus.mojo versions-maven-plugin - 2.10.0 + 2.11.0 file:${project.basedir}/versionRuleset.xml @@ -439,7 +439,7 @@ org.cyclonedx cyclonedx-maven-plugin - 2.6.1 + 2.7.0 package From 26a499491ff061f6744a3ef4f61b65eb4c2c2654 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sun, 29 May 2022 23:14:04 -0400 Subject: [PATCH 004/197] Issue #620. Reorganize source to get stuff out of implementatiopn class. Moved ESAPI propery variables ('public static final String') from DefaultSecurityConfiguration to here. Moved DefaultSearchPath enum from DefaultSecurityConfiguration to here. --- src/main/java/org/owasp/esapi/PropNames.java | 201 +++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 src/main/java/org/owasp/esapi/PropNames.java diff --git a/src/main/java/org/owasp/esapi/PropNames.java b/src/main/java/org/owasp/esapi/PropNames.java new file mode 100644 index 000000000..33a5eb4e1 --- /dev/null +++ b/src/main/java/org/owasp/esapi/PropNames.java @@ -0,0 +1,201 @@ +// TODO: Discuss: Should the name of this be PropConstants or PropertConstants +// since there are some property values included here? I don't +// really like that as much as PropNames, but I could live with +// it. +/* + * 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 + * https://owasp.org/www-project-enterprise-security-api/. + * + * Copyright (c) 2022 - 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. + * + */ +package org.owasp.esapi; + + +/** + * This non-constructable class of public constants defines all the property names used in {@code ESAPI.properties} as + * well as some of the default property values for some of those properties. This class is not intended + * to be extended or instantiated. Technically, an interface would have worked here, but we + * also wanted to be able to prevent 'implements PropNames', which really does not make much + * sense since no specific behavior is promised here. Another alternative would have + * been to place all of these in the {@code org.owasp.esapi.SecurityConfiguration} interface, + * but that interface is already overly bloated. Hence this was decided as a compromise. + *

+ * Note that the constants herein were originally all defined within + * {@code org.owasp.esapi.reference.DefaultSecurityConfiguration}, but those + * values are now marked deprecated and they are candidates for removal 2 years + * from the date of this release. + *

+ * Mostly this is intended to prevent having to hard-code property names all + * over the place in implementation-level classes (e.g., + * {@code org.owasp.esapi.reference.DefaultSecurityConfiguration}). + * It is suggested that this file be used as a 'static import'; + * e.g., + *

+ *      import static org.owasp.esapi.PropNames.*;                      // Import all properties, en masse
+ * or
+ *      import static org.owasp.esapi.PropNames.SomeSpecificPropName;   // Import specific property name
+ * 
+ * This can be extremely useful when used with methods such as + * {@code SecurityConfiguration.getIntProp(String propName)}, + * {@code SecurityConfiguration.getBooleanProp(String propName)}, + * {@code SecurityConfiguration.getStringProp(String propName)}, etc. + * + * @author Kevin W. Wall (kevin.w.wall .at. gmail.com) + * @since 2.4.1.0 + * @see org.owasp.esapi.reference.DefaultSecurityConfiguration + */ + +public final class PropNames { + + public static final String REMEMBER_TOKEN_DURATION = "Authenticator.RememberTokenDuration"; + public static final String IDLE_TIMEOUT_DURATION = "Authenticator.IdleTimeoutDuration"; + public static final String ABSOLUTE_TIMEOUT_DURATION = "Authenticator.AbsoluteTimeoutDuration"; + public static final String ALLOWED_LOGIN_ATTEMPTS = "Authenticator.AllowedLoginAttempts"; + public static final String USERNAME_PARAMETER_NAME = "Authenticator.UsernameParameterName"; + public static final String PASSWORD_PARAMETER_NAME = "Authenticator.PasswordParameterName"; + public static final String MAX_OLD_PASSWORD_HASHES = "Authenticator.MaxOldPasswordHashes"; + + public static final String ALLOW_MULTIPLE_ENCODING = "Encoder.AllowMultipleEncoding"; + public static final String ALLOW_MIXED_ENCODING = "Encoder.AllowMixedEncoding"; + public static final String CANONICALIZATION_CODECS = "Encoder.DefaultCodecList"; + + public static final String DISABLE_INTRUSION_DETECTION = "IntrusionDetector.Disable"; + + public static final String MASTER_KEY = "Encryptor.MasterKey"; + public static final String MASTER_SALT = "Encryptor.MasterSalt"; + public static final String KEY_LENGTH = "Encryptor.EncryptionKeyLength"; + public static final String ENCRYPTION_ALGORITHM = "Encryptor.EncryptionAlgorithm"; + public static final String HASH_ALGORITHM = "Encryptor.HashAlgorithm"; + public static final String HASH_ITERATIONS = "Encryptor.HashIterations"; + public static final String CHARACTER_ENCODING = "Encryptor.CharacterEncoding"; + public static final String RANDOM_ALGORITHM = "Encryptor.RandomAlgorithm"; + public static final String DIGITAL_SIGNATURE_ALGORITHM = "Encryptor.DigitalSignatureAlgorithm"; + public static final String DIGITAL_SIGNATURE_KEY_LENGTH = "Encryptor.DigitalSignatureKeyLength"; + public static final String PREFERRED_JCE_PROVIDER = "Encryptor.PreferredJCEProvider"; + public static final String CIPHER_TRANSFORMATION_IMPLEMENTATION = "Encryptor.CipherTransformation"; + public static final String CIPHERTEXT_USE_MAC = "Encryptor.CipherText.useMAC"; + public static final String PLAINTEXT_OVERWRITE = "Encryptor.PlainText.overwrite"; + public static final String IV_TYPE = "Encryptor.ChooseIVMethod"; // Will be removed in future release. + public static final String COMBINED_CIPHER_MODES = "Encryptor.cipher_modes.combined_modes"; + public static final String ADDITIONAL_ALLOWED_CIPHER_MODES = "Encryptor.cipher_modes.additional_allowed"; + public static final String KDF_PRF_ALG = "Encryptor.KDF.PRF"; + public static final String PRINT_PROPERTIES_WHEN_LOADED = "ESAPI.printProperties"; + + public static final String WORKING_DIRECTORY = "Executor.WorkingDirectory"; + public static final String APPROVED_EXECUTABLES = "Executor.ApprovedExecutables"; + + public static final String FORCE_HTTPONLYSESSION = "HttpUtilities.ForceHttpOnlySession"; + public static final String FORCE_SECURESESSION = "HttpUtilities.SecureSession"; + public static final String FORCE_HTTPONLYCOOKIES = "HttpUtilities.ForceHttpOnlyCookies"; + public static final String FORCE_SECURECOOKIES = "HttpUtilities.ForceSecureCookies"; + public static final String MAX_HTTP_HEADER_SIZE = "HttpUtilities.MaxHeaderSize"; + public static final String UPLOAD_DIRECTORY = "HttpUtilities.UploadDir"; + public static final String UPLOAD_TEMP_DIRECTORY = "HttpUtilities.UploadTempDir"; + public static final String APPROVED_UPLOAD_EXTENSIONS = "HttpUtilities.ApprovedUploadExtensions"; + public static final String MAX_UPLOAD_FILE_BYTES = "HttpUtilities.MaxUploadFileBytes"; + public static final String RESPONSE_CONTENT_TYPE = "HttpUtilities.ResponseContentType"; + public static final String HTTP_SESSION_ID_NAME = "HttpUtilities.HttpSessionIdName"; + + public static final String APPLICATION_NAME = "Logger.ApplicationName"; + public static final String LOG_USER_INFO = "Logger.UserInfo"; + public static final String LOG_CLIENT_INFO = "Logger.ClientInfo"; + public static final String LOG_ENCODING_REQUIRED = "Logger.LogEncodingRequired"; + public static final String LOG_APPLICATION_NAME = "Logger.LogApplicationName"; + public static final String LOG_SERVER_IP = "Logger.LogServerIP"; + + public static final String VALIDATION_PROPERTIES = "Validator.ConfigurationFile"; + public static final String VALIDATION_PROPERTIES_MULTIVALUED = "Validator.ConfigurationFile.MultiValued"; + public static final String ACCEPT_LENIENT_DATES = "Validator.AcceptLenientDates"; + public static final String VALIDATOR_HTML_VALIDATION_ACTION = "Validator.HtmlValidationAction"; + public static final String VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE = "Validator.HtmlValidationConfigurationFile"; + + /** + * Special {@code java.lang.System} property that, if set to {@code true}, will + * disable logging from {@code DefaultSecurityConfiguration.logToStdout()} + * methods, which is called from various {@code logSpecial()} methods. + * + * @see org.owasp.esapi.reference.DefaultSecurityConfiguration#logToStdout(String msg, Throwable t) + */ + public static final String DISCARD_LOGSPECIAL = "org.owasp.esapi.logSpecial.discard"; + + /* + * Implementation Keys + */ + public static final String LOG_IMPLEMENTATION = "ESAPI.Logger"; + public static final String AUTHENTICATION_IMPLEMENTATION = "ESAPI.Authenticator"; + public static final String ENCODER_IMPLEMENTATION = "ESAPI.Encoder"; + public static final String ACCESS_CONTROL_IMPLEMENTATION = "ESAPI.AccessControl"; + public static final String ENCRYPTION_IMPLEMENTATION = "ESAPI.Encryptor"; + public static final String INTRUSION_DETECTION_IMPLEMENTATION = "ESAPI.IntrusionDetector"; + public static final String RANDOMIZER_IMPLEMENTATION = "ESAPI.Randomizer"; + public static final String EXECUTOR_IMPLEMENTATION = "ESAPI.Executor"; + public static final String VALIDATOR_IMPLEMENTATION = "ESAPI.Validator"; + public static final String HTTP_UTILITIES_IMPLEMENTATION = "ESAPI.HTTPUtilities"; + + + ////////////////////////////////////////////////////////////////////////////// + // // + // These are not really property names, but the shouldn't really be in an // + // implementation class that we want to only deal with via the // + // SecurityConfiguration interface. // + // // + ////////////////////////////////////////////////////////////////////////////// + + + /* + * These are default implementation classes. + */ + public static final String DEFAULT_LOG_IMPLEMENTATION = "org.owasp.esapi.logging.java.JavaLogFactory"; + public static final String DEFAULT_AUTHENTICATION_IMPLEMENTATION = "org.owasp.esapi.reference.FileBasedAuthenticator"; + public static final String DEFAULT_ENCODER_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultEncoder"; + public static final String DEFAULT_ACCESS_CONTROL_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultAccessController"; + public static final String DEFAULT_ENCRYPTION_IMPLEMENTATION = "org.owasp.esapi.reference.crypto.JavaEncryptor"; + public static final String DEFAULT_INTRUSION_DETECTION_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultIntrusionDetector"; + public static final String DEFAULT_RANDOMIZER_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultRandomizer"; + public static final String DEFAULT_EXECUTOR_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultExecutor"; + public static final String DEFAULT_HTTP_UTILITIES_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultHTTPUtilities"; + public static final String DEFAULT_VALIDATOR_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultValidator"; + + /** The name of the ESAPI property file */ + public static final String DEFAULT_RESOURCE_FILE = "ESAPI.properties"; + + // + // Private CTOR to prevent creation of PropName objects. We wouldn't need + // this if this were an interface, nor would we need the explict 'public static final'. + // + private PropNames() { + throw new AssertionError("Thought you'd cheat using reflection or JNI, huh? :)"); + } + + + /** Enum used with the search paths used to locate an + * {@code ESAPI.properties} and/or a {@code validation.properties} + * file. + */ + public enum DefaultSearchPath { + + RESOURCE_DIRECTORY("resourceDirectory/"), + SRC_MAIN_RESOURCES("src/main/resources/"), + ROOT(""), + DOT_ESAPI(".esapi/"), + ESAPI("esapi/"), + RESOURCES("resources/"); + + private final String path; + + private DefaultSearchPath(String s){ + this.path = s; + } + + public String value(){ + return path; + } + } +} From 0123aa24af801825ed56c4b9ad11277f2e997740 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sun, 29 May 2022 23:17:23 -0400 Subject: [PATCH 005/197] Reorganized by moving public stuff from this implementation class to the new PropNames class. Also some misc code cleanup such as removing extraneous whitespace at end of lines, etc. --- .../DefaultSecurityConfiguration.java | 500 +++++++++++------- 1 file changed, 316 insertions(+), 184 deletions(-) diff --git a/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java b/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java index f9cf95fe4..da64fd894 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java @@ -2,7 +2,7 @@ * 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 + * Enterprise Security API (ESAPI) project. For details, please see{ * http://www.owasp.org/index.php/ESAPI. * * Copyright (c) 2007 - The OWASP Foundation @@ -36,6 +36,8 @@ import org.apache.commons.lang.text.StrTokenizer; import org.owasp.esapi.ESAPI; import org.owasp.esapi.Logger; +import org.owasp.esapi.PropNames; // <== Actual property names moved to here. Eventually we'll do static import. +import org.owasp.esapi.PropNames.DefaultSearchPath; import org.owasp.esapi.SecurityConfiguration; import org.owasp.esapi.configuration.EsapiPropertyManager; import org.owasp.esapi.errors.ConfigurationException; @@ -63,10 +65,17 @@ * keys and passwords, logging locations, error thresholds, and allowed file extensions. *

* WARNING: Do not forget to update ESAPI.properties to change the master key and other security critical settings. + *

+ * DEPRECATION WARNING: All of the variables of the type '{@code public static final String}' + * are now declared and defined in the {@code org.owasp.esapi.PropNames}. These public fields + * representing property names and values in this class will be eventually deleted and + * no longer available, so please migrate to the corresponding names in {@code PropNames}. Removal of these + * public fields from this class will likely occur sometime in 2Q2024. * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @author Jim Manico (jim .at. manico.net) Manico.net - * @author Kevin Wall (kevin.w.wall .at. gmail.com) + * @author Kevin W. Wall (kevin.w.wall .at. gmail.com) + * */ public class DefaultSecurityConfiguration implements SecurityConfiguration { @@ -82,123 +91,267 @@ public static SecurityConfiguration getInstance() { } return instance; } - + private Properties properties = null; private String cipherXformFromESAPIProp = null; // New in ESAPI 2.0 - private String cipherXformCurrent = null; // New in ESAPI 2.0 - - /** The name of the ESAPI property file */ - public static final String DEFAULT_RESOURCE_FILE = "ESAPI.properties"; - - public static final String REMEMBER_TOKEN_DURATION = "Authenticator.RememberTokenDuration"; - public static final String IDLE_TIMEOUT_DURATION = "Authenticator.IdleTimeoutDuration"; - public static final String ABSOLUTE_TIMEOUT_DURATION = "Authenticator.AbsoluteTimeoutDuration"; - public static final String ALLOWED_LOGIN_ATTEMPTS = "Authenticator.AllowedLoginAttempts"; - public static final String USERNAME_PARAMETER_NAME = "Authenticator.UsernameParameterName"; - public static final String PASSWORD_PARAMETER_NAME = "Authenticator.PasswordParameterName"; - public static final String MAX_OLD_PASSWORD_HASHES = "Authenticator.MaxOldPasswordHashes"; - - public static final String ALLOW_MULTIPLE_ENCODING = "Encoder.AllowMultipleEncoding"; - public static final String ALLOW_MIXED_ENCODING = "Encoder.AllowMixedEncoding"; - public static final String CANONICALIZATION_CODECS = "Encoder.DefaultCodecList"; - - public static final String DISABLE_INTRUSION_DETECTION = "IntrusionDetector.Disable"; - - public static final String MASTER_KEY = "Encryptor.MasterKey"; - public static final String MASTER_SALT = "Encryptor.MasterSalt"; - public static final String KEY_LENGTH = "Encryptor.EncryptionKeyLength"; - public static final String ENCRYPTION_ALGORITHM = "Encryptor.EncryptionAlgorithm"; - public static final String HASH_ALGORITHM = "Encryptor.HashAlgorithm"; - public static final String HASH_ITERATIONS = "Encryptor.HashIterations"; - public static final String CHARACTER_ENCODING = "Encryptor.CharacterEncoding"; - public static final String RANDOM_ALGORITHM = "Encryptor.RandomAlgorithm"; - public static final String DIGITAL_SIGNATURE_ALGORITHM = "Encryptor.DigitalSignatureAlgorithm"; - public static final String DIGITAL_SIGNATURE_KEY_LENGTH = "Encryptor.DigitalSignatureKeyLength"; + private String cipherXformCurrent = null; // New in ESAPI 2.0 + + /** The name of the ESAPI property file. + * @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. + */ + @Deprecated public static final String DEFAULT_RESOURCE_FILE = PropNames.DEFAULT_RESOURCE_FILE; + + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String REMEMBER_TOKEN_DURATION = PropNames.REMEMBER_TOKEN_DURATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String IDLE_TIMEOUT_DURATION = PropNames.IDLE_TIMEOUT_DURATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String ABSOLUTE_TIMEOUT_DURATION = PropNames.ABSOLUTE_TIMEOUT_DURATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String ALLOWED_LOGIN_ATTEMPTS = PropNames.ALLOWED_LOGIN_ATTEMPTS; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String USERNAME_PARAMETER_NAME = PropNames.USERNAME_PARAMETER_NAME; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String PASSWORD_PARAMETER_NAME = PropNames.PASSWORD_PARAMETER_NAME; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String MAX_OLD_PASSWORD_HASHES = PropNames.MAX_OLD_PASSWORD_HASHES; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String ALLOW_MULTIPLE_ENCODING = PropNames.ALLOW_MULTIPLE_ENCODING; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String ALLOW_MIXED_ENCODING = PropNames.ALLOW_MIXED_ENCODING ; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String CANONICALIZATION_CODECS = PropNames.CANONICALIZATION_CODECS; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DISABLE_INTRUSION_DETECTION = PropNames.DISABLE_INTRUSION_DETECTION ; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String MASTER_KEY = PropNames.MASTER_KEY; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String MASTER_SALT = PropNames.MASTER_SALT; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String KEY_LENGTH = PropNames.KEY_LENGTH; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String ENCRYPTION_ALGORITHM = PropNames.ENCRYPTION_ALGORITHM; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String HASH_ALGORITHM = PropNames.HASH_ALGORITHM; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String HASH_ITERATIONS = PropNames.HASH_ITERATIONS; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String CHARACTER_ENCODING = PropNames.CHARACTER_ENCODING; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String RANDOM_ALGORITHM = PropNames.RANDOM_ALGORITHM; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DIGITAL_SIGNATURE_ALGORITHM = PropNames.DIGITAL_SIGNATURE_ALGORITHM; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DIGITAL_SIGNATURE_KEY_LENGTH = PropNames.DIGITAL_SIGNATURE_KEY_LENGTH; + // ==================================// - // New in ESAPI Java 2.x // + // New in ESAPI Java 2.x // // ================================= // - public static final String PREFERRED_JCE_PROVIDER = "Encryptor.PreferredJCEProvider"; - public static final String CIPHER_TRANSFORMATION_IMPLEMENTATION = "Encryptor.CipherTransformation"; - public static final String CIPHERTEXT_USE_MAC = "Encryptor.CipherText.useMAC"; - public static final String PLAINTEXT_OVERWRITE = "Encryptor.PlainText.overwrite"; + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String PREFERRED_JCE_PROVIDER = PropNames.PREFERRED_JCE_PROVIDER; - @Deprecated - public static final String IV_TYPE = "Encryptor.ChooseIVMethod"; // Will be removed in future release. - - public static final String COMBINED_CIPHER_MODES = "Encryptor.cipher_modes.combined_modes"; - public static final String ADDITIONAL_ALLOWED_CIPHER_MODES = "Encryptor.cipher_modes.additional_allowed"; - public static final String KDF_PRF_ALG = "Encryptor.KDF.PRF"; - public static final String PRINT_PROPERTIES_WHEN_LOADED = "ESAPI.printProperties"; - - public static final String WORKING_DIRECTORY = "Executor.WorkingDirectory"; - public static final String APPROVED_EXECUTABLES = "Executor.ApprovedExecutables"; - - public static final String FORCE_HTTPONLYSESSION = "HttpUtilities.ForceHttpOnlySession"; - public static final String FORCE_SECURESESSION = "HttpUtilities.SecureSession"; - public static final String FORCE_HTTPONLYCOOKIES = "HttpUtilities.ForceHttpOnlyCookies"; - public static final String FORCE_SECURECOOKIES = "HttpUtilities.ForceSecureCookies"; - public static final String MAX_HTTP_HEADER_SIZE = "HttpUtilities.MaxHeaderSize"; - public static final String UPLOAD_DIRECTORY = "HttpUtilities.UploadDir"; - public static final String UPLOAD_TEMP_DIRECTORY = "HttpUtilities.UploadTempDir"; - public static final String APPROVED_UPLOAD_EXTENSIONS = "HttpUtilities.ApprovedUploadExtensions"; - public static final String MAX_UPLOAD_FILE_BYTES = "HttpUtilities.MaxUploadFileBytes"; - public static final String RESPONSE_CONTENT_TYPE = "HttpUtilities.ResponseContentType"; - public static final String HTTP_SESSION_ID_NAME = "HttpUtilities.HttpSessionIdName"; - - public static final String APPLICATION_NAME = "Logger.ApplicationName"; - public static final String LOG_ENCODING_REQUIRED = "Logger.LogEncodingRequired"; - public static final String LOG_APPLICATION_NAME = "Logger.LogApplicationName"; - public static final String LOG_SERVER_IP = "Logger.LogServerIP"; - public static final String LOG_USER_INFO = "Logger.UserInfo"; - public static final String LOG_CLIENT_INFO = "Logger.ClientInfo"; - public static final String VALIDATION_PROPERTIES = "Validator.ConfigurationFile"; - public static final String VALIDATION_PROPERTIES_MULTIVALUED = "Validator.ConfigurationFile.MultiValued"; - public static final String ACCEPT_LENIENT_DATES = "Validator.AcceptLenientDates"; - public static final String VALIDATOR_HTML_VALIDATION_ACTION = "Validator.HtmlValidationAction"; - public static final String VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE = "Validator.HtmlValidationConfigurationFile"; - - /** - * Special {@code System} property that, if set to {@code true}, will + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String CIPHER_TRANSFORMATION_IMPLEMENTATION = PropNames.CIPHER_TRANSFORMATION_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String CIPHERTEXT_USE_MAC = PropNames.CIPHERTEXT_USE_MAC; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String PLAINTEXT_OVERWRITE = PropNames.PLAINTEXT_OVERWRITE; + + @Deprecated public static final String IV_TYPE = PropNames.IV_TYPE; // Will be removed in future release. + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String COMBINED_CIPHER_MODES = PropNames.COMBINED_CIPHER_MODES; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String ADDITIONAL_ALLOWED_CIPHER_MODES = PropNames.ADDITIONAL_ALLOWED_CIPHER_MODES; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String KDF_PRF_ALG = PropNames.KDF_PRF_ALG; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String PRINT_PROPERTIES_WHEN_LOADED = PropNames.PRINT_PROPERTIES_WHEN_LOADED; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String WORKING_DIRECTORY = PropNames.WORKING_DIRECTORY; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String APPROVED_EXECUTABLES = PropNames.APPROVED_EXECUTABLES; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String FORCE_HTTPONLYSESSION = PropNames.FORCE_HTTPONLYSESSION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String FORCE_SECURESESSION = PropNames.FORCE_SECURESESSION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String FORCE_HTTPONLYCOOKIES = PropNames.FORCE_HTTPONLYCOOKIES; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String FORCE_SECURECOOKIES = PropNames.FORCE_SECURECOOKIES; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String MAX_HTTP_HEADER_SIZE = PropNames.MAX_HTTP_HEADER_SIZE; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String UPLOAD_DIRECTORY = PropNames.UPLOAD_DIRECTORY; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String UPLOAD_TEMP_DIRECTORY = PropNames.UPLOAD_TEMP_DIRECTORY; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String APPROVED_UPLOAD_EXTENSIONS = PropNames.APPROVED_UPLOAD_EXTENSIONS; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String MAX_UPLOAD_FILE_BYTES = PropNames.MAX_UPLOAD_FILE_BYTES; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String RESPONSE_CONTENT_TYPE = PropNames.RESPONSE_CONTENT_TYPE; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String HTTP_SESSION_ID_NAME = PropNames.HTTP_SESSION_ID_NAME; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String APPLICATION_NAME = PropNames.APPLICATION_NAME; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String LOG_ENCODING_REQUIRED = PropNames.LOG_ENCODING_REQUIRED; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String LOG_APPLICATION_NAME = PropNames.LOG_APPLICATION_NAME; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String LOG_SERVER_IP = PropNames.LOG_SERVER_IP; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String LOG_USER_INFO = PropNames.LOG_USER_INFO; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String LOG_CLIENT_INFO = PropNames.LOG_CLIENT_INFO; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String VALIDATION_PROPERTIES = PropNames.VALIDATION_PROPERTIES; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String VALIDATION_PROPERTIES_MULTIVALUED = PropNames.VALIDATION_PROPERTIES_MULTIVALUED; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String ACCEPT_LENIENT_DATES = PropNames.ACCEPT_LENIENT_DATES; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String VALIDATOR_HTML_VALIDATION_ACTION = PropNames.VALIDATOR_HTML_VALIDATION_ACTION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE = PropNames.VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE; + + /** + * Special {@code java.lang.System} property that, if set to {@code true}, will * disable logging from {@code DefaultSecurityConfiguration.logToStdout()} * methods, which is called from various {@code logSpecial()} methods. * @see org.owasp.esapi.reference.DefaultSecurityConfiguration#logToStdout(String msg, Throwable t) + * @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ - public static final String DISCARD_LOGSPECIAL = "org.owasp.esapi.logSpecial.discard"; + @Deprecated public static final String DISCARD_LOGSPECIAL = PropNames.DISCARD_LOGSPECIAL; // We assume that this does not change in the middle of processing the // ESAPI.properties files and thus only fetch its value once. - private static final String logSpecialValue = System.getProperty(DISCARD_LOGSPECIAL, "false"); + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated private static final String logSpecialValue = System.getProperty( PropNames.DISCARD_LOGSPECIAL, "false" ); protected final int MAX_REDIRECT_LOCATION = 1000; - + + /* * Implementation Keys */ - public static final String LOG_IMPLEMENTATION = "ESAPI.Logger"; - public static final String AUTHENTICATION_IMPLEMENTATION = "ESAPI.Authenticator"; - public static final String ENCODER_IMPLEMENTATION = "ESAPI.Encoder"; - public static final String ACCESS_CONTROL_IMPLEMENTATION = "ESAPI.AccessControl"; - public static final String ENCRYPTION_IMPLEMENTATION = "ESAPI.Encryptor"; - public static final String INTRUSION_DETECTION_IMPLEMENTATION = "ESAPI.IntrusionDetector"; - public static final String RANDOMIZER_IMPLEMENTATION = "ESAPI.Randomizer"; - public static final String EXECUTOR_IMPLEMENTATION = "ESAPI.Executor"; - public static final String VALIDATOR_IMPLEMENTATION = "ESAPI.Validator"; - public static final String HTTP_UTILITIES_IMPLEMENTATION = "ESAPI.HTTPUtilities"; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String LOG_IMPLEMENTATION = PropNames.LOG_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String AUTHENTICATION_IMPLEMENTATION = PropNames.AUTHENTICATION_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String ENCODER_IMPLEMENTATION = PropNames.ENCODER_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String ACCESS_CONTROL_IMPLEMENTATION = PropNames.ACCESS_CONTROL_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String ENCRYPTION_IMPLEMENTATION = PropNames.ENCRYPTION_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String INTRUSION_DETECTION_IMPLEMENTATION = PropNames.INTRUSION_DETECTION_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String RANDOMIZER_IMPLEMENTATION = PropNames.RANDOMIZER_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String EXECUTOR_IMPLEMENTATION = PropNames.EXECUTOR_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String VALIDATOR_IMPLEMENTATION = PropNames.VALIDATOR_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String HTTP_UTILITIES_IMPLEMENTATION = PropNames.HTTP_UTILITIES_IMPLEMENTATION; + /* * Default Implementations */ - public static final String DEFAULT_LOG_IMPLEMENTATION = "org.owasp.esapi.logging.java.JavaLogFactory"; - public static final String DEFAULT_AUTHENTICATION_IMPLEMENTATION = "org.owasp.esapi.reference.FileBasedAuthenticator"; - public static final String DEFAULT_ENCODER_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultEncoder"; - public static final String DEFAULT_ACCESS_CONTROL_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultAccessController"; - public static final String DEFAULT_ENCRYPTION_IMPLEMENTATION = "org.owasp.esapi.reference.crypto.JavaEncryptor"; - public static final String DEFAULT_INTRUSION_DETECTION_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultIntrusionDetector"; - public static final String DEFAULT_RANDOMIZER_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultRandomizer"; - public static final String DEFAULT_EXECUTOR_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultExecutor"; - public static final String DEFAULT_HTTP_UTILITIES_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultHTTPUtilities"; - public static final String DEFAULT_VALIDATOR_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultValidator"; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DEFAULT_LOG_IMPLEMENTATION = PropNames.DEFAULT_LOG_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DEFAULT_AUTHENTICATION_IMPLEMENTATION = PropNames.DEFAULT_AUTHENTICATION_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DEFAULT_ENCODER_IMPLEMENTATION = PropNames.DEFAULT_ENCODER_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DEFAULT_ACCESS_CONTROL_IMPLEMENTATION = PropNames.DEFAULT_ACCESS_CONTROL_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DEFAULT_ENCRYPTION_IMPLEMENTATION = PropNames.DEFAULT_ENCRYPTION_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DEFAULT_INTRUSION_DETECTION_IMPLEMENTATION = PropNames.DEFAULT_INTRUSION_DETECTION_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DEFAULT_RANDOMIZER_IMPLEMENTATION = PropNames.DEFAULT_RANDOMIZER_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DEFAULT_EXECUTOR_IMPLEMENTATION = PropNames.DEFAULT_EXECUTOR_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DEFAULT_HTTP_UTILITIES_IMPLEMENTATION = PropNames.DEFAULT_HTTP_UTILITIES_IMPLEMENTATION; + + /** @deprecated Use same field name, but from {@code org.owasp.esapi.PropNames} instead. */ + @Deprecated public static final String DEFAULT_VALIDATOR_IMPLEMENTATION = PropNames.DEFAULT_VALIDATOR_IMPLEMENTATION; private static final Map patternCache = new HashMap(); @@ -220,11 +373,10 @@ public static SecurityConfiguration getInstance() { private final String resourceFile; private EsapiPropertyManager esapiPropertyManager; -// private static long lastModified = -1; /** - * Instantiates a new configuration, using the provided property file name - * + * Instantiates a new configuration, using the provided property file name. + * * @param resourceFile The name of the property file to load */ DefaultSecurityConfiguration(String resourceFile) { @@ -239,13 +391,13 @@ public static SecurityConfiguration getInstance() { throw new ConfigurationException("Failed to load security configuration", e); } } - + /** * Instantiates a new configuration with the supplied properties. - * + * * Warning - if the setResourceDirectory() method is invoked the properties will * be re-loaded, replacing the supplied properties. - * + * * @param properties */ public DefaultSecurityConfiguration(Properties properties) { @@ -257,10 +409,10 @@ public DefaultSecurityConfiguration(Properties properties) { logSpecial("Failed to load security configuration", e ); throw new ConfigurationException("Failed to load security configuration", e); } - this.properties = properties; + this.properties = properties; this.setCipherXProperties(); } - + /** * Instantiates a new configuration. */ @@ -438,7 +590,7 @@ private Properties loadPropertiesFromStream( InputStream is, String name ) throw /** * Load configuration. Never prints properties. - * + * * @throws java.io.IOException * if the file is inaccessible */ @@ -447,34 +599,33 @@ protected void loadConfiguration() throws IOException { //first attempt file IO loading of properties logSpecial("Attempting to load " + resourceFile + " via file I/O."); properties = loadPropertiesFromStream(getResourceStream(resourceFile), resourceFile); - } catch (Exception iae) { //if file I/O loading fails, attempt classpath based loading next logSpecial("Loading " + resourceFile + " via file I/O failed. Exception was: " + iae); logSpecial("Attempting to load " + resourceFile + " via the classpath."); try { properties = loadConfigurationFromClasspath(resourceFile); - } catch (Exception e) { + } catch (Exception e) { logSpecial(resourceFile + " could not be loaded by any means. Fail.", e); throw new ConfigurationException(resourceFile + " could not be loaded by any means. Fail.", e); - } + } } - + // if properties loaded properly above, get validation properties and merge them into the main properties if (properties != null) { final Iterator validationPropFileNames; - + //defaults to single-valued for backwards compatibility final boolean multivalued= getESAPIProperty(VALIDATION_PROPERTIES_MULTIVALUED, false); final String validationPropValue = getESAPIProperty(VALIDATION_PROPERTIES, "validation.properties"); - + if(multivalued){ - // the following cast warning goes away if the apache commons lib is updated to current version + // the following cast warning goes away if the apache commons lib is updated to current version validationPropFileNames = StrTokenizer.getCSVInstance(validationPropValue); } else { validationPropFileNames = Collections.singletonList(validationPropValue).iterator(); } - + //clear any cached validation patterns so they can be reloaded from validation.properties patternCache.clear(); while(validationPropFileNames.hasNext()){ @@ -484,18 +635,17 @@ protected void loadConfiguration() throws IOException { //first attempt file IO loading of properties logSpecial("Attempting to load " + validationPropFileName + " via file I/O."); validationProperties = loadPropertiesFromStream(getResourceStream(validationPropFileName), validationPropFileName); - } catch (Exception iae) { //if file I/O loading fails, attempt classpath based loading next logSpecial("Loading " + validationPropFileName + " via file I/O failed."); - logSpecial("Attempting to load " + validationPropFileName + " via the classpath."); + logSpecial("Attempting to load " + validationPropFileName + " via the classpath."); try { validationProperties = loadConfigurationFromClasspath(validationPropFileName); - } catch (Exception e) { + } catch (Exception e) { logSpecial(validationPropFileName + " could not be loaded by any means. fail.", e); - } + } } - + if (validationProperties != null) { Iterator i = validationProperties.keySet().iterator(); while( i.hasNext() ) { @@ -504,27 +654,29 @@ protected void loadConfiguration() throws IOException { properties.put( key, value); } } - + if ( shouldPrintProperties() ) { - - //FIXME - make this chunk configurable - /* - logSpecial(" ========Master Configuration========", null); - //logSpecial( " ResourceDirectory: " + DefaultSecurityConfiguration.resourceDirectory ); - Iterator j = new TreeSet( properties.keySet() ).iterator(); - while (j.hasNext()) { - String key = (String)j.next(); - // print out properties, but not sensitive ones like MasterKey and MasterSalt - if ( !key.contains( "Master" ) ) { - logSpecial(" | " + key + "=" + properties.get(key), null); - } + // Gotta give them something. + logSpecial("DefaultSecurityConfiguration: The code to print all the properties is currently commented out"); + + //FIXME - make this chunk configurable + /* + logSpecial(" ========Master Configuration========", null); + //logSpecial( " ResourceDirectory: " + DefaultSecurityConfiguration.resourceDirectory ); + Iterator j = new TreeSet( properties.keySet() ).iterator(); + while (j.hasNext()) { + String key = (String)j.next(); + // print out properties, but not sensitive ones like MasterKey and MasterSalt + if ( !key.contains( "Master" ) ) { + logSpecial(" | " + key + "=" + properties.get(key), null); + } + } + */ } - */ - } } } - } - + } + /** * @param filename * @return An {@code InputStream} associated with the specified file name as @@ -547,7 +699,7 @@ public InputStream getResourceStream(String filename) throws IOException { throw new FileNotFoundException(); } - + /** * {@inheritDoc} */ @@ -623,9 +775,10 @@ public File getResourceFile(String filename) { // return null if not found return null; } - + /** - * Used to load ESAPI.properties from a variety of different classpath locations. + * Used to load ESAPI.properties from a variety of different classpath locations. The order is described in the + * class overview Javadoc for this class. * * @param fileName The properties file filename. */ @@ -636,7 +789,7 @@ private Properties loadConfigurationFromClasspath(String fileName) throws Illega ClassLoader[] loaders = new ClassLoader[] { Thread.currentThread().getContextClassLoader(), ClassLoader.getSystemClassLoader(), - getClass().getClassLoader() + getClass().getClassLoader() }; String[] classLoaderNames = { "current thread context class loader", @@ -658,7 +811,7 @@ private Properties loadConfigurationFromClasspath(String fileName) throws Illega // in = loaders[i].getResourceAsStream(fileName); // in = loaders[i].getResourceAsStream(DefaultSearchPath.ROOT.value() + fileName); - + // try resourceDirectory folder if (in == null) { currentClasspathSearchLocation = resourceDirectory + "/"; @@ -669,26 +822,26 @@ private Properties loadConfigurationFromClasspath(String fileName) throws Illega if (in == null) { currentClasspathSearchLocation = ".esapi/"; in = currentLoader.getResourceAsStream(DefaultSearchPath.DOT_ESAPI.value() + fileName); - } - + } + // try esapi folder (new directory) if (in == null) { currentClasspathSearchLocation = "esapi/"; in = currentLoader.getResourceAsStream(DefaultSearchPath.ESAPI.value() + fileName); - } - + } + // try resources folder if (in == null) { currentClasspathSearchLocation = "resources/"; in = currentLoader.getResourceAsStream(DefaultSearchPath.RESOURCES.value() + fileName); } - + // try src/main/resources folder if (in == null) { currentClasspathSearchLocation = "src/main/resources/"; in = currentLoader.getResourceAsStream(DefaultSearchPath.SRC_MAIN_RESOURCES.value() + fileName); } - + // now load the properties if (in != null) { result = new Properties(); @@ -699,7 +852,6 @@ private Properties loadConfigurationFromClasspath(String fileName) throws Illega } } catch (Exception e) { result = null; - } finally { try { in.close(); @@ -749,7 +901,7 @@ public final synchronized static void logToStdout(String msg, Throwable t) { "; exception message was: " + t); } } - + /** * Used to log errors to the console during the loading of the properties file itself. Can't use * standard logging in this case, since the Logger may not be initialized yet. Output is sent to @@ -834,7 +986,7 @@ public boolean useMACforCipherText() { public boolean overwritePlainText() { return getESAPIProperty(PLAINTEXT_OVERWRITE, true); } - + /** * {@inheritDoc} */ @@ -965,7 +1117,7 @@ public File getUploadTempDirectory() { ); return new File( dir ); } - + /** * {@inheritDoc} */ @@ -1064,7 +1216,7 @@ public String getResponseContentType() { public String getHttpSessionIdName() { return getESAPIProperty( HTTP_SESSION_ID_NAME, "JSESSIONID" ); } - + /** * {@inheritDoc} */ @@ -1126,13 +1278,13 @@ public File getWorkingDirectory() { } return null; } - + /** * {@inheritDoc} */ public String getPreferredJCEProvider() { return properties.getProperty(PREFERRED_JCE_PROVIDER); // No default! - } + } /** * {@inheritDoc} @@ -1151,7 +1303,7 @@ public List getAdditionalAllowedCipherModes() List empty = new ArrayList(); // Default is empty list return getESAPIProperty(ADDITIONAL_ALLOWED_CIPHER_MODES, empty); } - + /** * {@inheritDoc} */ @@ -1214,7 +1366,7 @@ protected int getESAPIProperty( String key, int def ) { /** * Returns a {@code List} representing the parsed, comma-separated property. - * + * * @param key The specified property name * @param def A default value for the property name to return if the property * is not set. @@ -1233,9 +1385,9 @@ protected List getESAPIProperty( String key, List def ) { /** * {@inheritDoc} * Looks for property in three configuration files in following order: - * 1.) In file defined as org.owasp.esapi.opsteam system property - * 2.) In file defined as org.owasp.esapi.devteam system property - * 3.) In ESAPI.properties* + * 1.) In file defined as org.owasp.esapi.opsteam system property + * 2.) In file defined as org.owasp.esapi.devteam system property + * 3.) In ESAPI.properties */ @Override public int getIntProp(String propertyName) throws ConfigurationException { @@ -1255,8 +1407,8 @@ public int getIntProp(String propertyName) throws ConfigurationException { /** * {@inheritDoc} * Looks for property in three configuration files in following order: - * 1.) In file defined as org.owasp.esapi.opsteam system property - * 2.) In file defined as org.owasp.esapi.devteam system property + * 1.) In file defined as org.owasp.esapi.opsteam system property + * 2.) In file defined as org.owasp.esapi.devteam system property * 3.) In ESAPI.properties */ @Override @@ -1278,10 +1430,10 @@ public byte[] getByteArrayProp(String propertyName) throws ConfigurationExceptio } /** - * {@inheritDoc} + * {@inheritDoc} * Looks for property in three configuration files in following order: - * 1.) In file defined as org.owasp.esapi.opsteam system property - * 2.) In file defined as org.owasp.esapi.devteam system property + * 1.) In file defined as org.owasp.esapi.opsteam system property + * 2.) In file defined as org.owasp.esapi.devteam system property * 3.) In ESAPI.properties */ @Override @@ -1332,24 +1484,4 @@ protected boolean shouldPrintProperties() { protected Properties getESAPIProperties() { return properties; } - - public enum DefaultSearchPath { - - RESOURCE_DIRECTORY("resourceDirectory/"), - SRC_MAIN_RESOURCES("src/main/resources/"), - ROOT(""), - DOT_ESAPI(".esapi/"), - ESAPI("esapi/"), - RESOURCES("resources/"); - - private final String path; - - private DefaultSearchPath(String s){ - this.path = s; - } - - public String value(){ - return path; - } - } } From acae408f64be2eafc8b0d7b505f7e7420a8eedc4 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sun, 29 May 2022 23:28:06 -0400 Subject: [PATCH 006/197] Issue #620 - changed DefaultSecurityConfiguration refs to PropNames. --- .../esapi/crypto/KeyDerivationFunction.java | 7 +- .../errors/EnterpriseSecurityException.java | 7 +- .../esapi/logging/java/JavaLogFactory.java | 21 +++-- .../esapi/logging/log4j/Log4JLogFactory.java | 21 +++-- .../logging/log4j/Log4JLoggerFactory.java | 20 +++-- .../esapi/logging/slf4j/Slf4JLogFactory.java | 20 +++-- .../validation/HTMLValidationRule.java | 19 ++-- .../filters/SecurityWrapperRequestTest.java | 3 +- .../filters/SecurityWrapperResponseTest.java | 2 +- .../DefaultSecurityConfigurationTest.java | 88 ++++++++++--------- .../validation/DateValidationRuleTest.java | 4 +- .../HTMLValidationRuleClasspathTest.java | 6 +- .../HTMLValidationRuleCleanTest.java | 3 +- .../HTMLValidationRuleThrowsTest.java | 3 +- 14 files changed, 124 insertions(+), 100 deletions(-) diff --git a/src/main/java/org/owasp/esapi/crypto/KeyDerivationFunction.java b/src/main/java/org/owasp/esapi/crypto/KeyDerivationFunction.java index cc50b5ee8..51032eec7 100644 --- a/src/main/java/org/owasp/esapi/crypto/KeyDerivationFunction.java +++ b/src/main/java/org/owasp/esapi/crypto/KeyDerivationFunction.java @@ -21,7 +21,7 @@ import org.owasp.esapi.Logger; import org.owasp.esapi.errors.ConfigurationException; import org.owasp.esapi.errors.EncryptionException; -import org.owasp.esapi.reference.DefaultSecurityConfiguration; +import static org.owasp.esapi.PropNames.KDF_PRF_ALG; import org.owasp.esapi.util.ByteConversionUtil; /** @@ -133,7 +133,7 @@ public KeyDerivationFunction() { if ( ! KeyDerivationFunction.isValidPRF(prfName) ) { throw new ConfigurationException("Algorithm name " + prfName + " not a valid algorithm name for property " + - DefaultSecurityConfiguration.KDF_PRF_ALG); + KDF_PRF_ALG); } prfAlg_ = prfName; } @@ -159,8 +159,7 @@ static int getDefaultPRFSelection() { } } throw new ConfigurationException("Algorithm name " + prfName + - " not a valid algorithm name for property " + - DefaultSecurityConfiguration.KDF_PRF_ALG); + " not a valid algorithm name for property " + KDF_PRF_ALG); } /** diff --git a/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityException.java b/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityException.java index 1be227524..4e05d0cf7 100644 --- a/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityException.java +++ b/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityException.java @@ -18,12 +18,7 @@ import org.owasp.esapi.ESAPI; import org.owasp.esapi.Logger; -// At some point, all these property names will be moved to a new class named -// org.owasp.esapi.PropNames -// but until then, while this is an ugly kludge, we are importing it via a -// reference implementation class until we have a chance to clean it up. -// (Note: kwwall's Bitbucket code already has that class.) -import static org.owasp.esapi.reference.DefaultSecurityConfiguration.DISABLE_INTRUSION_DETECTION; +import static org.owasp.esapi.PropNames.DISABLE_INTRUSION_DETECTION; /** diff --git a/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java b/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java index 016c37dde..038d19b5e 100644 --- a/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java +++ b/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java @@ -33,7 +33,14 @@ import org.owasp.esapi.logging.cleaning.CompositeLogScrubber; import org.owasp.esapi.logging.cleaning.LogScrubber; import org.owasp.esapi.logging.cleaning.NewlineLogScrubber; -import org.owasp.esapi.reference.DefaultSecurityConfiguration; + +import static org.owasp.esapi.PropNames.LOG_ENCODING_REQUIRED; +import static org.owasp.esapi.PropNames.LOG_USER_INFO; +import static org.owasp.esapi.PropNames.LOG_CLIENT_INFO; +import static org.owasp.esapi.PropNames.LOG_APPLICATION_NAME; +import static org.owasp.esapi.PropNames.APPLICATION_NAME; +import static org.owasp.esapi.PropNames.LOG_SERVER_IP; + /** * LogFactory implementation which creates JAVA supporting Loggers. * @@ -55,15 +62,15 @@ public class JavaLogFactory implements LogFactory { private static JavaLogBridge LOG_BRIDGE; static { - boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_ENCODING_REQUIRED); + boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(LOG_ENCODING_REQUIRED); JAVA_LOG_SCRUBBER = createLogScrubber(encodeLog); - boolean logUserInfo = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_USER_INFO); - boolean logClientInfo = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_CLIENT_INFO); - boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_APPLICATION_NAME); - String appName = ESAPI.securityConfiguration().getStringProp(DefaultSecurityConfiguration.APPLICATION_NAME); - boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_SERVER_IP); + boolean logUserInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_USER_INFO); + boolean logClientInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_CLIENT_INFO); + boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(LOG_APPLICATION_NAME); + String appName = ESAPI.securityConfiguration().getStringProp(APPLICATION_NAME); + boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(LOG_SERVER_IP); JAVA_LOG_APPENDER = createLogAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); Map levelLookup = new HashMap<>(); diff --git a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogFactory.java b/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogFactory.java index 0f318600a..a71cf3141 100644 --- a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogFactory.java +++ b/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogFactory.java @@ -29,7 +29,14 @@ import org.owasp.esapi.logging.cleaning.CompositeLogScrubber; import org.owasp.esapi.logging.cleaning.LogScrubber; import org.owasp.esapi.logging.cleaning.NewlineLogScrubber; -import org.owasp.esapi.reference.DefaultSecurityConfiguration; + +import static org.owasp.esapi.PropNames.LOG_ENCODING_REQUIRED; +import static org.owasp.esapi.PropNames.LOG_USER_INFO; +import static org.owasp.esapi.PropNames.LOG_CLIENT_INFO; +import static org.owasp.esapi.PropNames.LOG_APPLICATION_NAME; +import static org.owasp.esapi.PropNames.APPLICATION_NAME; +import static org.owasp.esapi.PropNames.LOG_SERVER_IP; + /** * LogFactory implementation which creates Log4J supporting Loggers. * @@ -48,15 +55,15 @@ public class Log4JLogFactory implements LogFactory { private static Log4JLogBridge LOG_BRIDGE; static { - boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_ENCODING_REQUIRED); + boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(LOG_ENCODING_REQUIRED); Log4J_LOG_SCRUBBER = createLogScrubber(encodeLog); - boolean logUserInfo = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_USER_INFO); - boolean logClientInfo = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_CLIENT_INFO); - boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_APPLICATION_NAME); - String appName = ESAPI.securityConfiguration().getStringProp(DefaultSecurityConfiguration.APPLICATION_NAME); - boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_SERVER_IP); + boolean logUserInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_USER_INFO); + boolean logClientInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_CLIENT_INFO); + boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(LOG_APPLICATION_NAME); + String appName = ESAPI.securityConfiguration().getStringProp(APPLICATION_NAME); + boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(LOG_SERVER_IP); Log4J_LOG_APPENDER = createLogAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); Map levelLookup = new HashMap<>(); diff --git a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactory.java b/src/main/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactory.java index 931ae6267..91dd0da4f 100644 --- a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactory.java +++ b/src/main/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactory.java @@ -20,7 +20,13 @@ import org.owasp.esapi.ESAPI; import org.owasp.esapi.logging.appender.LogAppender; import org.owasp.esapi.logging.cleaning.LogScrubber; -import org.owasp.esapi.reference.DefaultSecurityConfiguration; + +import static org.owasp.esapi.PropNames.LOG_ENCODING_REQUIRED; +import static org.owasp.esapi.PropNames.LOG_USER_INFO; +import static org.owasp.esapi.PropNames.LOG_CLIENT_INFO; +import static org.owasp.esapi.PropNames.LOG_APPLICATION_NAME; +import static org.owasp.esapi.PropNames.APPLICATION_NAME; +import static org.owasp.esapi.PropNames.LOG_SERVER_IP; /** * Service Provider Interface implementation that can be provided as the org.apache.log4j.spi.LoggerFactory reference in a Log4J configuration. @@ -37,14 +43,14 @@ public class Log4JLoggerFactory implements LoggerFactory { private static LogScrubber LOG4J_LOG_SCRUBBER; static { - boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_ENCODING_REQUIRED); + boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(LOG_ENCODING_REQUIRED); LOG4J_LOG_SCRUBBER = Log4JLogFactory.createLogScrubber(encodeLog); - boolean logUserInfo = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_USER_INFO); - boolean logClientInfo = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_CLIENT_INFO); - boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_APPLICATION_NAME); - String appName = ESAPI.securityConfiguration().getStringProp(DefaultSecurityConfiguration.APPLICATION_NAME); - boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_SERVER_IP); + boolean logUserInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_USER_INFO); + boolean logClientInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_CLIENT_INFO); + boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(LOG_APPLICATION_NAME); + String appName = ESAPI.securityConfiguration().getStringProp(APPLICATION_NAME); + boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(LOG_SERVER_IP); LOG4J_LOG_APPENDER = Log4JLogFactory.createLogAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); } diff --git a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java index 85341b2df..d2e6c6305 100644 --- a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java +++ b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java @@ -29,7 +29,13 @@ import org.owasp.esapi.logging.cleaning.CompositeLogScrubber; import org.owasp.esapi.logging.cleaning.LogScrubber; import org.owasp.esapi.logging.cleaning.NewlineLogScrubber; -import org.owasp.esapi.reference.DefaultSecurityConfiguration; + +import static org.owasp.esapi.PropNames.LOG_ENCODING_REQUIRED; +import static org.owasp.esapi.PropNames.LOG_USER_INFO; +import static org.owasp.esapi.PropNames.LOG_CLIENT_INFO; +import static org.owasp.esapi.PropNames.LOG_APPLICATION_NAME; +import static org.owasp.esapi.PropNames.APPLICATION_NAME; +import static org.owasp.esapi.PropNames.LOG_SERVER_IP; import org.slf4j.LoggerFactory; /** * LogFactory implementation which creates SLF4J supporting Loggers. @@ -54,15 +60,15 @@ public class Slf4JLogFactory implements LogFactory { private static Slf4JLogBridge LOG_BRIDGE; static { - boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_ENCODING_REQUIRED); + boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(LOG_ENCODING_REQUIRED); SLF4J_LOG_SCRUBBER = createLogScrubber(encodeLog); - boolean logUserInfo = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_USER_INFO); - boolean logClientInfo = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_CLIENT_INFO); - boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_APPLICATION_NAME); - String appName = ESAPI.securityConfiguration().getStringProp(DefaultSecurityConfiguration.APPLICATION_NAME); - boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_SERVER_IP); + boolean logUserInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_USER_INFO); + boolean logClientInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_CLIENT_INFO); + boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(LOG_APPLICATION_NAME); + String appName = ESAPI.securityConfiguration().getStringProp(APPLICATION_NAME); + boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(LOG_SERVER_IP); SLF4J_LOG_APPENDER = createLogAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); Map levelLookup = new HashMap<>(); diff --git a/src/main/java/org/owasp/esapi/reference/validation/HTMLValidationRule.java b/src/main/java/org/owasp/esapi/reference/validation/HTMLValidationRule.java index 41e60e697..e813a0222 100644 --- a/src/main/java/org/owasp/esapi/reference/validation/HTMLValidationRule.java +++ b/src/main/java/org/owasp/esapi/reference/validation/HTMLValidationRule.java @@ -30,7 +30,10 @@ import org.owasp.esapi.StringUtilities; import org.owasp.esapi.errors.ConfigurationException; import org.owasp.esapi.errors.ValidationException; -import org.owasp.esapi.reference.DefaultSecurityConfiguration.DefaultSearchPath; +import org.owasp.esapi.PropNames.DefaultSearchPath; +import static org.owasp.esapi.PropNames.VALIDATOR_HTML_VALIDATION_ACTION; +import static org.owasp.esapi.PropNames.VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE; + import org.owasp.validator.html.AntiSamy; import org.owasp.validator.html.CleanResults; import org.owasp.validator.html.Policy; @@ -106,13 +109,11 @@ public class HTMLValidationRule extends StringValidationRule { /*package */ static String resolveAntisamyFilename() { String antisamyPolicyFilename = ANTISAMYPOLICY_FILENAME; try { - antisamyPolicyFilename = ESAPI.securityConfiguration().getStringProp( - // Future: This will be moved to a new PropNames class - org.owasp.esapi.reference.DefaultSecurityConfiguration.VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE ); + antisamyPolicyFilename = ESAPI.securityConfiguration().getStringProp( VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE ); } catch (ConfigurationException cex) { LOGGER.info(Logger.EVENT_FAILURE, "ESAPI property " + - org.owasp.esapi.reference.DefaultSecurityConfiguration.VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE + + VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE + " not set, using default value: " + ANTISAMYPOLICY_FILENAME); } return antisamyPolicyFilename; @@ -197,9 +198,7 @@ private boolean legacyHtmlValidation() { // Hindsight: maybe we should have getBooleanProp(), getStringProp(), // getIntProp() methods that take a default arg as well? // At least for ESAPI 3.x. - propValue = ESAPI.securityConfiguration().getStringProp( - // Future: This will be moved to a new PropNames class - org.owasp.esapi.reference.DefaultSecurityConfiguration.VALIDATOR_HTML_VALIDATION_ACTION ); + propValue = ESAPI.securityConfiguration().getStringProp( VALIDATOR_HTML_VALIDATION_ACTION ); switch ( propValue.toLowerCase() ) { case "throw": legacy = false; // New, presumably correct behavior, as addressed by GitHub issue 509 @@ -209,7 +208,7 @@ private boolean legacyHtmlValidation() { break; default: LOGGER.warning(Logger.EVENT_FAILURE, "ESAPI property " + - org.owasp.esapi.reference.DefaultSecurityConfiguration.VALIDATOR_HTML_VALIDATION_ACTION + + VALIDATOR_HTML_VALIDATION_ACTION + " was set to \"" + propValue + "\". Must be set to either \"clean\"" + " (the default for legacy support) or \"throw\"; assuming \"clean\" for legacy behavior."); legacy = true; @@ -219,7 +218,7 @@ private boolean legacyHtmlValidation() { // OPEN ISSUE: Should we log this? I think so. Convince me otherwise. But maybe // we should only log it once or every Nth time?? LOGGER.warning(Logger.EVENT_FAILURE, "ESAPI property " + - org.owasp.esapi.reference.DefaultSecurityConfiguration.VALIDATOR_HTML_VALIDATION_ACTION + + VALIDATOR_HTML_VALIDATION_ACTION + " must be set to either \"clean\" (the default for legacy support) or \"throw\"; assuming \"clean\"", cex); } diff --git a/src/test/java/org/owasp/esapi/filters/SecurityWrapperRequestTest.java b/src/test/java/org/owasp/esapi/filters/SecurityWrapperRequestTest.java index d7faddb8a..e7ee596e0 100644 --- a/src/test/java/org/owasp/esapi/filters/SecurityWrapperRequestTest.java +++ b/src/test/java/org/owasp/esapi/filters/SecurityWrapperRequestTest.java @@ -22,8 +22,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -// A hack for now; eventually, I plan to move this into a new org.owasp.esapi.PropNames class. -kww -import static org.owasp.esapi.reference.DefaultSecurityConfiguration.DISABLE_INTRUSION_DETECTION; +import static org.owasp.esapi.PropNames.DISABLE_INTRUSION_DETECTION; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; diff --git a/src/test/java/org/owasp/esapi/filters/SecurityWrapperResponseTest.java b/src/test/java/org/owasp/esapi/filters/SecurityWrapperResponseTest.java index 499da8799..951a57e5b 100644 --- a/src/test/java/org/owasp/esapi/filters/SecurityWrapperResponseTest.java +++ b/src/test/java/org/owasp/esapi/filters/SecurityWrapperResponseTest.java @@ -6,7 +6,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.owasp.esapi.reference.DefaultSecurityConfiguration.DISABLE_INTRUSION_DETECTION; +import static org.owasp.esapi.PropNames.DISABLE_INTRUSION_DETECTION; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; diff --git a/src/test/java/org/owasp/esapi/reference/DefaultSecurityConfigurationTest.java b/src/test/java/org/owasp/esapi/reference/DefaultSecurityConfigurationTest.java index 6fd6d3ef4..225a8b117 100644 --- a/src/test/java/org/owasp/esapi/reference/DefaultSecurityConfigurationTest.java +++ b/src/test/java/org/owasp/esapi/reference/DefaultSecurityConfigurationTest.java @@ -16,7 +16,9 @@ import org.owasp.esapi.Logger; import org.owasp.esapi.SecurityConfiguration; import org.owasp.esapi.errors.ConfigurationException; -import org.owasp.esapi.reference.DefaultSecurityConfiguration.DefaultSearchPath; +import org.owasp.esapi.PropNames.DefaultSearchPath; + +import static org.owasp.esapi.PropNames.*; public class DefaultSecurityConfigurationTest { @@ -29,7 +31,7 @@ private DefaultSecurityConfiguration createWithProperty(String key, String val) @Test public void testGetApplicationName() { final String expected = "ESAPI_UnitTests"; - DefaultSecurityConfiguration secConf = this.createWithProperty(DefaultSecurityConfiguration.APPLICATION_NAME, expected); + DefaultSecurityConfiguration secConf = this.createWithProperty(APPLICATION_NAME, expected); assertEquals(expected, secConf.getApplicationName()); } @@ -37,10 +39,10 @@ public void testGetApplicationName() { public void testGetLogImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); - assertEquals(DefaultSecurityConfiguration.DEFAULT_LOG_IMPLEMENTATION, secConf.getLogImplementation()); + assertEquals(DEFAULT_LOG_IMPLEMENTATION, secConf.getLogImplementation()); final String expected = "TestLogger"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.LOG_IMPLEMENTATION, expected); + secConf = this.createWithProperty(LOG_IMPLEMENTATION, expected); assertEquals(expected, secConf.getLogImplementation()); } @@ -48,10 +50,10 @@ public void testGetLogImplementation() { public void testAuthenticationImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); - assertEquals(DefaultSecurityConfiguration.DEFAULT_AUTHENTICATION_IMPLEMENTATION, secConf.getAuthenticationImplementation()); + assertEquals(DEFAULT_AUTHENTICATION_IMPLEMENTATION, secConf.getAuthenticationImplementation()); final String expected = "TestAuthentication"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.AUTHENTICATION_IMPLEMENTATION, expected); + secConf = this.createWithProperty(AUTHENTICATION_IMPLEMENTATION, expected); assertEquals(expected, secConf.getAuthenticationImplementation()); } @@ -59,10 +61,10 @@ public void testAuthenticationImplementation() { public void testEncoderImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); - assertEquals(DefaultSecurityConfiguration.DEFAULT_ENCODER_IMPLEMENTATION, secConf.getEncoderImplementation()); + assertEquals(DEFAULT_ENCODER_IMPLEMENTATION, secConf.getEncoderImplementation()); final String expected = "TestEncoder"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.ENCODER_IMPLEMENTATION, expected); + secConf = this.createWithProperty(ENCODER_IMPLEMENTATION, expected); assertEquals(expected, secConf.getEncoderImplementation()); } @@ -70,10 +72,10 @@ public void testEncoderImplementation() { public void testAccessControlImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); - assertEquals(DefaultSecurityConfiguration.DEFAULT_ACCESS_CONTROL_IMPLEMENTATION, secConf.getAccessControlImplementation()); + assertEquals(DEFAULT_ACCESS_CONTROL_IMPLEMENTATION, secConf.getAccessControlImplementation()); final String expected = "TestAccessControl"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.ACCESS_CONTROL_IMPLEMENTATION, expected); + secConf = this.createWithProperty(ACCESS_CONTROL_IMPLEMENTATION, expected); assertEquals(expected, secConf.getAccessControlImplementation()); } @@ -81,10 +83,10 @@ public void testAccessControlImplementation() { public void testEncryptionImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); - assertEquals(DefaultSecurityConfiguration.DEFAULT_ENCRYPTION_IMPLEMENTATION, secConf.getEncryptionImplementation()); + assertEquals(DEFAULT_ENCRYPTION_IMPLEMENTATION, secConf.getEncryptionImplementation()); final String expected = "TestEncryption"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.ENCRYPTION_IMPLEMENTATION, expected); + secConf = this.createWithProperty(ENCRYPTION_IMPLEMENTATION, expected); assertEquals(expected, secConf.getEncryptionImplementation()); } @@ -92,10 +94,10 @@ public void testEncryptionImplementation() { public void testIntrusionDetectionImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); - assertEquals(DefaultSecurityConfiguration.DEFAULT_INTRUSION_DETECTION_IMPLEMENTATION, secConf.getIntrusionDetectionImplementation()); + assertEquals(DEFAULT_INTRUSION_DETECTION_IMPLEMENTATION, secConf.getIntrusionDetectionImplementation()); final String expected = "TestIntrusionDetection"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.INTRUSION_DETECTION_IMPLEMENTATION, expected); + secConf = this.createWithProperty(INTRUSION_DETECTION_IMPLEMENTATION, expected); assertEquals(expected, secConf.getIntrusionDetectionImplementation()); } @@ -103,10 +105,10 @@ public void testIntrusionDetectionImplementation() { public void testRandomizerImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); - assertEquals(DefaultSecurityConfiguration.DEFAULT_RANDOMIZER_IMPLEMENTATION, secConf.getRandomizerImplementation()); + assertEquals(DEFAULT_RANDOMIZER_IMPLEMENTATION, secConf.getRandomizerImplementation()); final String expected = "TestRandomizer"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.RANDOMIZER_IMPLEMENTATION, expected); + secConf = this.createWithProperty(RANDOMIZER_IMPLEMENTATION, expected); assertEquals(expected, secConf.getRandomizerImplementation()); } @@ -114,10 +116,10 @@ public void testRandomizerImplementation() { public void testExecutorImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); - assertEquals(DefaultSecurityConfiguration.DEFAULT_EXECUTOR_IMPLEMENTATION, secConf.getExecutorImplementation()); + assertEquals(DEFAULT_EXECUTOR_IMPLEMENTATION, secConf.getExecutorImplementation()); final String expected = "TestExecutor"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.EXECUTOR_IMPLEMENTATION, expected); + secConf = this.createWithProperty(EXECUTOR_IMPLEMENTATION, expected); assertEquals(expected, secConf.getExecutorImplementation()); } @@ -125,10 +127,10 @@ public void testExecutorImplementation() { public void testHTTPUtilitiesImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); - assertEquals(DefaultSecurityConfiguration.DEFAULT_HTTP_UTILITIES_IMPLEMENTATION, secConf.getHTTPUtilitiesImplementation()); + assertEquals(DEFAULT_HTTP_UTILITIES_IMPLEMENTATION, secConf.getHTTPUtilitiesImplementation()); final String expected = "TestHTTPUtilities"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.HTTP_UTILITIES_IMPLEMENTATION, expected); + secConf = this.createWithProperty(HTTP_UTILITIES_IMPLEMENTATION, expected); assertEquals(expected, secConf.getHTTPUtilitiesImplementation()); } @@ -136,10 +138,10 @@ public void testHTTPUtilitiesImplementation() { public void testValidationImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); - assertEquals(DefaultSecurityConfiguration.DEFAULT_VALIDATOR_IMPLEMENTATION, secConf.getValidationImplementation()); + assertEquals(DEFAULT_VALIDATOR_IMPLEMENTATION, secConf.getValidationImplementation()); final String expected = "TestValidation"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.VALIDATOR_IMPLEMENTATION, expected); + secConf = this.createWithProperty(VALIDATOR_IMPLEMENTATION, expected); assertEquals(expected, secConf.getValidationImplementation()); } @@ -150,7 +152,7 @@ public void testGetEncryptionKeyLength() { assertEquals(128, secConf.getEncryptionKeyLength()); final int expected = 256; - secConf = this.createWithProperty(DefaultSecurityConfiguration.KEY_LENGTH, String.valueOf(expected)); + secConf = this.createWithProperty(KEY_LENGTH, String.valueOf(expected)); assertEquals(expected, secConf.getEncryptionKeyLength()); } @@ -161,7 +163,7 @@ public void testGetKDFPseudoRandomFunction() { assertEquals("HmacSHA256", secConf.getKDFPseudoRandomFunction()); final String expected = "HmacSHA1"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.KDF_PRF_ALG, expected); + secConf = this.createWithProperty(KDF_PRF_ALG, expected); assertEquals(expected, secConf.getKDFPseudoRandomFunction()); } @@ -179,7 +181,7 @@ public void testGetMasterSalt() { final String salt = "53081"; final String property = ESAPI.encoder().encodeForBase64(salt.getBytes(), false); Properties properties = new Properties(); - properties.setProperty(DefaultSecurityConfiguration.MASTER_SALT, property); + properties.setProperty(MASTER_SALT, property); DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(properties); assertEquals(salt, new String(secConf.getMasterSalt())); } @@ -195,7 +197,7 @@ public void testGetAllowedExecutables() { Properties properties = new Properties(); - properties.setProperty(DefaultSecurityConfiguration.APPROVED_EXECUTABLES, String.valueOf("/bin/bzip2,/bin/diff, /bin/cvs")); + properties.setProperty(APPROVED_EXECUTABLES, String.valueOf("/bin/bzip2,/bin/diff, /bin/cvs")); secConf = new DefaultSecurityConfiguration(properties); allowedExecutables = secConf.getAllowedExecutables(); assertEquals(3, allowedExecutables.size()); @@ -216,7 +218,7 @@ public void testGetAllowedFileExtensions() { Properties properties = new Properties(); - properties.setProperty(DefaultSecurityConfiguration.APPROVED_UPLOAD_EXTENSIONS, String.valueOf(".txt,.xml,.html,.png")); + properties.setProperty(APPROVED_UPLOAD_EXTENSIONS, String.valueOf(".txt,.xml,.html,.png")); secConf = new DefaultSecurityConfiguration(properties); allowedFileExtensions = secConf.getAllowedFileExtensions(); assertEquals(4, allowedFileExtensions.size()); @@ -230,7 +232,7 @@ public void testGetAllowedFileUploadSize() { assertTrue(secConf.getAllowedFileUploadSize() > (1024 * 100)); final int expected = (1024 * 1000); - secConf = this.createWithProperty(DefaultSecurityConfiguration.MAX_UPLOAD_FILE_BYTES, String.valueOf(expected)); + secConf = this.createWithProperty(MAX_UPLOAD_FILE_BYTES, String.valueOf(expected)); assertEquals(expected, secConf.getAllowedFileUploadSize()); } @@ -242,8 +244,8 @@ public void testGetParameterNames() { assertEquals("username", secConf.getUsernameParameterName()); Properties properties = new Properties(); - properties.setProperty(DefaultSecurityConfiguration.PASSWORD_PARAMETER_NAME, "j_password"); - properties.setProperty(DefaultSecurityConfiguration.USERNAME_PARAMETER_NAME, "j_username"); + properties.setProperty(PASSWORD_PARAMETER_NAME, "j_password"); + properties.setProperty(USERNAME_PARAMETER_NAME, "j_username"); secConf = new DefaultSecurityConfiguration(properties); assertEquals("j_password", secConf.getPasswordParameterName()); assertEquals("j_username", secConf.getUsernameParameterName()); @@ -255,7 +257,7 @@ public void testGetEncryptionAlgorithm() { DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals("AES", secConf.getEncryptionAlgorithm()); - secConf = this.createWithProperty(DefaultSecurityConfiguration.ENCRYPTION_ALGORITHM, "3DES"); + secConf = this.createWithProperty(ENCRYPTION_ALGORITHM, "3DES"); assertEquals("3DES", secConf.getEncryptionAlgorithm()); } @@ -266,7 +268,7 @@ public void testGetCipherXProperties() { //assertEquals("AES/CBC/PKCS5Padding", secConf.getC); Properties properties = new Properties(); - properties.setProperty(DefaultSecurityConfiguration.CIPHER_TRANSFORMATION_IMPLEMENTATION, "Blowfish/CFB/ISO10126Padding"); + properties.setProperty(CIPHER_TRANSFORMATION_IMPLEMENTATION, "Blowfish/CFB/ISO10126Padding"); secConf = new DefaultSecurityConfiguration(properties); assertEquals("Blowfish/CFB/ISO10126Padding", secConf.getCipherTransformation()); @@ -285,18 +287,18 @@ public void testIV() { Properties props = new Properties(); String ivType = null; - props.setProperty(DefaultSecurityConfiguration.IV_TYPE, "fixed"); // No longer supported. + props.setProperty(IV_TYPE, "fixed"); // No longer supported. secConf = new DefaultSecurityConfiguration( props ); try { ivType = secConf.getIVType(); // This should now throw a Configuration Exception. - fail("Expected ConfigurationException to be thrown for " + DefaultSecurityConfiguration.IV_TYPE + "=" + ivType); + fail("Expected ConfigurationException to be thrown for " + IV_TYPE + "=" + ivType); } catch (ConfigurationException ce) { assertNotNull(ce.getMessage()); } - props.setProperty(DefaultSecurityConfiguration.IV_TYPE, "illegal"); // This will just result in a logSpecial message & "random" is returned. + props.setProperty(IV_TYPE, "illegal"); // This will just result in a logSpecial message & "random" is returned. secConf = new DefaultSecurityConfiguration(props); ivType = secConf.getIVType(); assertEquals(ivType, "random"); @@ -307,13 +309,13 @@ public void testGetAllowMultipleEncoding() { DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertFalse(secConf.getAllowMultipleEncoding()); - secConf = this.createWithProperty(DefaultSecurityConfiguration.ALLOW_MULTIPLE_ENCODING, "yes"); + secConf = this.createWithProperty(ALLOW_MULTIPLE_ENCODING, "yes"); assertTrue(secConf.getAllowMultipleEncoding()); - secConf = this.createWithProperty(DefaultSecurityConfiguration.ALLOW_MULTIPLE_ENCODING, "true"); + secConf = this.createWithProperty(ALLOW_MULTIPLE_ENCODING, "true"); assertTrue(secConf.getAllowMultipleEncoding()); - secConf = this.createWithProperty(DefaultSecurityConfiguration.ALLOW_MULTIPLE_ENCODING, "no"); + secConf = this.createWithProperty(ALLOW_MULTIPLE_ENCODING, "no"); assertFalse(secConf.getAllowMultipleEncoding()); } @@ -323,7 +325,7 @@ public void testGetDefaultCanonicalizationCodecs() { assertFalse(secConf.getDefaultCanonicalizationCodecs().isEmpty()); String property = "org.owasp.esapi.codecs.TestCodec1,org.owasp.esapi.codecs.TestCodec2"; - secConf = this.createWithProperty(DefaultSecurityConfiguration.CANONICALIZATION_CODECS, property); + secConf = this.createWithProperty(CANONICALIZATION_CODECS, property); assertTrue(secConf.getDefaultCanonicalizationCodecs().contains("org.owasp.esapi.codecs.TestCodec1")); } @@ -332,13 +334,13 @@ public void testGetDisableIntrusionDetection() { DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertFalse(secConf.getDisableIntrusionDetection()); - secConf = this.createWithProperty(DefaultSecurityConfiguration.DISABLE_INTRUSION_DETECTION, "TRUE"); + secConf = this.createWithProperty(DISABLE_INTRUSION_DETECTION, "TRUE"); assertTrue(secConf.getDisableIntrusionDetection()); - secConf = this.createWithProperty(DefaultSecurityConfiguration.DISABLE_INTRUSION_DETECTION, "true"); + secConf = this.createWithProperty(DISABLE_INTRUSION_DETECTION, "true"); assertTrue(secConf.getDisableIntrusionDetection()); - secConf = this.createWithProperty(DefaultSecurityConfiguration.DISABLE_INTRUSION_DETECTION, "false"); + secConf = this.createWithProperty(DISABLE_INTRUSION_DETECTION, "false"); assertFalse(secConf.getDisableIntrusionDetection()); } @@ -482,7 +484,7 @@ public void testDeprecatedMethods() { assertTrue("1: Deprecated (1st) method returns different value than new (2nd) method", ESAPI.securityConfiguration().getDisableIntrusionDetection() == - ESAPI.securityConfiguration().getBooleanProp( DefaultSecurityConfiguration.DISABLE_INTRUSION_DETECTION ) + ESAPI.securityConfiguration().getBooleanProp( DISABLE_INTRUSION_DETECTION ) ); // TODO: add some more tests here for the deprecated replacements. } diff --git a/src/test/java/org/owasp/esapi/reference/validation/DateValidationRuleTest.java b/src/test/java/org/owasp/esapi/reference/validation/DateValidationRuleTest.java index 3e25597d5..a289c77ec 100644 --- a/src/test/java/org/owasp/esapi/reference/validation/DateValidationRuleTest.java +++ b/src/test/java/org/owasp/esapi/reference/validation/DateValidationRuleTest.java @@ -23,9 +23,9 @@ import org.owasp.esapi.ValidationErrorList; import org.owasp.esapi.errors.ValidationException; import org.owasp.esapi.reference.DefaultSecurityConfiguration; +import static org.owasp.esapi.PropNames.ACCEPT_LENIENT_DATES; import org.powermock.reflect.Whitebox; - public class DateValidationRuleTest { @Rule @@ -74,7 +74,7 @@ public void testsetDateFormatNullThrows() { @Test public void testsetDateFormat() { - boolean acceptLenient = ESAPI.securityConfiguration().getBooleanProp( DefaultSecurityConfiguration.ACCEPT_LENIENT_DATES); + boolean acceptLenient = ESAPI.securityConfiguration().getBooleanProp( ACCEPT_LENIENT_DATES ); DateFormat newFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US); newFormat.setLenient(!acceptLenient); diff --git a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleClasspathTest.java b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleClasspathTest.java index c05f9f236..3287f8348 100644 --- a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleClasspathTest.java +++ b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleClasspathTest.java @@ -32,6 +32,8 @@ import org.owasp.esapi.Validator; import org.owasp.esapi.errors.ValidationException; import org.owasp.validator.html.PolicyException; +import static org.owasp.esapi.PropNames.VALIDATOR_HTML_VALIDATION_ACTION; +import static org.owasp.esapi.PropNames.VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE; /** * The Class HTMLValidationRuleThrowsTest. @@ -72,9 +74,9 @@ private static class ConfOverride extends SecurityConfigurationWrapper { @Override public String getStringProp(String propName) { // Would it be better making this file a static import? - if ( propName.equals( org.owasp.esapi.reference.DefaultSecurityConfiguration.VALIDATOR_HTML_VALIDATION_ACTION ) ) { + if ( propName.equals( VALIDATOR_HTML_VALIDATION_ACTION ) ) { return desiredReturnAction; - } else if ( propName.equals( org.owasp.esapi.reference.DefaultSecurityConfiguration.VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE ) ) { + } else if ( propName.equals( VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE ) ) { return desiredReturnConfigurationFile; } else { return super.getStringProp( propName ); diff --git a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java index f0c97ecd4..32ca5feca 100644 --- a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java +++ b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java @@ -26,6 +26,7 @@ import org.owasp.esapi.errors.ValidationException; import org.owasp.esapi.filters.SecurityWrapperRequest; import org.owasp.esapi.reference.validation.HTMLValidationRule; +import static org.owasp.esapi.PropNames.VALIDATOR_HTML_VALIDATION_ACTION; import org.junit.Test; import org.junit.Before; @@ -65,7 +66,7 @@ private static class ConfOverride extends SecurityConfigurationWrapper { @Override public String getStringProp(String propName) { // Would it be better making this file a static import? - if ( propName.equals( org.owasp.esapi.reference.DefaultSecurityConfiguration.VALIDATOR_HTML_VALIDATION_ACTION ) ) { + if ( propName.equals( VALIDATOR_HTML_VALIDATION_ACTION ) ) { return desiredReturn; } else { return super.getStringProp( propName ); diff --git a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleThrowsTest.java b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleThrowsTest.java index 6130836dd..8965ea243 100644 --- a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleThrowsTest.java +++ b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleThrowsTest.java @@ -23,6 +23,7 @@ import org.owasp.esapi.Validator; import org.owasp.esapi.errors.ValidationException; import org.owasp.esapi.reference.validation.HTMLValidationRule; +import static org.owasp.esapi.PropNames.VALIDATOR_HTML_VALIDATION_ACTION; import org.junit.Test; import org.junit.Before; @@ -59,7 +60,7 @@ private static class ConfOverride extends SecurityConfigurationWrapper { @Override public String getStringProp(String propName) { // Would it be better making this file a static import? - if ( propName.equals( org.owasp.esapi.reference.DefaultSecurityConfiguration.VALIDATOR_HTML_VALIDATION_ACTION ) ) { + if ( propName.equals( VALIDATOR_HTML_VALIDATION_ACTION ) ) { return desiredReturn; } else { return super.getStringProp( propName ); From 613bc49cf6f05c2a796eee3efff982c25f4772e7 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Tue, 28 Jun 2022 14:01:30 -0400 Subject: [PATCH 007/197] Add forward slash encoding to DefaultEncoder's encodeForLDAP and encodeForDN According to [1] and [2], the forward slash ('/') character should be encoded for LDAP filters and distinguished names [1] https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax [2] https://social.technet.microsoft.com/wiki/contents/articles/5312.active-directory-characters-to-escape.aspx --- .../org/owasp/esapi/reference/DefaultEncoder.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java b/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java index fe504e722..d781459ff 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java @@ -305,13 +305,18 @@ public String encodeForLDAP(String input, boolean encodeWildcards) { } // TODO: replace with LDAP codec StringBuilder sb = new StringBuilder(); + // According to "Special Characters" at [1], the encoder should escape '*', '(', ')', '\', '/', NUL. Also see [2]. + // [1] https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax + // [2] https://social.technet.microsoft.com/wiki/contents/articles/5312.active-directory-characters-to-escape.aspx for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); - switch (c) { case '\\': sb.append("\\5c"); break; + case '/': + sb.append("\\2f"); + break; case '*': if (encodeWildcards) { sb.append("\\2a"); @@ -349,12 +354,18 @@ public String encodeForDN(String input) { if ((input.length() > 0) && ((input.charAt(0) == ' ') || (input.charAt(0) == '#'))) { sb.append('\\'); // add the leading backslash if needed } + // According to [1] and [2], the encoder should escape forward slash ('/') in DNs. + // [1] https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax + // [2] https://social.technet.microsoft.com/wiki/contents/articles/5312.active-directory-characters-to-escape.aspx for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); switch (c) { case '\\': sb.append("\\\\"); break; + case '/': + sb.append("\\/"); + break; case ',': sb.append("\\,"); break; From 90841862313fee99fef93ee8c233459ff9647f39 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Wed, 29 Jun 2022 12:49:45 -0400 Subject: [PATCH 008/197] Add forward slash encoding to DefaultEncoder's encodeForLDAP and encodeForDN According to [1] and [2], the forward slash ('/') character should be encoded for LDAP filters and distinguished names. [1] https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax [2] https://social.technet.microsoft.com/wiki/contents/articles/5312.active-directory-characters-to-escape.aspx --- .../java/org/owasp/esapi/reference/DefaultEncoder.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java b/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java index d781459ff..aa019a810 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java @@ -305,9 +305,13 @@ public String encodeForLDAP(String input, boolean encodeWildcards) { } // TODO: replace with LDAP codec StringBuilder sb = new StringBuilder(); - // According to "Special Characters" at [1], the encoder should escape '*', '(', ')', '\', '/', NUL. Also see [2]. + // According to Microsoft docs [1,2], the forward slash ('/') MUST be escaped. + // According to RFC 4513 Section 3 [3], the forward slash (and other characters) MAY be escaped. + // Since Microsoft is a MUST, escape forward slash for all implementations. Also see discussion at [4]. // [1] https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax // [2] https://social.technet.microsoft.com/wiki/contents/articles/5312.active-directory-characters-to-escape.aspx + // [3] https://tools.ietf.org/search/rfc4515#section-3 + // [4] https://lists.openldap.org/hyperkitty/list/openldap-technical@openldap.org/thread/3QPDDLO356ONSJM3JUKD7NMPOOIKIQ5T/ for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); switch (c) { @@ -354,9 +358,7 @@ public String encodeForDN(String input) { if ((input.length() > 0) && ((input.charAt(0) == ' ') || (input.charAt(0) == '#'))) { sb.append('\\'); // add the leading backslash if needed } - // According to [1] and [2], the encoder should escape forward slash ('/') in DNs. - // [1] https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax - // [2] https://social.technet.microsoft.com/wiki/contents/articles/5312.active-directory-characters-to-escape.aspx + // See discussion of forward slash ('/') in encodeForLDAP() for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); switch (c) { From 0ff0ddb174c9b96faf56c172e84033d8ceeb1687 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Wed, 29 Jun 2022 13:46:31 -0400 Subject: [PATCH 009/197] Add forward slash encoding to DefaultEncoder's encodeForLDAP and encodeForDN (v3) According to [1] and [2], the forward slash ('/') character should be encoded for LDAP filters and distinguished names. [1] https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax [2] https://social.technet.microsoft.com/wiki/contents/articles/5312.active-directory-characters-to-escape.aspx --- src/test/java/org/owasp/esapi/reference/EncoderTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/org/owasp/esapi/reference/EncoderTest.java b/src/test/java/org/owasp/esapi/reference/EncoderTest.java index 66f95c5b8..1b586a073 100644 --- a/src/test/java/org/owasp/esapi/reference/EncoderTest.java +++ b/src/test/java/org/owasp/esapi/reference/EncoderTest.java @@ -535,6 +535,7 @@ public void testEncodeForLDAP() { assertEquals("Zeros", "Hi \\00", instance.encodeForLDAP("Hi \u0000")); assertEquals("LDAP Christams Tree", "Hi \\28This\\29 = is \\2a a \\5c test # � � �", instance.encodeForLDAP("Hi (This) = is * a \\ test # � � �")); assertEquals("Hi \\28This\\29 =", instance.encodeForLDAP("Hi (This) =")); + assertEquals("Forward slash for \\2fMicrosoft\\2f \\2fAD\\2f", instance.encodeForLDAP("Forward slash for /Microsoft/ /AD/")); } /** @@ -547,6 +548,7 @@ public void testEncodeForLDAPWithoutEncodingWildcards() { assertEquals("No special characters to escape", "Hi This is a test #��", instance.encodeForLDAP("Hi This is a test #��", false)); assertEquals("Zeros", "Hi \\00", instance.encodeForLDAP("Hi \u0000", false)); assertEquals("LDAP Christams Tree", "Hi \\28This\\29 = is * a \\5c test # � � �", instance.encodeForLDAP("Hi (This) = is * a \\ test # � � �", false)); + assertEquals("Forward slash for \\2fMicrosoft\\2f \\2fAD\\2f", instance.encodeForLDAP("Forward slash for /Microsoft/ /AD/")); } /** @@ -563,6 +565,7 @@ public void testEncodeForDN() { assertEquals("less than greater than", "Hello\\<\\>", instance.encodeForDN("Hello<>")); assertEquals("only 3 spaces", "\\ \\ ", instance.encodeForDN(" ")); assertEquals("Christmas Tree DN", "\\ Hello\\\\ \\+ \\, \\\"World\\\" \\;\\ ", instance.encodeForDN(" Hello\\ + , \"World\" ; ")); + assertEquals("Forward slash for \\2fMicrosoft\\2f \\2fAD\\2f", instance.encodeForDN("Forward slash for /Microsoft/ /AD/")); } /** From c4276d67ee08e52da431d9464354a459ce197d23 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Thu, 30 Jun 2022 10:15:18 -0400 Subject: [PATCH 010/197] Add forward slash encoding to DefaultEncoder's encodeForLDAP and encodeForDN (v4) According to [1] and [2], the forward slash ('/') character should be encoded for LDAP filters and distinguished names. [1] https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax [2] https://social.technet.microsoft.com/wiki/contents/articles/5312.active-directory-characters-to-escape.aspx --- src/test/java/org/owasp/esapi/reference/EncoderTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/owasp/esapi/reference/EncoderTest.java b/src/test/java/org/owasp/esapi/reference/EncoderTest.java index 1b586a073..51c306e1f 100644 --- a/src/test/java/org/owasp/esapi/reference/EncoderTest.java +++ b/src/test/java/org/owasp/esapi/reference/EncoderTest.java @@ -548,7 +548,7 @@ public void testEncodeForLDAPWithoutEncodingWildcards() { assertEquals("No special characters to escape", "Hi This is a test #��", instance.encodeForLDAP("Hi This is a test #��", false)); assertEquals("Zeros", "Hi \\00", instance.encodeForLDAP("Hi \u0000", false)); assertEquals("LDAP Christams Tree", "Hi \\28This\\29 = is * a \\5c test # � � �", instance.encodeForLDAP("Hi (This) = is * a \\ test # � � �", false)); - assertEquals("Forward slash for \\2fMicrosoft\\2f \\2fAD\\2f", instance.encodeForLDAP("Forward slash for /Microsoft/ /AD/")); + assertEquals("Forward slash for \\/Microsoft\\/ \\/AD\\/", instance.encodeForLDAP("Forward slash for /Microsoft/ /AD/")); } /** From 0078dc0843de039ea75acb6293422d52768e4cd7 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Thu, 30 Jun 2022 10:19:57 -0400 Subject: [PATCH 011/197] Add forward slash encoding to DefaultEncoder's encodeForLDAP and encodeForDN (v5) According to [1] and [2], the forward slash ('/') character should be encoded for LDAP filters and distinguished names. [1] https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax [2] https://social.technet.microsoft.com/wiki/contents/articles/5312.active-directory-characters-to-escape.aspx --- src/test/java/org/owasp/esapi/reference/EncoderTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/owasp/esapi/reference/EncoderTest.java b/src/test/java/org/owasp/esapi/reference/EncoderTest.java index 51c306e1f..261e51fa9 100644 --- a/src/test/java/org/owasp/esapi/reference/EncoderTest.java +++ b/src/test/java/org/owasp/esapi/reference/EncoderTest.java @@ -548,7 +548,7 @@ public void testEncodeForLDAPWithoutEncodingWildcards() { assertEquals("No special characters to escape", "Hi This is a test #��", instance.encodeForLDAP("Hi This is a test #��", false)); assertEquals("Zeros", "Hi \\00", instance.encodeForLDAP("Hi \u0000", false)); assertEquals("LDAP Christams Tree", "Hi \\28This\\29 = is * a \\5c test # � � �", instance.encodeForLDAP("Hi (This) = is * a \\ test # � � �", false)); - assertEquals("Forward slash for \\/Microsoft\\/ \\/AD\\/", instance.encodeForLDAP("Forward slash for /Microsoft/ /AD/")); + assertEquals("Forward slash for \\2fMicrosoft\\2f \\2fAD\\2f", instance.encodeForLDAP("Forward slash for /Microsoft/ /AD/")); } /** @@ -565,7 +565,7 @@ public void testEncodeForDN() { assertEquals("less than greater than", "Hello\\<\\>", instance.encodeForDN("Hello<>")); assertEquals("only 3 spaces", "\\ \\ ", instance.encodeForDN(" ")); assertEquals("Christmas Tree DN", "\\ Hello\\\\ \\+ \\, \\\"World\\\" \\;\\ ", instance.encodeForDN(" Hello\\ + , \"World\" ; ")); - assertEquals("Forward slash for \\2fMicrosoft\\2f \\2fAD\\2f", instance.encodeForDN("Forward slash for /Microsoft/ /AD/")); + assertEquals("Forward slash for \\/Microsoft\\/ \\/AD\\/", instance.encodeForDN("Forward slash for /Microsoft/ /AD/")); } /** From e4fc652ae20fe7ed69d0d18fc59846f0af067153 Mon Sep 17 00:00:00 2001 From: jeremiahjstacey Date: Sat, 2 Jul 2022 20:43:11 -0500 Subject: [PATCH 012/197] Log4J Removal (#714) Close issue #534 - This is a planned removal of all Log4J 1 dependencies after nearly 2 years of deprecation. The release for this will be released on or shortly after 2022-07-13. * Suppression cleanup Clearing log4j1 suppressions from baseline. Should cause maven site goal to fail if cleanup is not incomplete. * Log4J 1.x Source & Dependency Removal Removing baseline code & tests pertaining to log4j 1.x support. Removing log4j 1.x dependency from pom. * WAF Cleanup - Removing customized Log handling AppGuardianConfiguration had a declaration of a log4j log Level class which appears to never be used. ESAPIWebApplicationFirewallFilter attempts to compliment/override a pre-existing log4j1.x configuratino through the filterConfig with an expectation that ESAPI is configured for that Logger explicitly. * This has just been removed to allow the implementation to use the ESAPI Logger as configured. * Removing ant-javadoc.xml artifact Javadocs are generated in the maven build through the javadoc maven plugin. * log4j 1.x configuration file removal Remvoing log4j.dtd and log4j.xml instances from baseline. * log4j 1.x - Removing references in properties Cleaning up source and test references to the removed content. * log4j 1.x cleanup - scripts Removing log4j class contexts from the release process scripts. * JAVADOC CLEANUP Addressing warnings in javadoc generation. * Case sensitivity addressed in SecurityConfiguration. * Removed invalid class reference from Logger. This would have been an update; however, the reference point no longer fufills the reason for the initial link. This commit is superfluous to the log4j1.x removal intention of the branch where it was committed. * Merging suppressions file * Version updates Applying the latest plugin and dependency versions. * Comment Grammer cleanup. PR feedback. --- ant-javadoc.xml | 8 - configuration/esapi/ESAPI.properties | 3 - configuration/log4j.dtd | 227 ----- configuration/log4j.xml | 62 -- pom.xml | 21 +- ...esapi4java-core-TEMPLATE-release-notes.txt | 1 - src/main/java/org/owasp/esapi/Logger.java | 4 +- .../esapi/logging/log4j/Log4JLogBridge.java | 43 - .../logging/log4j/Log4JLogBridgeImpl.java | 76 -- .../esapi/logging/log4j/Log4JLogFactory.java | 125 --- .../logging/log4j/Log4JLogLevelHandler.java | 43 - .../logging/log4j/Log4JLogLevelHandlers.java | 56 -- .../esapi/logging/log4j/Log4JLogger.java | 168 ---- .../logging/log4j/Log4JLoggerFactory.java | 90 -- .../ESAPIWebApplicationFirewallFilter.java | 876 +++++++++--------- .../AppGuardianConfiguration.java | 28 - .../logging/log4j/Log4JLogBridgeImplTest.java | 152 --- .../logging/log4j/Log4JLogFactoryTest.java | 108 --- .../log4j/Log4JLogLevelHandlersTest.java | 102 -- .../logging/log4j/Log4JLoggerFactoryTest.java | 97 -- .../esapi/logging/log4j/Log4JLoggerTest.java | 287 ------ ...ESAPI-CommaValidatorFileChecker.properties | 5 +- .../ESAPI-DualValidatorFileChecker.properties | 5 +- ...SAPI-QuotedValidatorFileChecker.properties | 5 +- ...SAPI-SingleValidatorFileChecker.properties | 5 +- src/test/resources/esapi/ESAPI.properties | 3 - src/test/resources/log4j.dtd | 227 ----- src/test/resources/log4j.xml | 70 -- suppressions.xml | 102 -- 29 files changed, 444 insertions(+), 2555 deletions(-) delete mode 100644 ant-javadoc.xml delete mode 100644 configuration/log4j.dtd delete mode 100644 configuration/log4j.xml delete mode 100644 src/main/java/org/owasp/esapi/logging/log4j/Log4JLogBridge.java delete mode 100644 src/main/java/org/owasp/esapi/logging/log4j/Log4JLogBridgeImpl.java delete mode 100644 src/main/java/org/owasp/esapi/logging/log4j/Log4JLogFactory.java delete mode 100644 src/main/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandler.java delete mode 100644 src/main/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandlers.java delete mode 100644 src/main/java/org/owasp/esapi/logging/log4j/Log4JLogger.java delete mode 100644 src/main/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactory.java delete mode 100644 src/test/java/org/owasp/esapi/logging/log4j/Log4JLogBridgeImplTest.java delete mode 100644 src/test/java/org/owasp/esapi/logging/log4j/Log4JLogFactoryTest.java delete mode 100644 src/test/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandlersTest.java delete mode 100644 src/test/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactoryTest.java delete mode 100644 src/test/java/org/owasp/esapi/logging/log4j/Log4JLoggerTest.java delete mode 100644 src/test/resources/log4j.dtd delete mode 100644 src/test/resources/log4j.xml diff --git a/ant-javadoc.xml b/ant-javadoc.xml deleted file mode 100644 index 2995a75b0..000000000 --- a/ant-javadoc.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/configuration/esapi/ESAPI.properties b/configuration/esapi/ESAPI.properties index bbb7531cd..19c34b729 100644 --- a/configuration/esapi/ESAPI.properties +++ b/configuration/esapi/ESAPI.properties @@ -66,9 +66,6 @@ ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector -# Log4JFactory Requires log4j.xml or log4j.properties in classpath - http://www.laliluna.de/log4j-tutorial.html -# Note that this is now considered deprecated! -#ESAPI.Logger=org.owasp.esapi.logging.log4j.Log4JLogFactory ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory # To use the new SLF4J logger in ESAPI (see GitHub issue #129), set # ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory diff --git a/configuration/log4j.dtd b/configuration/log4j.dtd deleted file mode 100644 index 1aabd96c3..000000000 --- a/configuration/log4j.dtd +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/configuration/log4j.xml b/configuration/log4j.xml deleted file mode 100644 index 47c064004..000000000 --- a/configuration/log4j.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pom.xml b/pom.xml index d9dde1dda..317d5c189 100644 --- a/pom.xml +++ b/pom.xml @@ -138,10 +138,10 @@ UTF-8 1.35 2.0.9 - 4.7.0 + 4.7.1 1.12.0 4.7.0.0 - 3.0.0-M6 + 3.0.0-M7 1.8 @@ -235,11 +235,6 @@ - - log4j - log4j - 1.2.17 - org.apache.commons commons-collections4 @@ -411,7 +406,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.3.0 + 3.4.0 org.apache.maven.plugins @@ -421,7 +416,7 @@ org.apache.maven.plugins maven-release-plugin - 3.0.0-M5 + 3.0.0-M6 org.codehaus.mojo @@ -538,7 +533,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0 + 3.1.0 org.codehaus.mojo @@ -671,7 +666,7 @@ org.apache.maven.plugins maven-pmd-plugin - 3.16.0 + 3.17.0 @@ -689,7 +684,7 @@ org.apache.maven.plugins maven-site-plugin - 4.0.0-M1 + 4.0.0-M2 @@ -743,7 +738,7 @@ org.owasp dependency-check-maven - 7.1.0 + 7.1.1 1.0 ./suppressions.xml diff --git a/scripts/esapi4java-core-TEMPLATE-release-notes.txt b/scripts/esapi4java-core-TEMPLATE-release-notes.txt index 5caad5c37..b55fd969c 100644 --- a/scripts/esapi4java-core-TEMPLATE-release-notes.txt +++ b/scripts/esapi4java-core-TEMPLATE-release-notes.txt @@ -58,7 +58,6 @@ However, if you try to juse the new ESAPI 2.2.1.0 or later logging you will noti To use ESAPI logging in ESAPI 2.2.1.0 (and later), you will need to set the ESAPI.Logger property to org.owasp.esapi.logging.java.JavaLogFactory - To use the new default, java.util.logging (JUL) - org.owasp.esapi.logging.log4j.Log4JLogFactory - To use the end-of-life Log4J 1.x logger org.owasp.esapi.logging.slf4j.Slf4JLogFactory - To use the new (to release 2.2.0.0) SLF4J logger In addition, if you wish to use JUL for logging, you *MUST* supply an "esapi-java-logging.properties" file in your classpath. This file is included in the 'esapi-2.2.2.0-configuration.jar' file provided under the 'Assets' section of the GitHub Release at diff --git a/src/main/java/org/owasp/esapi/Logger.java b/src/main/java/org/owasp/esapi/Logger.java index 0f41e7376..c73e27ab2 100644 --- a/src/main/java/org/owasp/esapi/Logger.java +++ b/src/main/java/org/owasp/esapi/Logger.java @@ -205,9 +205,7 @@ public String toString() { */ void setLevel(int level); - /** Retrieve the current ESAPI logging level for this logger. See - * {@link org.owasp.esapi.logging.log4j.Log4JLogger} for an explanation of - * why this method is not simply called {@code getLevel()}. + /** Retrieve the current ESAPI logging level for this logger. * * @return The current logging level. */ diff --git a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogBridge.java b/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogBridge.java deleted file mode 100644 index b89acb81e..000000000 --- a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogBridge.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * 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. - * - * @created 2019 - */ -package org.owasp.esapi.logging.log4j; - -import org.apache.log4j.Logger; -import org.owasp.esapi.Logger.EventType; -/** - * Contract for translating an ESAPI log event into an Log4J log event. - * - */ -@Deprecated -public interface Log4JLogBridge { - /** - * Translation for the provided ESAPI level, type, and message to the specified Log4J Logger. - * @param logger Logger to receive the translated message. - * @param esapiLevel ESAPI level of event. - * @param type ESAPI event type - * @param message ESAPI event message content. - */ - void log(Logger logger, int esapiLevel, EventType type, String message) ; - /** - * Translation for the provided ESAPI level, type, message, and Throwable to the specified Log4J Logger. - * @param logger Logger to receive the translated message. - * @param esapiLevel ESAPI level of event. - * @param type ESAPI event type - * @param message ESAPI event message content. - * @param throwable ESAPI event Throwable content - */ - void log(Logger logger, int esapiLevel, EventType type, String message, Throwable throwable) ; - -} diff --git a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogBridgeImpl.java b/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogBridgeImpl.java deleted file mode 100644 index 58be15beb..000000000 --- a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogBridgeImpl.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * 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. - * - * @created 2019 - */ - -package org.owasp.esapi.logging.log4j; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; -import org.owasp.esapi.Logger.EventType; -import org.owasp.esapi.logging.appender.LogAppender; -import org.owasp.esapi.logging.cleaning.LogScrubber; - -/** - * Implementation which is intended to bridge the ESAPI Logging API into LOG4J supported Object structures. - * - */ -@Deprecated -public class Log4JLogBridgeImpl implements Log4JLogBridge { - /** Configuration providing associations between esapi log levels and LOG4J levels.*/ - private final Map esapiSlfLevelMap; - /** Cleaner used for log content.*/ - private final LogScrubber scrubber; - /** Appender used for assembling default message content for all logs.*/ - private final LogAppender appender; - - /** - * Constructor. - * @param logScrubber Log message cleaner. - * @param esapiSlfHandlerMap Map identifying ESAPI -> LOG4J log level associations. - */ - public Log4JLogBridgeImpl(LogAppender messageAppender, LogScrubber logScrubber, Map esapiSlfHandlerMap) { - //Defensive copy to prevent external mutations. - this.esapiSlfLevelMap = new HashMap<>(esapiSlfHandlerMap); - this.scrubber = logScrubber; - this.appender = messageAppender; - } - @Override - public void log(Logger logger, int esapiLevel, EventType type, String message) { - Log4JLogLevelHandler handler = esapiSlfLevelMap.get(esapiLevel); - if (handler == null) { - throw new IllegalArgumentException("Unable to lookup LOG4J level mapping for esapi value of " + esapiLevel); - } - if (handler.isEnabled(logger)) { - String fullMessage = appender.appendTo(logger.getName(), type, message); - String cleanString = scrubber.cleanMessage(fullMessage); - - handler.log(logger, cleanString); - } - } - @Override - public void log(Logger logger, int esapiLevel, EventType type, String message, Throwable throwable) { - Log4JLogLevelHandler handler = esapiSlfLevelMap.get(esapiLevel); - if (handler == null) { - throw new IllegalArgumentException("Unable to lookup LOG4J level mapping for esapi value of " + esapiLevel); - } - if (handler.isEnabled(logger)) { - String fullMessage = appender.appendTo(logger.getName(), type, message); - String cleanString = scrubber.cleanMessage(fullMessage); - - handler.log(logger, cleanString, throwable); - } - } -} diff --git a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogFactory.java b/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogFactory.java deleted file mode 100644 index a71cf3141..000000000 --- a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogFactory.java +++ /dev/null @@ -1,125 +0,0 @@ -/** - * 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. - * - * @created 2019 - */ -package org.owasp.esapi.logging.log4j; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.owasp.esapi.ESAPI; -import org.owasp.esapi.LogFactory; -import org.owasp.esapi.Logger; -import org.owasp.esapi.codecs.HTMLEntityCodec; -import org.owasp.esapi.logging.appender.LogAppender; -import org.owasp.esapi.logging.appender.LogPrefixAppender; -import org.owasp.esapi.logging.cleaning.CodecLogScrubber; -import org.owasp.esapi.logging.cleaning.CompositeLogScrubber; -import org.owasp.esapi.logging.cleaning.LogScrubber; -import org.owasp.esapi.logging.cleaning.NewlineLogScrubber; - -import static org.owasp.esapi.PropNames.LOG_ENCODING_REQUIRED; -import static org.owasp.esapi.PropNames.LOG_USER_INFO; -import static org.owasp.esapi.PropNames.LOG_CLIENT_INFO; -import static org.owasp.esapi.PropNames.LOG_APPLICATION_NAME; -import static org.owasp.esapi.PropNames.APPLICATION_NAME; -import static org.owasp.esapi.PropNames.LOG_SERVER_IP; - -/** - * LogFactory implementation which creates Log4J supporting Loggers. - * - */ -@Deprecated -public class Log4JLogFactory implements LogFactory { - /** Immune characters for the codec log scrubber for JAVA context.*/ - private static final char[] IMMUNE_LOG4J_HTML = {',', '.', '-', '_', ' ' }; - /** Codec being used to clean messages for logging.*/ - private static final HTMLEntityCodec HTML_CODEC = new HTMLEntityCodec(); - /** Log appender instance.*/ - private static LogAppender Log4J_LOG_APPENDER; - /** Log cleaner instance.*/ - private static LogScrubber Log4J_LOG_SCRUBBER; - /** Bridge class for mapping esapi -> log4j log levels.*/ - private static Log4JLogBridge LOG_BRIDGE; - - static { - boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(LOG_ENCODING_REQUIRED); - Log4J_LOG_SCRUBBER = createLogScrubber(encodeLog); - - - boolean logUserInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_USER_INFO); - boolean logClientInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_CLIENT_INFO); - boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(LOG_APPLICATION_NAME); - String appName = ESAPI.securityConfiguration().getStringProp(APPLICATION_NAME); - boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(LOG_SERVER_IP); - Log4J_LOG_APPENDER = createLogAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); - - Map levelLookup = new HashMap<>(); - levelLookup.put(Logger.ALL, Log4JLogLevelHandlers.TRACE); - levelLookup.put(Logger.TRACE, Log4JLogLevelHandlers.TRACE); - levelLookup.put(Logger.DEBUG, Log4JLogLevelHandlers.DEBUG); - levelLookup.put(Logger.INFO, Log4JLogLevelHandlers.INFO); - levelLookup.put(Logger.ERROR, Log4JLogLevelHandlers.ERROR); - levelLookup.put(Logger.WARNING, Log4JLogLevelHandlers.WARN); - levelLookup.put(Logger.FATAL, Log4JLogLevelHandlers.FATAL); - //LEVEL.OFF not used. If it's off why would we try to log it? - - LOG_BRIDGE = new Log4JLogBridgeImpl(Log4J_LOG_APPENDER, Log4J_LOG_SCRUBBER, levelLookup); - } - - /** - * Populates the default log scrubber for use in factory-created loggers. - * @param requiresEncoding {@code true} if encoding is required for log content. - * @return LogScrubber instance. - */ - /*package*/ static LogScrubber createLogScrubber(boolean requiresEncoding) { - List messageScrubber = new ArrayList<>(); - messageScrubber.add(new NewlineLogScrubber()); - - if (requiresEncoding) { - messageScrubber.add(new CodecLogScrubber(HTML_CODEC, IMMUNE_LOG4J_HTML)); - } - - return new CompositeLogScrubber(messageScrubber); - - } - - /** - * Populates the default log appender for use in factory-created loggers. - * @param appName - * @param logApplicationName - * @param logServerIp - * @param logClientInfo - * - * @return LogAppender instance. - */ - /*package*/ static LogAppender createLogAppender(boolean logUserInfo, boolean logClientInfo, boolean logServerIp, boolean logApplicationName, String appName) { - return new LogPrefixAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); - } - - - @Override - public Logger getLogger(String moduleName) { - org.apache.log4j.Logger log4JLogger = org.apache.log4j.Logger.getLogger(moduleName); - return new Log4JLogger(log4JLogger, LOG_BRIDGE, Logger.ALL); - } - - @Override - public Logger getLogger(@SuppressWarnings("rawtypes") Class clazz) { - org.apache.log4j.Logger log4JLogger = org.apache.log4j.Logger.getLogger(clazz); - return new Log4JLogger(log4JLogger, LOG_BRIDGE, Logger.ALL); - } - -} diff --git a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandler.java b/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandler.java deleted file mode 100644 index 7b6b57ee9..000000000 --- a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * 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. - * - * @created 2019 - */ -package org.owasp.esapi.logging.log4j; - -import org.apache.log4j.Logger; - -/** - * Contract used to isolate translations for each SLF4J Logging Level. - * - * @see Log4JLogLevelHandlers - * @see Log4JLogBridgeImpl - * - */ -@Deprecated -interface Log4JLogLevelHandler { - /** Check if the logging level is enabled for the specified logger.*/ - boolean isEnabled(Logger logger); - /** - * Calls the appropriate log level event on the specified logger. - * @param logger Logger to invoke. - * @param msg Message to log. - */ - void log(Logger logger, String msg); - /** - * Calls the appropriate log level event on the specified logger. - * @param logger Logger to invoke - * @param msg Message to log - * @param th Throwable to log. - */ - void log(Logger logger, String msg, Throwable th); -} diff --git a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandlers.java b/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandlers.java deleted file mode 100644 index e6ee6a48c..000000000 --- a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandlers.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * 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. - * - * @created 2019 - */ - -package org.owasp.esapi.logging.log4j; - - -import org.apache.log4j.Level; -import org.apache.log4j.Logger; - -/** - * Enumeration capturing the propagation of Log4J level events. - * - */ -@Deprecated -public enum Log4JLogLevelHandlers implements Log4JLogLevelHandler { - FATAL(Level.FATAL), - ERROR(Level.ERROR), - WARN(Level.WARN), - INFO(Level.INFO), - DEBUG(Level.DEBUG), - TRACE(Level.TRACE), - ALL(Level.ALL); - - private final Level level; - - private Log4JLogLevelHandlers(Level lvl) { - this.level = lvl; - } - - @Override - public boolean isEnabled(Logger logger) { - return logger.isEnabledFor(level); - } - - @Override - public void log(Logger logger, String msg) { - logger.log(level, msg); - } - - @Override - public void log(Logger logger, String msg, Throwable th) { - logger.log(level, msg, th); - } -} diff --git a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogger.java b/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogger.java deleted file mode 100644 index cbbda2140..000000000 --- a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLogger.java +++ /dev/null @@ -1,168 +0,0 @@ -/** - * 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. - * - * @created 2019 - */ -package org.owasp.esapi.logging.log4j; - -import org.owasp.esapi.Logger; -/** - * ESAPI Logger implementation which relays events to an Log4j delegate. - */ -@Deprecated -public class Log4JLogger implements org.owasp.esapi.Logger { - /** Delegate Logger.*/ - private final org.apache.log4j.Logger delegate; - /** Handler for translating events from ESAPI context for SLF4J processing.*/ - private final Log4JLogBridge logBridge; - /** Maximum log level that will be forwarded to SLF4J from the ESAPI context.*/ - private int loggingLevel; - - /** - * Constructs a new instance. - * @param slf4JLogger Delegate SLF4J logger. - * @param bridge Translator for ESAPI -> SLF4J logging events. - * @param defaultEsapiLevel Maximum ESAPI log level events to propagate. - */ - public Log4JLogger(org.apache.log4j.Logger slf4JLogger, Log4JLogBridge bridge, int defaultEsapiLevel) { - delegate = slf4JLogger; - this.logBridge = bridge; - loggingLevel = defaultEsapiLevel; - } - - private void log(int esapiLevel, EventType type, String message) { - if (isEnabled(esapiLevel)) { - logBridge.log(delegate, esapiLevel, type, message); - } - } - - private void log(int esapiLevel, EventType type, String message, Throwable throwable) { - if (isEnabled(esapiLevel)) { - logBridge.log(delegate, esapiLevel, type, message, throwable); - } - } - - - private boolean isEnabled(int esapiLevel) { - return esapiLevel >= loggingLevel; - } - - @Override - public void always(EventType type, String message) { - log (Logger.ALL, type, message); - } - - @Override - public void always(EventType type, String message, Throwable throwable) { - log (Logger.ALL, type, message, throwable); - } - - @Override - public void trace(EventType type, String message) { - log (Logger.TRACE, type, message); - } - - @Override - public void trace(EventType type, String message, Throwable throwable) { - log (Logger.TRACE, type, message, throwable); - } - - @Override - public void debug(EventType type, String message) { - log (Logger.DEBUG, type, message); - } - - @Override - public void debug(EventType type, String message, Throwable throwable) { - log (Logger.DEBUG, type, message, throwable); - } - - @Override - public void info(EventType type, String message) { - log (Logger.INFO, type, message); - } - - @Override - public void info(EventType type, String message, Throwable throwable) { - log (Logger.INFO, type, message, throwable); - } - - @Override - public void warning(EventType type, String message) { - log (Logger.WARNING, type, message); - } - - @Override - public void warning(EventType type, String message, Throwable throwable) { - log (Logger.WARNING, type, message, throwable); - } - - @Override - public void error(EventType type, String message) { - log (Logger.ERROR, type, message); - } - - @Override - public void error(EventType type, String message, Throwable throwable) { - log (Logger.ERROR, type, message, throwable); - } - - @Override - public void fatal(EventType type, String message) { - log (Logger.FATAL, type, message); - } - - @Override - public void fatal(EventType type, String message, Throwable throwable) { - log (Logger.FATAL, type, message, throwable); - } - - @Override - public int getESAPILevel() { - return loggingLevel; - } - - @Override - public boolean isTraceEnabled() { - return isEnabled(Logger.TRACE); - } - - @Override - public boolean isDebugEnabled() { - return isEnabled(Logger.DEBUG); - } - @Override - public boolean isInfoEnabled() { - return isEnabled(Logger.INFO); - } - @Override - public boolean isWarningEnabled() { - return isEnabled(Logger.WARNING); - } - - @Override - public boolean isErrorEnabled() { - return isEnabled(Logger.ERROR); - } - - @Override - public boolean isFatalEnabled() { - return isEnabled(Logger.FATAL); - } - - - @Override - public void setLevel(int level) { - loggingLevel = level; - } - -} diff --git a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactory.java b/src/main/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactory.java deleted file mode 100644 index 91dd0da4f..000000000 --- a/src/main/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactory.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * 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.logging.log4j; - -import org.apache.log4j.Priority; -import org.apache.log4j.spi.LoggerFactory; -import org.owasp.esapi.ESAPI; -import org.owasp.esapi.logging.appender.LogAppender; -import org.owasp.esapi.logging.cleaning.LogScrubber; - -import static org.owasp.esapi.PropNames.LOG_ENCODING_REQUIRED; -import static org.owasp.esapi.PropNames.LOG_USER_INFO; -import static org.owasp.esapi.PropNames.LOG_CLIENT_INFO; -import static org.owasp.esapi.PropNames.LOG_APPLICATION_NAME; -import static org.owasp.esapi.PropNames.APPLICATION_NAME; -import static org.owasp.esapi.PropNames.LOG_SERVER_IP; - -/** - * Service Provider Interface implementation that can be provided as the org.apache.log4j.spi.LoggerFactory reference in a Log4J configuration. - *
- * - * <loggerFactory class="org.owasp.esapi.logging.log4j.Log4JLoggerFactory"/> - * - */ -@Deprecated -public class Log4JLoggerFactory implements LoggerFactory { - /** Log appender instance.*/ - private static LogAppender LOG4J_LOG_APPENDER; - /** Log cleaner instance.*/ - private static LogScrubber LOG4J_LOG_SCRUBBER; - - static { - boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(LOG_ENCODING_REQUIRED); - LOG4J_LOG_SCRUBBER = Log4JLogFactory.createLogScrubber(encodeLog); - - boolean logUserInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_USER_INFO); - boolean logClientInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_CLIENT_INFO); - boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(LOG_APPLICATION_NAME); - String appName = ESAPI.securityConfiguration().getStringProp(APPLICATION_NAME); - boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(LOG_SERVER_IP); - LOG4J_LOG_APPENDER = Log4JLogFactory.createLogAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); - } - - /** - * This constructor must be public so it can be accessed from within log4j - */ - public Log4JLoggerFactory() {} - - /** - * Overridden to return instances of org.owasp.esapi.reference.Log4JLogger. - * - * @param name The class name to return a logger for. - * @return org.owasp.esapi.reference.Log4JLogger - */ - public org.apache.log4j.Logger makeNewLoggerInstance(String name) { - return new EsapiLog4JWrapper(name); - } - - - public static class EsapiLog4JWrapper extends org.apache.log4j.Logger { - - protected EsapiLog4JWrapper(String name) { - super(name); - } - - @Override - protected void forcedLog(String fqcn, Priority level, Object message, Throwable t) { - String toClean = message.toString(); - - String fullMessage = LOG4J_LOG_APPENDER.appendTo(getName(), null, toClean); - String cleanMsg = LOG4J_LOG_SCRUBBER.cleanMessage(fullMessage); - - super.forcedLog(fqcn, level, cleanMsg, t); - } - - } -} diff --git a/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java b/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java index 3bf56cab4..0879ac516 100644 --- a/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java +++ b/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java @@ -16,7 +16,6 @@ package org.owasp.esapi.waf; import java.io.File; - import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; @@ -32,7 +31,6 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileUploadException; -import org.apache.log4j.xml.DOMConfigurator; import org.owasp.esapi.ESAPI; import org.owasp.esapi.Logger; import org.owasp.esapi.waf.actions.Action; @@ -60,448 +58,436 @@ */ public class ESAPIWebApplicationFirewallFilter implements Filter { - private AppGuardianConfiguration appGuardConfig; - - private static final String CONFIGURATION_FILE_PARAM = "configuration"; - private static final String LOGGING_FILE_PARAM = "log_settings"; - private static final String POLLING_TIME_PARAM = "polling_time"; - - private static final int DEFAULT_POLLING_TIME = 30000; - - private String configurationFilename = null; - - private long pollingTime; - - private long lastConfigReadTime; - - // private static final String FAUX_SESSION_COOKIE = "FAUXSC"; - // private static final String SESSION_COOKIE_CANARY = - // "org.owasp.esapi.waf.canary"; - - private FilterConfig fc; - - private final Logger logger = ESAPI.getLogger(ESAPIWebApplicationFirewallFilter.class); - - /** - * This function is used in testing to dynamically alter the configuration. - * - * @param policyFilePath - * The path to the policy file - * @param webRootDir - * The root directory of the web application. - * @throws FileNotFoundException - * if the policy file cannot be located - */ - public void setConfiguration(String policyFilePath, String webRootDir) throws FileNotFoundException { - - FileInputStream inputStream = null; - - try { - inputStream = new FileInputStream(new File(policyFilePath)); - appGuardConfig = ConfigurationParser.readConfigurationFile(inputStream, webRootDir); - lastConfigReadTime = System.currentTimeMillis(); - configurationFilename = policyFilePath; - } catch (ConfigurationException e) { - // TODO: It would be ideal if this method through the - // ConfigurationException rather than catching it and - // writing the error to the console. - e.printStackTrace(); - } finally { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - public AppGuardianConfiguration getConfiguration() { - return appGuardConfig; - } - - /** - * - * This function is invoked at application startup and when the - * configuration file polling period has elapsed and a change in the - * configuration file has been detected. - * - * It's main purpose is to read the configuration file and establish the - * configuration object model for use at runtime during the - * doFilter() method. - */ - public void init(FilterConfig fc) throws ServletException { - - /* - * This variable is saved so that we can retrieve it later to re-invoke - * this function. - */ - this.fc = fc; - - logger.debug(Logger.EVENT_SUCCESS, ">> Initializing WAF"); - /* - * Pull logging file. - */ - - // Demoted scope to a local since this is the only place it is - // referenced - String logSettingsFilename = fc.getInitParameter(LOGGING_FILE_PARAM); - - String realLogSettingsFilename = fc.getServletContext().getRealPath(logSettingsFilename); - - if (realLogSettingsFilename == null || (!new File(realLogSettingsFilename).exists())) { - throw new ServletException( - "[ESAPI WAF] Could not find log file at resolved path: " + realLogSettingsFilename); - } - - /* - * Pull main configuration file. - */ - - configurationFilename = fc.getInitParameter(CONFIGURATION_FILE_PARAM); - - configurationFilename = fc.getServletContext().getRealPath(configurationFilename); - - if (configurationFilename == null || !new File(configurationFilename).exists()) { - throw new ServletException( - "[ESAPI WAF] Could not find configuration file at resolved path: " + configurationFilename); - } - - /* - * Find out polling time from a parameter. If none is provided, use the - * default (10 seconds). - */ - - String sPollingTime = fc.getInitParameter(POLLING_TIME_PARAM); - - if (sPollingTime != null) { - pollingTime = Long.parseLong(sPollingTime); - } else { - pollingTime = DEFAULT_POLLING_TIME; - } - - /* - * Open up configuration file and populate the AppGuardian configuration - * object. - */ - - FileInputStream inputStream = null; - - try { - String webRootDir = fc.getServletContext().getRealPath("/"); - inputStream = new FileInputStream(configurationFilename); - appGuardConfig = ConfigurationParser.readConfigurationFile(inputStream, webRootDir); - DOMConfigurator.configure(realLogSettingsFilename); - lastConfigReadTime = System.currentTimeMillis(); - } catch (FileNotFoundException e) { - throw new ServletException(e); - } catch (ConfigurationException e) { - throw new ServletException(e); - } finally { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - /** - * This is the where the main interception and rule-checking logic of the - * WAF resides. - */ - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) - throws IOException, ServletException { - - /* - * Check to see if polling time has elapsed. If it has, that means we - * should check to see if the config file has been changed. If it has, - * then re-read it. - * - * // TODO: Any reason this logic shouldn't be moved into a polling - * thread class? - */ - - if ((System.currentTimeMillis() - lastConfigReadTime) > pollingTime) { - File f = new File(configurationFilename); - long lastModified = f.lastModified(); - if (lastModified > lastConfigReadTime) { - /* - * The file has been altered since it was read in the last time. - * Must re-read it. - */ - logger.debug(Logger.EVENT_SUCCESS, ">> Re-reading WAF policy"); - init(fc); - } - } - - logger.debug(Logger.EVENT_SUCCESS, ">>In WAF doFilter"); - - HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; - HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; - - InterceptingHTTPServletRequest request = null; - InterceptingHTTPServletResponse response = null; - - /* - * First thing to do is create the InterceptingHTTPServletResponse, - * since we'll need that possibly before the - * InterceptingHTTPServletRequest. - * - * The normal HttpRequest-type objects will suffice us until we get to - * stage 2. - * - * 1st argument = the response to base the instance on 2nd argument = - * should we bother intercepting the egress response? 3rd argument = - * cookie rules because thats where they mostly get acted on - */ - - if (appGuardConfig.getCookieRules().size() + appGuardConfig.getBeforeResponseRules().size() > 0) { - response = new InterceptingHTTPServletResponse(httpResponse, true, appGuardConfig.getCookieRules()); - } - - /* - * Stage 1: Rules that do not need the request body. - */ - logger.debug(Logger.EVENT_SUCCESS, ">> Starting stage 1"); - - List rules = this.appGuardConfig.getBeforeBodyRules(); - - for (int i = 0; i < rules.size(); i++) { - - Rule rule = rules.get(i); - logger.debug(Logger.EVENT_SUCCESS, " Applying BEFORE rule: " + rule.getClass().getName()); - - /* - * The rules execute in check(). The check() method will also log. - * All we have to do is decide what other actions to take. - */ - Action action = rule.check(httpRequest, response, httpResponse); - - if (action.isActionNecessary()) { - - if (action instanceof BlockAction) { - if (response != null) { - response.setStatus(appGuardConfig.getDefaultResponseCode()); - } else { - httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); - } - return; - - } else if (action instanceof RedirectAction) { - sendRedirect(response, httpResponse, ((RedirectAction) action).getRedirectURL()); - return; - - } else if (action instanceof DefaultAction) { - - switch (AppGuardianConfiguration.DEFAULT_FAIL_ACTION) { - case AppGuardianConfiguration.BLOCK: - if (response != null) { - response.setStatus(appGuardConfig.getDefaultResponseCode()); - } else { - httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); - } - return; - - case AppGuardianConfiguration.REDIRECT: - sendRedirect(response, httpResponse); - return; - } - } - } - } - - /* - * Create the InterceptingHTTPServletRequest. - */ - - try { - request = new InterceptingHTTPServletRequest((HttpServletRequest) servletRequest); - } catch (FileUploadException fue) { - logger.error(Logger.EVENT_SUCCESS, "Error Wrapping Request", fue); - } - - /* - * Stage 2: After the body has been read, but before the the application - * has gotten it. - */ - logger.debug(Logger.EVENT_SUCCESS, ">> Starting Stage 2"); - - rules = this.appGuardConfig.getAfterBodyRules(); - - for (int i = 0; i < rules.size(); i++) { - - Rule rule = rules.get(i); - logger.debug(Logger.EVENT_SUCCESS, " Applying BEFORE CHAIN rule: " + rule.getClass().getName()); - - /* - * The rules execute in check(). The check() method will take care - * of logging. All we have to do is decide what other actions to - * take. - */ - Action action = rule.check(request, response, httpResponse); - - if (action.isActionNecessary()) { - - if (action instanceof BlockAction) { - if (response != null) { - response.setStatus(appGuardConfig.getDefaultResponseCode()); - } else { - httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); - } - return; - - } else if (action instanceof RedirectAction) { - sendRedirect(response, httpResponse, ((RedirectAction) action).getRedirectURL()); - return; - - } else if (action instanceof DefaultAction) { - - switch (AppGuardianConfiguration.DEFAULT_FAIL_ACTION) { - case AppGuardianConfiguration.BLOCK: - if (response != null) { - response.setStatus(appGuardConfig.getDefaultResponseCode()); - } else { - httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); - } - return; - - case AppGuardianConfiguration.REDIRECT: - sendRedirect(response, httpResponse); - return; - } - } - } - } - - /* - * In between stages 2 and 3 is the application's processing of the - * input. - */ - logger.debug(Logger.EVENT_SUCCESS, ">> Calling the FilterChain: " + chain); - chain.doFilter(request, response != null ? response : httpResponse); - - /* - * Stage 3: Before the response has been sent back to the user. - */ - logger.debug(Logger.EVENT_SUCCESS, ">> Starting Stage 3"); - - rules = this.appGuardConfig.getBeforeResponseRules(); - - for (int i = 0; i < rules.size(); i++) { - - Rule rule = rules.get(i); - logger.debug(Logger.EVENT_SUCCESS, " Applying AFTER CHAIN rule: " + rule.getClass().getName()); - - /* - * The rules execute in check(). The check() method will also log. - * All we have to do is decide what other actions to take. - */ - Action action = rule.check(request, response, httpResponse); - - if (action.isActionNecessary()) { - - if (action instanceof BlockAction) { - if (response != null) { - response.setStatus(appGuardConfig.getDefaultResponseCode()); - } else { - httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); - } - return; - - } else if (action instanceof RedirectAction) { - sendRedirect(response, httpResponse, ((RedirectAction) action).getRedirectURL()); - return; - - } else if (action instanceof DefaultAction) { - - switch (AppGuardianConfiguration.DEFAULT_FAIL_ACTION) { - case AppGuardianConfiguration.BLOCK: - if (response != null) { - response.setStatus(appGuardConfig.getDefaultResponseCode()); - } else { - httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); - } - return; - - case AppGuardianConfiguration.REDIRECT: - sendRedirect(response, httpResponse); - return; - } - } - } - } - - /* - * Now that we've run our last set of rules we can allow the response to - * go through if we were intercepting. - */ - - if (response != null) { - logger.debug(Logger.EVENT_SUCCESS, ">>> committing reponse"); - response.commit(); - } - } - - /* - * Utility method to send HTTP redirects that automatically determines which - * response class to use. - */ - private void sendRedirect(InterceptingHTTPServletResponse response, HttpServletResponse httpResponse, - String redirectURL) throws IOException { - - if (response != null) { // if we've been buffering everything we clean - // it all out before sending back. - response.reset(); - response.resetBuffer(); - response.sendRedirect(redirectURL); - response.commit(); - } else { - httpResponse.sendRedirect(redirectURL); - } - - } - - public void destroy() { - /* - * Any cleanup necessary? - */ - } - - private void sendRedirect(InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) - throws IOException { - /* - * [chrisisbeef] - commented out as this is not currently used. Minor - * performance tweak. String finalJavaScript = - * AppGuardianConfiguration.JAVASCRIPT_REDIRECT; finalJavaScript = - * finalJavaScript.replaceAll(AppGuardianConfiguration. - * JAVASCRIPT_TARGET_TOKEN, appGuardConfig.getDefaultErrorPage()); - */ - - if (response != null) { - response.reset(); - response.resetBuffer(); - /* - * response.setStatus(appGuardConfig.getDefaultResponseCode()); - * response.getOutputStream().write(finalJavaScript.getBytes()); - */ - response.sendRedirect(appGuardConfig.getDefaultErrorPage()); - - } else { - if (!httpResponse.isCommitted()) { - httpResponse.sendRedirect(appGuardConfig.getDefaultErrorPage()); - } else { - /* - * Can't send redirect because response is already committed. - * I'm not sure how this could happen, but I didn't want to - * cause IOExceptions in case if it ever does. - */ - } - - } - } + private AppGuardianConfiguration appGuardConfig; + + private static final String CONFIGURATION_FILE_PARAM = "configuration"; + private static final String LOGGING_FILE_PARAM = "log_settings"; + private static final String POLLING_TIME_PARAM = "polling_time"; + + private static final int DEFAULT_POLLING_TIME = 30000; + + private String configurationFilename = null; + + private long pollingTime; + + private long lastConfigReadTime; + + // private static final String FAUX_SESSION_COOKIE = "FAUXSC"; + // private static final String SESSION_COOKIE_CANARY = + // "org.owasp.esapi.waf.canary"; + + private FilterConfig fc; + + private final Logger logger = ESAPI.getLogger(ESAPIWebApplicationFirewallFilter.class); + + /** + * This function is used in testing to dynamically alter the configuration. + * + * @param policyFilePath + * The path to the policy file + * @param webRootDir + * The root directory of the web application. + * @throws FileNotFoundException + * if the policy file cannot be located + */ + public void setConfiguration(String policyFilePath, String webRootDir) throws FileNotFoundException { + + FileInputStream inputStream = null; + + try { + inputStream = new FileInputStream(new File(policyFilePath)); + appGuardConfig = ConfigurationParser.readConfigurationFile(inputStream, webRootDir); + lastConfigReadTime = System.currentTimeMillis(); + configurationFilename = policyFilePath; + } catch (ConfigurationException e) { + // TODO: It would be ideal if this method threw the + // ConfigurationException rather than catching it and + // writing the error to the console. + e.printStackTrace(); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public AppGuardianConfiguration getConfiguration() { + return appGuardConfig; + } + + /** + * + * This function is invoked at application startup and when the + * configuration file polling period has elapsed and a change in the + * configuration file has been detected. + * + * It's main purpose is to read the configuration file and establish the + * configuration object model for use at runtime during the + * doFilter() method. + */ + public void init(FilterConfig fc) throws ServletException { + + /* + * This variable is saved so that we can retrieve it later to re-invoke + * this function. + */ + this.fc = fc; + + logger.debug(Logger.EVENT_SUCCESS, ">> Initializing WAF"); + /* + * Pull logging file. + */ + + /* + * Pull main configuration file. + */ + + configurationFilename = fc.getInitParameter(CONFIGURATION_FILE_PARAM); + + configurationFilename = fc.getServletContext().getRealPath(configurationFilename); + + if (configurationFilename == null || !new File(configurationFilename).exists()) { + throw new ServletException( + "[ESAPI WAF] Could not find configuration file at resolved path: " + configurationFilename); + } + + /* + * Find out polling time from a parameter. If none is provided, use the + * default (10 seconds). + */ + + String sPollingTime = fc.getInitParameter(POLLING_TIME_PARAM); + + if (sPollingTime != null) { + pollingTime = Long.parseLong(sPollingTime); + } else { + pollingTime = DEFAULT_POLLING_TIME; + } + + /* + * Open up configuration file and populate the AppGuardian configuration + * object. + */ + + FileInputStream inputStream = null; + + try { + String webRootDir = fc.getServletContext().getRealPath("/"); + inputStream = new FileInputStream(configurationFilename); + appGuardConfig = ConfigurationParser.readConfigurationFile(inputStream, webRootDir); + lastConfigReadTime = System.currentTimeMillis(); + } catch (FileNotFoundException e) { + throw new ServletException(e); + } catch (ConfigurationException e) { + throw new ServletException(e); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + /** + * This is the where the main interception and rule-checking logic of the + * WAF resides. + */ + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) + throws IOException, ServletException { + + /* + * Check to see if polling time has elapsed. If it has, that means we + * should check to see if the config file has been changed. If it has, + * then re-read it. + * + * // TODO: Any reason this logic shouldn't be moved into a polling + * thread class? + */ + + if ((System.currentTimeMillis() - lastConfigReadTime) > pollingTime) { + File f = new File(configurationFilename); + long lastModified = f.lastModified(); + if (lastModified > lastConfigReadTime) { + /* + * The file has been altered since it was read in the last time. + * Must re-read it. + */ + logger.debug(Logger.EVENT_SUCCESS, ">> Re-reading WAF policy"); + init(fc); + } + } + + logger.debug(Logger.EVENT_SUCCESS, ">>In WAF doFilter"); + + HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; + HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; + + InterceptingHTTPServletRequest request = null; + InterceptingHTTPServletResponse response = null; + + /* + * First thing to do is create the InterceptingHTTPServletResponse, + * since we'll need that possibly before the + * InterceptingHTTPServletRequest. + * + * The normal HttpRequest-type objects will suffice us until we get to + * stage 2. + * + * 1st argument = the response to base the instance on 2nd argument = + * should we bother intercepting the egress response? 3rd argument = + * cookie rules because thats where they mostly get acted on + */ + + if (appGuardConfig.getCookieRules().size() + appGuardConfig.getBeforeResponseRules().size() > 0) { + response = new InterceptingHTTPServletResponse(httpResponse, true, appGuardConfig.getCookieRules()); + } + + /* + * Stage 1: Rules that do not need the request body. + */ + logger.debug(Logger.EVENT_SUCCESS, ">> Starting stage 1"); + + List rules = this.appGuardConfig.getBeforeBodyRules(); + + for (int i = 0; i < rules.size(); i++) { + + Rule rule = rules.get(i); + logger.debug(Logger.EVENT_SUCCESS, " Applying BEFORE rule: " + rule.getClass().getName()); + + /* + * The rules execute in check(). The check() method will also log. + * All we have to do is decide what other actions to take. + */ + Action action = rule.check(httpRequest, response, httpResponse); + + if (action.isActionNecessary()) { + + if (action instanceof BlockAction) { + if (response != null) { + response.setStatus(appGuardConfig.getDefaultResponseCode()); + } else { + httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); + } + return; + + } else if (action instanceof RedirectAction) { + sendRedirect(response, httpResponse, ((RedirectAction) action).getRedirectURL()); + return; + + } else if (action instanceof DefaultAction) { + + switch (AppGuardianConfiguration.DEFAULT_FAIL_ACTION) { + case AppGuardianConfiguration.BLOCK: + if (response != null) { + response.setStatus(appGuardConfig.getDefaultResponseCode()); + } else { + httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); + } + return; + + case AppGuardianConfiguration.REDIRECT: + sendRedirect(response, httpResponse); + return; + } + } + } + } + + /* + * Create the InterceptingHTTPServletRequest. + */ + + try { + request = new InterceptingHTTPServletRequest((HttpServletRequest) servletRequest); + } catch (FileUploadException fue) { + logger.error(Logger.EVENT_SUCCESS, "Error Wrapping Request", fue); + } + + /* + * Stage 2: After the body has been read, but before the the application + * has gotten it. + */ + logger.debug(Logger.EVENT_SUCCESS, ">> Starting Stage 2"); + + rules = this.appGuardConfig.getAfterBodyRules(); + + for (int i = 0; i < rules.size(); i++) { + + Rule rule = rules.get(i); + logger.debug(Logger.EVENT_SUCCESS, " Applying BEFORE CHAIN rule: " + rule.getClass().getName()); + + /* + * The rules execute in check(). The check() method will take care + * of logging. All we have to do is decide what other actions to + * take. + */ + Action action = rule.check(request, response, httpResponse); + + if (action.isActionNecessary()) { + + if (action instanceof BlockAction) { + if (response != null) { + response.setStatus(appGuardConfig.getDefaultResponseCode()); + } else { + httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); + } + return; + + } else if (action instanceof RedirectAction) { + sendRedirect(response, httpResponse, ((RedirectAction) action).getRedirectURL()); + return; + + } else if (action instanceof DefaultAction) { + + switch (AppGuardianConfiguration.DEFAULT_FAIL_ACTION) { + case AppGuardianConfiguration.BLOCK: + if (response != null) { + response.setStatus(appGuardConfig.getDefaultResponseCode()); + } else { + httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); + } + return; + + case AppGuardianConfiguration.REDIRECT: + sendRedirect(response, httpResponse); + return; + } + } + } + } + + /* + * In between stages 2 and 3 is the application's processing of the + * input. + */ + logger.debug(Logger.EVENT_SUCCESS, ">> Calling the FilterChain: " + chain); + chain.doFilter(request, response != null ? response : httpResponse); + + /* + * Stage 3: Before the response has been sent back to the user. + */ + logger.debug(Logger.EVENT_SUCCESS, ">> Starting Stage 3"); + + rules = this.appGuardConfig.getBeforeResponseRules(); + + for (int i = 0; i < rules.size(); i++) { + + Rule rule = rules.get(i); + logger.debug(Logger.EVENT_SUCCESS, " Applying AFTER CHAIN rule: " + rule.getClass().getName()); + + /* + * The rules execute in check(). The check() method will also log. + * All we have to do is decide what other actions to take. + */ + Action action = rule.check(request, response, httpResponse); + + if (action.isActionNecessary()) { + + if (action instanceof BlockAction) { + if (response != null) { + response.setStatus(appGuardConfig.getDefaultResponseCode()); + } else { + httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); + } + return; + + } else if (action instanceof RedirectAction) { + sendRedirect(response, httpResponse, ((RedirectAction) action).getRedirectURL()); + return; + + } else if (action instanceof DefaultAction) { + + switch (AppGuardianConfiguration.DEFAULT_FAIL_ACTION) { + case AppGuardianConfiguration.BLOCK: + if (response != null) { + response.setStatus(appGuardConfig.getDefaultResponseCode()); + } else { + httpResponse.setStatus(appGuardConfig.getDefaultResponseCode()); + } + return; + + case AppGuardianConfiguration.REDIRECT: + sendRedirect(response, httpResponse); + return; + } + } + } + } + + /* + * Now that we've run our last set of rules we can allow the response to + * go through if we were intercepting. + */ + + if (response != null) { + logger.debug(Logger.EVENT_SUCCESS, ">>> committing reponse"); + response.commit(); + } + } + + /* + * Utility method to send HTTP redirects that automatically determines which + * response class to use. + */ + private void sendRedirect(InterceptingHTTPServletResponse response, HttpServletResponse httpResponse, + String redirectURL) throws IOException { + + if (response != null) { // if we've been buffering everything we clean + // it all out before sending back. + response.reset(); + response.resetBuffer(); + response.sendRedirect(redirectURL); + response.commit(); + } else { + httpResponse.sendRedirect(redirectURL); + } + + } + + public void destroy() { + /* + * Any cleanup necessary? + */ + } + + private void sendRedirect(InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) + throws IOException { + /* + * [chrisisbeef] - commented out as this is not currently used. Minor + * performance tweak. String finalJavaScript = + * AppGuardianConfiguration.JAVASCRIPT_REDIRECT; finalJavaScript = + * finalJavaScript.replaceAll(AppGuardianConfiguration. + * JAVASCRIPT_TARGET_TOKEN, appGuardConfig.getDefaultErrorPage()); + */ + + if (response != null) { + response.reset(); + response.resetBuffer(); + /* + * response.setStatus(appGuardConfig.getDefaultResponseCode()); + * response.getOutputStream().write(finalJavaScript.getBytes()); + */ + response.sendRedirect(appGuardConfig.getDefaultErrorPage()); + + } else { + if (!httpResponse.isCommitted()) { + httpResponse.sendRedirect(appGuardConfig.getDefaultErrorPage()); + } else { + /* + * Can't send redirect because response is already committed. + * I'm not sure how this could happen, but I didn't want to + * cause IOExceptions in case if it ever does. + */ + } + + } + } } diff --git a/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java b/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java index 8523c2ceb..aeeebb1e8 100644 --- a/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java +++ b/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java @@ -16,10 +16,8 @@ package org.owasp.esapi.waf.configuration; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import org.apache.log4j.Level; import org.owasp.esapi.waf.rules.Rule; /** @@ -46,32 +44,6 @@ public class AppGuardianConfiguration { public static final int OPERATOR_IN_LIST = 2; public static final int OPERATOR_EXISTS = 3; - //// TODO - Delete these comments and the next 2 declarations on log4j clean-up. - /* - * We have static copies of the log settings so that the Rule objects - * can access them, because they don't have access to the instance of - * the configuration object. - */ - /** - * @deprecated This {@code LOG_LEVEL} has never actually been used - * internally and this will be deleted when we remove all Log4J 1.x - * references. - */ - @Deprecated - public static Level LOG_LEVEL = Level.INFO; - /** - * @deprecated This {@code LOG_DIRECTORY} has never actually been used - * internally and this will be deleted when we remove all Log4J 1.x - * references. - */ - @Deprecated - public static String LOG_DIRECTORY = "/WEB-INF/logs"; - - /* - * Logging settings. - */ - private Level logLevel = Level.INFO; - private String logDirectory = "/WEB-INF/logs"; /* * Default settings. diff --git a/src/test/java/org/owasp/esapi/logging/log4j/Log4JLogBridgeImplTest.java b/src/test/java/org/owasp/esapi/logging/log4j/Log4JLogBridgeImplTest.java deleted file mode 100644 index f3bf41582..000000000 --- a/src/test/java/org/owasp/esapi/logging/log4j/Log4JLogBridgeImplTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/** - * 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. - * - * @created 2019 - */ -package org.owasp.esapi.logging.log4j; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TestName; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; -import org.owasp.esapi.Logger; -import org.owasp.esapi.Logger.EventType; -import org.owasp.esapi.logging.appender.LogAppender; -import org.owasp.esapi.logging.cleaning.LogScrubber; - -public class Log4JLogBridgeImplTest { - - @Rule - public TestName testName = new TestName(); - @Rule - public ExpectedException exEx = ExpectedException.none(); - - private LogScrubber mockScrubber = Mockito.mock(LogScrubber.class); - private LogAppender mockAppender = Mockito.mock(LogAppender.class); - private Log4JLogLevelHandler mockHandler = Mockito.mock(Log4JLogLevelHandler.class); - private org.apache.log4j.Logger log4JSpy; - private Throwable testEx = new Throwable(testName.getMethodName()); - private Log4JLogBridge bridge; - - @Before - public void setup() { - Map levelLookup = new HashMap<>(); - levelLookup.put(Logger.ALL, mockHandler); - - org.apache.log4j.Logger wrappedLogger =org.apache.log4j.Logger.getLogger(testName.getMethodName()); - log4JSpy = Mockito.spy(wrappedLogger); - bridge = new Log4JLogBridgeImpl(mockAppender, mockScrubber, levelLookup); - } - - @Test - public void testLogMessageWithUnmappedEsapiLevelThrowsException() { - exEx.expect(IllegalArgumentException.class); - exEx.expectMessage("Unable to lookup LOG4J level mapping"); - Map emptyMap = Collections.emptyMap(); - new Log4JLogBridgeImpl(mockAppender, mockScrubber, emptyMap).log(log4JSpy, 0, Logger.EVENT_UNSPECIFIED, "This Should fail"); - } - - @Test - public void testLogMessageAndExceptionWithUnmappedEsapiLevelThrowsException() { - exEx.expect(IllegalArgumentException.class); - exEx.expectMessage("Unable to lookup LOG4J level mapping"); - Map emptyMap = Collections.emptyMap(); - new Log4JLogBridgeImpl(mockAppender, mockScrubber, emptyMap).log(log4JSpy, 0, Logger.EVENT_UNSPECIFIED, "This Should fail", testEx); - } - - @Test - public void testLogMessage() { - EventType eventType = Logger.EVENT_UNSPECIFIED; - String loggerName = testName.getMethodName(); - String orignMsg = testName.getMethodName(); - String appendMsg = "[APPEND] " + orignMsg; - String cleanMsg = appendMsg + " [CLEANED]"; - - //Setup for Appender - Mockito.when(mockAppender.appendTo(loggerName, eventType, orignMsg)).thenReturn(appendMsg); - //Setup for Scrubber - Mockito.when(mockScrubber.cleanMessage(appendMsg)).thenReturn(cleanMsg); - //Setup for Delegate Handler - Mockito.when(mockHandler.isEnabled(log4JSpy)).thenReturn(true); - - bridge.log(log4JSpy, Logger.ALL, eventType, testName.getMethodName()); - - Mockito.verify(mockAppender, Mockito.times(1)).appendTo(loggerName, eventType, testName.getMethodName()); - Mockito.verify(mockScrubber, Mockito.times(1)).cleanMessage(appendMsg); - Mockito.verify(mockHandler, Mockito.times(1)).isEnabled(log4JSpy); - Mockito.verify(mockHandler, Mockito.times(0)).log(ArgumentMatchers.any(org.apache.log4j.Logger.class), ArgumentMatchers.any(String.class), ArgumentMatchers.any(Throwable.class)); - Mockito.verify(mockHandler, Mockito.times(1)).log(ArgumentMatchers.same(log4JSpy), ArgumentMatchers.eq(cleanMsg)); - - Mockito.verifyNoMoreInteractions(log4JSpy, mockAppender, mockScrubber,mockHandler); - } - - @Test - public void testLogErrorMessageWithException() { - EventType eventType = Logger.EVENT_UNSPECIFIED; - String loggerName = testName.getMethodName(); - String orignMsg = testName.getMethodName(); - String appendMsg = "[APPEND] " + orignMsg; - String cleanMsg = appendMsg + " [CLEANED]"; - - //Setup for Appender - Mockito.when(mockAppender.appendTo(loggerName, eventType, orignMsg)).thenReturn(appendMsg); - //Setup for Scrubber - Mockito.when(mockScrubber.cleanMessage(appendMsg)).thenReturn(cleanMsg); - //Setup for Delegate Handler - Mockito.when(mockHandler.isEnabled(log4JSpy)).thenReturn(true); - - bridge.log(log4JSpy, Logger.ALL, eventType, testName.getMethodName(), testEx); - - Mockito.verify(mockAppender, Mockito.times(1)).appendTo(loggerName, eventType, testName.getMethodName()); - Mockito.verify(mockScrubber, Mockito.times(1)).cleanMessage(appendMsg); - Mockito.verify(mockHandler, Mockito.times(1)).isEnabled(log4JSpy); - Mockito.verify(mockHandler, Mockito.times(0)).log(ArgumentMatchers.any(org.apache.log4j.Logger.class), ArgumentMatchers.any(String.class)); - - Mockito.verify(mockHandler, Mockito.times(1)).log(ArgumentMatchers.same(log4JSpy), ArgumentMatchers.eq(cleanMsg), ArgumentMatchers.same(testEx)); - - Mockito.verifyNoMoreInteractions(log4JSpy, mockAppender, mockScrubber,mockHandler); - } - - - @Test - public void testDisabledLogMessage() { - Mockito.when(mockHandler.isEnabled(log4JSpy)).thenReturn(false); - - bridge.log(log4JSpy, Logger.ALL, Logger.EVENT_UNSPECIFIED, testName.getMethodName()); - - Mockito.verify(mockHandler, Mockito.times(1)).isEnabled(log4JSpy); - Mockito.verify(mockScrubber, Mockito.times(0)).cleanMessage(ArgumentMatchers.anyString()); - Mockito.verify(mockHandler, Mockito.times(0)).log(ArgumentMatchers.any(org.apache.log4j.Logger.class), ArgumentMatchers.any(String.class)); - Mockito.verify(mockHandler, Mockito.times(0)).log(ArgumentMatchers.any(org.apache.log4j.Logger.class), ArgumentMatchers.any(String.class), ArgumentMatchers.any(Throwable.class)); - } - - @Test - public void testDisabledErrorLogWithException() { - Mockito.when(mockHandler.isEnabled(log4JSpy)).thenReturn(false); - - bridge.log(log4JSpy, Logger.ALL, Logger.EVENT_UNSPECIFIED, testName.getMethodName(), testEx); - - Mockito.verify(mockHandler, Mockito.times(1)).isEnabled(log4JSpy); - Mockito.verify(mockScrubber, Mockito.times(0)).cleanMessage(ArgumentMatchers.anyString()); - Mockito.verify(mockHandler, Mockito.times(0)).log(ArgumentMatchers.any(org.apache.log4j.Logger.class), ArgumentMatchers.any(String.class)); - Mockito.verify(mockHandler, Mockito.times(0)).log(ArgumentMatchers.any(org.apache.log4j.Logger.class), ArgumentMatchers.any(String.class), ArgumentMatchers.any(Throwable.class)); - - } - -} diff --git a/src/test/java/org/owasp/esapi/logging/log4j/Log4JLogFactoryTest.java b/src/test/java/org/owasp/esapi/logging/log4j/Log4JLogFactoryTest.java deleted file mode 100644 index 3e186480d..000000000 --- a/src/test/java/org/owasp/esapi/logging/log4j/Log4JLogFactoryTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * 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. - * - * @created 2019 - */ -package org.owasp.esapi.logging.log4j; - -import java.util.List; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.owasp.esapi.Logger; -import org.owasp.esapi.logging.appender.LogAppender; -import org.owasp.esapi.logging.appender.LogPrefixAppender; -import org.owasp.esapi.logging.cleaning.CodecLogScrubber; -import org.owasp.esapi.logging.cleaning.CompositeLogScrubber; -import org.owasp.esapi.logging.cleaning.LogScrubber; -import org.owasp.esapi.logging.cleaning.NewlineLogScrubber; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -@RunWith(PowerMockRunner.class) -@PrepareForTest (Log4JLogFactory.class) -public class Log4JLogFactoryTest { - @Rule - public TestName testName = new TestName(); - - @Test - public void testCreateLoggerByString() { - Logger logger = new Log4JLogFactory().getLogger("test"); - Assert.assertTrue(logger instanceof Log4JLogger); - } - - @Test public void testCreateLoggerByClass() { - Logger logger = new Log4JLogFactory().getLogger(Log4JLogBridgeImplTest.class); - Assert.assertTrue(logger instanceof Log4JLogger); - } - - @Test - public void checkScrubberWithEncoding() throws Exception { - ArgumentCaptor delegates = ArgumentCaptor.forClass(List.class); - PowerMockito.whenNew(CompositeLogScrubber.class).withArguments(delegates.capture()).thenReturn(null); - - //Call to invoke the constructor capture - Log4JLogFactory.createLogScrubber(true); - - List scrubbers = delegates.getValue(); - Assert.assertEquals(2, scrubbers.size()); - Assert.assertTrue(scrubbers.get(0) instanceof NewlineLogScrubber); - Assert.assertTrue(scrubbers.get(1) instanceof CodecLogScrubber); - } - - @Test - public void checkScrubberWithoutEncoding() throws Exception { - ArgumentCaptor delegates = ArgumentCaptor.forClass(List.class); - PowerMockito.whenNew(CompositeLogScrubber.class).withArguments(delegates.capture()).thenReturn(null); - - //Call to invoke the constructor capture - Log4JLogFactory.createLogScrubber(false); - - List scrubbers = delegates.getValue(); - Assert.assertEquals(1, scrubbers.size()); - Assert.assertTrue(scrubbers.get(0) instanceof NewlineLogScrubber); - } - - /** - * At this time there are no special considerations or handling for the appender - * creation in this scope. It is expected that the arguments to the internal - * creation method are passed directly to the constructor of the - * LogPrefixAppender with no mutation or additional validation. - */ - @Test - public void checkPassthroughAppenderConstruct() throws Exception { - LogPrefixAppender stubAppender = new LogPrefixAppender(true, true, true, true, ""); - ArgumentCaptor userInfoCapture = ArgumentCaptor.forClass(Boolean.class); - ArgumentCaptor clientInfoCapture = ArgumentCaptor.forClass(Boolean.class); - ArgumentCaptor serverInfoCapture = ArgumentCaptor.forClass(Boolean.class); - ArgumentCaptor logAppNameCapture = ArgumentCaptor.forClass(Boolean.class); - ArgumentCaptor appNameCapture = ArgumentCaptor.forClass(String.class); - - PowerMockito.whenNew(LogPrefixAppender.class).withArguments(userInfoCapture.capture(), clientInfoCapture.capture(), serverInfoCapture.capture(), logAppNameCapture.capture(), appNameCapture.capture()).thenReturn(stubAppender); - - LogAppender appender = Log4JLogFactory.createLogAppender(true, true, false, true, testName.getMethodName()); - - Assert.assertEquals(stubAppender, appender); - Assert.assertTrue(userInfoCapture.getValue()); - Assert.assertTrue(clientInfoCapture.getValue()); - Assert.assertFalse(serverInfoCapture.getValue()); - Assert.assertTrue(logAppNameCapture.getValue()); - Assert.assertEquals(testName.getMethodName(), appNameCapture.getValue()); - } - - -} diff --git a/src/test/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandlersTest.java b/src/test/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandlersTest.java deleted file mode 100644 index 149617f91..000000000 --- a/src/test/java/org/owasp/esapi/logging/log4j/Log4JLogLevelHandlersTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * 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. - * - * @created 2019 - */ -package org.owasp.esapi.logging.log4j; - -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; -import org.mockito.Mockito; -import org.owasp.esapi.logging.log4j.Log4JLogLevelHandlers; - -public class Log4JLogLevelHandlersTest { - - private Logger mockLogger = Mockito.mock(Logger.class); - @Rule - public TestName testName = new TestName(); - - private Throwable testException = new Throwable("Expected for testing"); - - @Test - public void testFatalDelegation() { - Log4JLogLevelHandlers.FATAL.isEnabled(mockLogger); - Log4JLogLevelHandlers.FATAL.log(mockLogger, testName.getMethodName()); - Log4JLogLevelHandlers.FATAL.log(mockLogger, testName.getMethodName(), testException); - - Mockito.verify(mockLogger, Mockito.times(1)).isEnabledFor(Level.FATAL); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.FATAL, testName.getMethodName()); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.FATAL, testName.getMethodName(), testException); - Mockito.verifyNoMoreInteractions(mockLogger); - } - - - @Test - public void testErrorDelegation() { - Log4JLogLevelHandlers.ERROR.isEnabled(mockLogger); - Log4JLogLevelHandlers.ERROR.log(mockLogger, testName.getMethodName()); - Log4JLogLevelHandlers.ERROR.log(mockLogger, testName.getMethodName(), testException); - - Mockito.verify(mockLogger, Mockito.times(1)).isEnabledFor(Level.ERROR); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.ERROR, testName.getMethodName()); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.ERROR, testName.getMethodName(), testException); - Mockito.verifyNoMoreInteractions(mockLogger); - } - - @Test - public void testWarnDelegation() { - Log4JLogLevelHandlers.WARN.isEnabled(mockLogger); - Log4JLogLevelHandlers.WARN.log(mockLogger, testName.getMethodName()); - Log4JLogLevelHandlers.WARN.log(mockLogger, testName.getMethodName(), testException); - - Mockito.verify(mockLogger, Mockito.times(1)).isEnabledFor(Level.WARN); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.WARN, testName.getMethodName()); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.WARN, testName.getMethodName(), testException); - Mockito.verifyNoMoreInteractions(mockLogger); - } - @Test - public void testInfoDelegation() { - Log4JLogLevelHandlers.INFO.isEnabled(mockLogger); - Log4JLogLevelHandlers.INFO.log(mockLogger, testName.getMethodName()); - Log4JLogLevelHandlers.INFO.log(mockLogger, testName.getMethodName(), testException); - - Mockito.verify(mockLogger, Mockito.times(1)).isEnabledFor(Level.INFO); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.INFO, testName.getMethodName()); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.INFO, testName.getMethodName(), testException); - Mockito.verifyNoMoreInteractions(mockLogger); - } - @Test - public void testDebugDelegation() { - Log4JLogLevelHandlers.DEBUG.isEnabled(mockLogger); - Log4JLogLevelHandlers.DEBUG.log(mockLogger, testName.getMethodName()); - Log4JLogLevelHandlers.DEBUG.log(mockLogger, testName.getMethodName(), testException); - - Mockito.verify(mockLogger, Mockito.times(1)).isEnabledFor(Level.DEBUG); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.DEBUG, testName.getMethodName()); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.DEBUG, testName.getMethodName(), testException); - Mockito.verifyNoMoreInteractions(mockLogger); - } - @Test - public void testTraceDelegation() { - Log4JLogLevelHandlers.TRACE.isEnabled(mockLogger); - Log4JLogLevelHandlers.TRACE.log(mockLogger, testName.getMethodName()); - Log4JLogLevelHandlers.TRACE.log(mockLogger, testName.getMethodName(), testException); - - Mockito.verify(mockLogger, Mockito.times(1)).isEnabledFor(Level.TRACE); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.TRACE, testName.getMethodName()); - Mockito.verify(mockLogger, Mockito.times(1)).log(Level.TRACE, testName.getMethodName(), testException); - Mockito.verifyNoMoreInteractions(mockLogger); - } -} diff --git a/src/test/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactoryTest.java b/src/test/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactoryTest.java deleted file mode 100644 index 5d73047d3..000000000 --- a/src/test/java/org/owasp/esapi/logging/log4j/Log4JLoggerFactoryTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * 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 2019 - */ -package org.owasp.esapi.logging.log4j; - -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.log4j.spi.LoggerRepository; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; -import org.junit.runner.RunWith; -import org.mockito.ArgumentMatchers; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; -import org.owasp.esapi.logging.appender.LogAppender; -import org.owasp.esapi.logging.cleaning.LogScrubber; -import org.powermock.reflect.Whitebox; - -/** - * Basic test implementation that verifies that the {@link LogAppender} and - * {@link LogScrubber} references are applied by the {@link Logger} instances - * created by the {@link Log4JLoggerFactory}. - * - */ -@RunWith(MockitoJUnitRunner.class) -public class Log4JLoggerFactoryTest { - @Mock - private LogScrubber scrubber; - @Mock - private LogAppender appender; - @Rule - public TestName testName = new TestName(); - - private String logMsg = testName.getMethodName() + "-MESSAGE"; - private Logger logger; - - @Before - public void configureStaticFactoryState() { - Log4JLoggerFactory factory = new Log4JLoggerFactory(); - Whitebox.setInternalState(Log4JLoggerFactory.class, "LOG4J_LOG_SCRUBBER", scrubber); - Whitebox.setInternalState(Log4JLoggerFactory.class, "LOG4J_LOG_APPENDER", appender); - - Mockito.when(scrubber.cleanMessage(logMsg)).thenReturn(logMsg); - Mockito.when(appender.appendTo(testName.getMethodName(), null, logMsg)).thenReturn(logMsg); - - LoggerRepository mockRepo = Mockito.mock(LoggerRepository.class); - Mockito.when(mockRepo.isDisabled(ArgumentMatchers.anyInt())).thenReturn(false); - - logger = factory.makeNewLoggerInstance(testName.getMethodName()); - Whitebox.setInternalState(logger, "repository", mockRepo); - logger.setLevel(Level.ALL); - } - - @Test - public void testLogDebug() { - logger.debug(logMsg); - Mockito.verify(scrubber, Mockito.times(1)).cleanMessage(logMsg); - Mockito.verify(appender, Mockito.times(1)).appendTo(testName.getMethodName(), null, logMsg); - } - - @Test - public void testLogInfo() { - logger.info(logMsg); - Mockito.verify(scrubber, Mockito.times(1)).cleanMessage(logMsg); - Mockito.verify(appender, Mockito.times(1)).appendTo(testName.getMethodName(), null, logMsg); - } - - @Test - public void testLogWarn() { - logger.warn(logMsg); - Mockito.verify(scrubber, Mockito.times(1)).cleanMessage(logMsg); - Mockito.verify(appender, Mockito.times(1)).appendTo(testName.getMethodName(), null, logMsg); - } - - @Test - public void testLogError() { - logger.error(logMsg); - Mockito.verify(scrubber, Mockito.times(1)).cleanMessage(logMsg); - Mockito.verify(appender, Mockito.times(1)).appendTo(testName.getMethodName(), null, logMsg); - } - -} diff --git a/src/test/java/org/owasp/esapi/logging/log4j/Log4JLoggerTest.java b/src/test/java/org/owasp/esapi/logging/log4j/Log4JLoggerTest.java deleted file mode 100644 index 16834f288..000000000 --- a/src/test/java/org/owasp/esapi/logging/log4j/Log4JLoggerTest.java +++ /dev/null @@ -1,287 +0,0 @@ -/** - * 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. - * - * @created 2019 - */ - -package org.owasp.esapi.logging.log4j; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; -import org.owasp.esapi.Logger; -import org.owasp.esapi.logging.log4j.Log4JLogBridge; -import org.owasp.esapi.logging.log4j.Log4JLogger; - -public class Log4JLoggerTest { - - private static final String MSG = Log4JLoggerTest.class.getSimpleName(); - - private Log4JLogBridge mockBridge = Mockito.mock(Log4JLogBridge.class); - private org.apache.log4j.Logger mockLogDelegate = Mockito.mock(org.apache.log4j.Logger.class); - - private Throwable testEx = new Throwable(MSG + "_Exception"); - private Logger testLogger = new Log4JLogger(mockLogDelegate, mockBridge, Logger.ALL); - - @Test - public void testLevelEnablement() { - testLogger.setLevel(Logger.INFO); - - Assert.assertTrue(testLogger.isFatalEnabled()); - Assert.assertTrue(testLogger.isErrorEnabled()); - Assert.assertTrue(testLogger.isWarningEnabled()); - Assert.assertTrue(testLogger.isInfoEnabled()); - Assert.assertFalse(testLogger.isDebugEnabled()); - Assert.assertFalse(testLogger.isTraceEnabled()); - - Assert.assertEquals(Logger.INFO, testLogger.getESAPILevel()); - } - - @Test - public void testAllLevelEnablement() { - testLogger.setLevel(Logger.ALL); - - Assert.assertTrue(testLogger.isFatalEnabled()); - Assert.assertTrue(testLogger.isErrorEnabled()); - Assert.assertTrue(testLogger.isWarningEnabled()); - Assert.assertTrue(testLogger.isInfoEnabled()); - Assert.assertTrue(testLogger.isDebugEnabled()); - Assert.assertTrue(testLogger.isTraceEnabled()); - } - - @Test - public void testOffLevelEnablement() { - testLogger.setLevel(Logger.OFF); - - Assert.assertFalse(testLogger.isFatalEnabled()); - Assert.assertFalse(testLogger.isErrorEnabled()); - Assert.assertFalse(testLogger.isWarningEnabled()); - Assert.assertFalse(testLogger.isInfoEnabled()); - Assert.assertFalse(testLogger.isDebugEnabled()); - Assert.assertFalse(testLogger.isTraceEnabled()); - } - @Test - public void testFatalWithMessage() { - testLogger.fatal(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.FATAL, Logger.EVENT_UNSPECIFIED, MSG); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testFatalWithMessageAndThrowable() { - testLogger.fatal(Logger.EVENT_UNSPECIFIED, MSG, testEx); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.FATAL, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testFatalWithMessageDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.fatal(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.FATAL, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testFatalWithMessageAndThrowableDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.fatal(Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.FATAL, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testErrorWithMessage() { - testLogger.error(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.ERROR, Logger.EVENT_UNSPECIFIED, MSG); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testErrorWithMessageAndThrowable() { - testLogger.error(Logger.EVENT_UNSPECIFIED, MSG, testEx); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.ERROR, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testErrorWithMessageDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.error(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.ERROR, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testErrorWithMessageAndThrowableDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.error(Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.ERROR, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testWarnWithMessage() { - testLogger.warning(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.WARNING, Logger.EVENT_UNSPECIFIED, MSG); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testWarnWithMessageAndThrowable() { - testLogger.warning(Logger.EVENT_UNSPECIFIED, MSG, testEx); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.WARNING, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testWarnWithMessageDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.warning(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.WARNING, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testWarnWithMessageAndThrowableDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.warning(Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.WARNING, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testInfoWithMessage() { - testLogger.info(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.INFO, Logger.EVENT_UNSPECIFIED, MSG); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testInfoWithMessageAndThrowable() { - testLogger.info(Logger.EVENT_UNSPECIFIED, MSG, testEx); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.INFO, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testInfoWithMessageDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.info(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.INFO, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testInfoWithMessageAndThrowableDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.info(Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.INFO, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testDebugWithMessage() { - testLogger.debug(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.DEBUG, Logger.EVENT_UNSPECIFIED, MSG); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testDebugWithMessageAndThrowable() { - testLogger.debug(Logger.EVENT_UNSPECIFIED, MSG, testEx); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.DEBUG, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testDebugWithMessageDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.debug(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.DEBUG, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testDebugWithMessageAndThrowableDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.debug(Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.DEBUG, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testTraceWithMessage() { - testLogger.trace(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.TRACE, Logger.EVENT_UNSPECIFIED, MSG); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testTraceWithMessageAndThrowable() { - testLogger.trace(Logger.EVENT_UNSPECIFIED, MSG, testEx); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.TRACE, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testTraceWithMessageDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.trace(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.TRACE, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testTraceWithMessageAndThrowableDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.trace(Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.TRACE, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testAlwaysWithMessage() { - testLogger.always(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.ALL, Logger.EVENT_UNSPECIFIED, MSG); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testAlwaysWithMessageAndThrowable() { - testLogger.always(Logger.EVENT_UNSPECIFIED, MSG, testEx); - - Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.ALL, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - - @Test - public void testAlwaysWithMessageDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.always(Logger.EVENT_UNSPECIFIED, MSG); - - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.ALL, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } - @Test - public void testAlwaysWithMessageAndThrowableDisabled() { - testLogger.setLevel(Logger.OFF); - testLogger.always(Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.ALL, Logger.EVENT_UNSPECIFIED, MSG, testEx); - Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); - } -} diff --git a/src/test/resources/esapi/ESAPI-CommaValidatorFileChecker.properties b/src/test/resources/esapi/ESAPI-CommaValidatorFileChecker.properties index 5f10329c6..9e6d67616 100644 --- a/src/test/resources/esapi/ESAPI-CommaValidatorFileChecker.properties +++ b/src/test/resources/esapi/ESAPI-CommaValidatorFileChecker.properties @@ -104,10 +104,7 @@ ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector -# Log4JFactory Requires log4j.xml or log4j.properties in classpath - http://www.laliluna.de/log4j-tutorial.html -ESAPI.Logger=org.owasp.esapi.logging.log4j.Log4JLogFactory -#ESAPI.Logger=org.owasp.esapi.reference.JavaLogFactory -#ESAPI.Logger=org.owasp.esapi.reference.ExampleExtendedLog4JLogFactory +ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory ESAPI.Randomizer=org.owasp.esapi.reference.DefaultRandomizer ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator diff --git a/src/test/resources/esapi/ESAPI-DualValidatorFileChecker.properties b/src/test/resources/esapi/ESAPI-DualValidatorFileChecker.properties index 74e645a20..625071607 100644 --- a/src/test/resources/esapi/ESAPI-DualValidatorFileChecker.properties +++ b/src/test/resources/esapi/ESAPI-DualValidatorFileChecker.properties @@ -104,10 +104,7 @@ ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector -# Log4JFactory Requires log4j.xml or log4j.properties in classpath - http://www.laliluna.de/log4j-tutorial.html -ESAPI.Logger=org.owasp.esapi.logging.log4j.Log4JLogFactory -#ESAPI.Logger=org.owasp.esapi.reference.JavaLogFactory -#ESAPI.Logger=org.owasp.esapi.reference.ExampleExtendedLog4JLogFactory +ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory ESAPI.Randomizer=org.owasp.esapi.reference.DefaultRandomizer ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator diff --git a/src/test/resources/esapi/ESAPI-QuotedValidatorFileChecker.properties b/src/test/resources/esapi/ESAPI-QuotedValidatorFileChecker.properties index 4b0a8a33d..46784ceff 100644 --- a/src/test/resources/esapi/ESAPI-QuotedValidatorFileChecker.properties +++ b/src/test/resources/esapi/ESAPI-QuotedValidatorFileChecker.properties @@ -103,10 +103,7 @@ ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector -# Log4JFactory Requires log4j.xml or log4j.properties in classpath - http://www.laliluna.de/log4j-tutorial.html -ESAPI.Logger=org.owasp.esapi.logging.log4j.Log4JLogFactory -#ESAPI.Logger=org.owasp.esapi.reference.JavaLogFactory -#ESAPI.Logger=org.owasp.esapi.reference.ExampleExtendedLog4JLogFactory +ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory ESAPI.Randomizer=org.owasp.esapi.reference.DefaultRandomizer ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator diff --git a/src/test/resources/esapi/ESAPI-SingleValidatorFileChecker.properties b/src/test/resources/esapi/ESAPI-SingleValidatorFileChecker.properties index 462d04721..f3742cee8 100644 --- a/src/test/resources/esapi/ESAPI-SingleValidatorFileChecker.properties +++ b/src/test/resources/esapi/ESAPI-SingleValidatorFileChecker.properties @@ -103,10 +103,7 @@ ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector -# Log4JFactory Requires log4j.xml or log4j.properties in classpath - http://www.laliluna.de/log4j-tutorial.html -ESAPI.Logger=org.owasp.esapi.logging.log4j.Log4JLogFactory -#ESAPI.Logger=org.owasp.esapi.reference.JavaLogFactory -#ESAPI.Logger=org.owasp.esapi.reference.ExampleExtendedLog4JLogFactory +ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory ESAPI.Randomizer=org.owasp.esapi.reference.DefaultRandomizer ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator diff --git a/src/test/resources/esapi/ESAPI.properties b/src/test/resources/esapi/ESAPI.properties index 29bc7b3dd..d9e12ce9c 100644 --- a/src/test/resources/esapi/ESAPI.properties +++ b/src/test/resources/esapi/ESAPI.properties @@ -96,9 +96,6 @@ ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector -# Log4JFactory Requires log4j.xml or log4j.properties in classpath - http://www.laliluna.de/log4j-tutorial.html -# Note that this is now considered deprecated! -#ESAPI.Logger=org.owasp.esapi.logging.log4j.Log4JLogFactory ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory # To use the new SLF4J logger in ESAPI (see GitHub issue #129), set # ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory diff --git a/src/test/resources/log4j.dtd b/src/test/resources/log4j.dtd deleted file mode 100644 index 1aabd96c3..000000000 --- a/src/test/resources/log4j.dtd +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/resources/log4j.xml b/src/test/resources/log4j.xml deleted file mode 100644 index 9b06c2a23..000000000 --- a/src/test/resources/log4j.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/suppressions.xml b/suppressions.xml index a67ad0522..b367558ce 100644 --- a/suppressions.xml +++ b/suppressions.xml @@ -1,108 +1,6 @@ - - - ^log4j:log4j:1\.2\.17$ - cpe:/a:apache:log4j - CVE-2019-17571 - - - - ^log4j:log4j:1\.2\.17$ - cpe:/a:apache:log4j - CVE-2020-9488 - - - - ^log4j:log4j:1\.2\.17$ - cpe:/a:apache:log4j - CVE-2021-4104 - - - - ^log4j:log4j:1\.2\.17$ - cpe:/a:apache:log4j - CVE-2022-23305 - - - - ^log4j:log4j:1\.2\.17$ - cpe:/a:apache:log4j - CVE-2022-23307 - - - - ^log4j:log4j:1\.2\.17$ - cpe:/a:apache:log4j - CVE-2022-23302 - Date: Sat, 9 Jul 2022 23:38:01 -0400 Subject: [PATCH 013/197] Remove obsolete references to Log4J. --- scripts/esapi-release.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/esapi-release.sh b/scripts/esapi-release.sh index 88c78e2fa..14253ff22 100755 --- a/scripts/esapi-release.sh +++ b/scripts/esapi-release.sh @@ -64,8 +64,8 @@ USAGE="Usage: $PROG esapi_svn_dir" tmpdir="/tmp/$PROG.$RANDOM-$$" esapi_release_dir="$tmpdir/esapi_release_dir" - # This is the directory under esapi_svn_dir where the log4j and ESAPI - # properties files are located as well as the $esapiConfig/* config files. + # This is the directory under esapi_svn_dir where ESAPI configuration files + # such as ESAPI.properties are located as well as the $esapiConfig/* config files. # Note that formerly used to be under src/main/resources, but it since # has been moved because where it was previously was causing problems with # Sonatype's Nexus. That particular problem may have been resolved, but it @@ -141,7 +141,7 @@ mkdir $jartmpdir cd $jartmpdir || exit jar xf "$jarfile" rm -fr ${esapiConfig:?} -rm -f properties/* log4j.* +rm -f properties/* rm -f settings.xml owasp-esapi-dev.jks # TODO: This part would need some work if we sign or seal the ESAPI jar as # that creates a special MANIFEST.MF file and other special files and From 4cead176683b527e146d97debae9884ea666bcf8 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sat, 9 Jul 2022 23:38:43 -0400 Subject: [PATCH 014/197] Revised obsolete references to Log4J 1 and mentioned it was removed in ESAPI 2.5.0.0. --- scripts/esapi4java-core-TEMPLATE-release-notes.txt | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/scripts/esapi4java-core-TEMPLATE-release-notes.txt b/scripts/esapi4java-core-TEMPLATE-release-notes.txt index b55fd969c..b4a953bf9 100644 --- a/scripts/esapi4java-core-TEMPLATE-release-notes.txt +++ b/scripts/esapi4java-core-TEMPLATE-release-notes.txt @@ -51,7 +51,7 @@ Issue # GitHub Issue Title @@@@ NOTE any special notes here. Probably leave this one, but I would suggest noting additions BEFORE this. [If you have already successfully been using ESAPI 2.2.1.0 or later, you probably can skip this section.] -Since ESAPI 2.2.1.0, the new default ESAPI logger is JUL (java.util.logging packages) and we have deprecated the use of Log4J 1.x because we now support SLF4J and Log4J 1.x is way past its end-of-life. We did not want to make SLF4J the default logger (at least not yet) as we did not want to have the default ESAPI use require additional dependencies. However, SLF4J is likely to be the future choice, at least once we start on ESAPI 3.0. A special shout-out to Jeremiah Stacey for making this possible by re-factoring much of the ESAPI logger code. Note, the straw that broke the proverbial camel's back was the announcement of CVE-2019-17571 (rated Critical), for which there is no fix available and likely will never be. +Since ESAPI 2.2.1.0, the new default ESAPI logger is JUL (java.util.logging packages) and we had deprecated the use of Log4J 1.x because was way past its end-of-life. (Note: As of ESAPI 2.5.0.0, we have officially removed all Log4J 1 dependencies, after it had been deprecated for 2 years as per our deprecation policy.) We did not want to make SLF4J the default logger (at least not yet) as we did not want to have the default ESAPI use require additional dependencies. However, SLF4J is likely to be the future choice, at least once we start on ESAPI 3.0. A special shout-out to Jeremiah Stacey for making this possible by re-factoring much of the ESAPI logger code. Note, the straw that broke the proverbial camel's back was the announcement of CVE-2019-17571 (rated Critical), for which there is no fix available and likely will never be. However, if you try to juse the new ESAPI 2.2.1.0 or later logging you will notice that you need to change ESAPI.Logger and also possibly provide some other properties as well to get the logging behavior that you desire. @@ -87,11 +87,6 @@ If you are using JavaLogFactory, you will also want to ensure that you have the See GitHub issue #560 for additional details. -Related to that aforemented Log4J 1.x CVE and how it affects ESAPI, be sure to read - https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf -which describes CVE-2019-17571, a deserialization vulnerability in Log4J 1.2.17. ESAPI is *NOT* affected by this (even if you chose to use Log4J 1 as you default ESAPI logger). This security bulletin describes why this CVE is not exploitable as used by ESAPI. - - Finally, while ESAPI still supports JDK 7 (even though that too is way past end-of-life), the next ESAPI release will move to JDK 8 as the minimal baseline. (We already use Java 8 for development but still to Java 7 source and runtime compatibility.) We need to do this out of necessity because some of our dependencies are no longer doing updates that support Java 7. ----------------------------------------------------------------------------- @@ -127,11 +122,6 @@ Another problem is if you run 'mvn test' from the 'cmd' prompt (and possibly Pow We believe these failures is because the maven-surefire-plugin is by default not forking a new JVM process for each test class. We are looking into this. For now, we have only have observed this behavior on Windows 10. If you see this error, please do NOT report it as a GitHub issue unless you know a fix for it. (And yes, we are aware of 'false' in the pom for the maven-surefire-plugin, but that causes other tests to fail that we haven't had time to fix.) - -Lastly, some SCA services may continue to flag vulnerabilties in ESAPI ${VERSION} related to log4j 1.2.17 (e.g., CVE-2020-9488). We do not believe the way that ESAPI uses log4j in a manner that leads to any exploitable behavior. See the security bulletins - https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf -for additional details. - ----------------------------------------------------------------------------- Other changes in this release, some of which not tracked via GitHub issues From 740b6473aa56725e9c39308aa33a012bfe5c5151 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sat, 9 Jul 2022 23:41:35 -0400 Subject: [PATCH 015/197] Remove references to log4j.dtd & log4j.xml since thev've been deleted. --- src/main/assembly/dist.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/assembly/dist.xml b/src/main/assembly/dist.xml index 3b2ee8e57..676039c82 100644 --- a/src/main/assembly/dist.xml +++ b/src/main/assembly/dist.xml @@ -38,8 +38,6 @@ configuration esapi/**/* - log4j.dtd - log4j.xml properties/**/* From c639ee665725ca72d954bd271b20f5c6d7dc0472 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sun, 10 Jul 2022 00:09:48 -0400 Subject: [PATCH 016/197] 1) Remove obsolete references to Log4J. 2) Javadoc clean-up. --- src/main/java/org/owasp/esapi/Logger.java | 61 +++++++++++++---------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/owasp/esapi/Logger.java b/src/main/java/org/owasp/esapi/Logger.java index c73e27ab2..7c4ccef9e 100644 --- a/src/main/java/org/owasp/esapi/Logger.java +++ b/src/main/java/org/owasp/esapi/Logger.java @@ -16,12 +16,12 @@ package org.owasp.esapi; /** - * The Logger interface defines a set of methods that can be used to log + * The {@code Logger} interface defines a set of methods that can be used to log * security events. It supports a hierarchy of logging levels which can be configured at runtime to determine * the severity of events that are logged, and those below the current threshold that are discarded. * Implementors should use a well established logging library * as it is quite difficult to create a high-performance logger. - *

+ *

* The logging levels defined by this interface (in descending order) are: *

    *
  • fatal (highest value)
  • @@ -33,9 +33,9 @@ *
* There are also several variations of {@code always()} methods that will always * log a message regardless of the log level. - *

+ *

* ESAPI also allows for the definition of the type of log event that is being generated. - * The Logger interface predefines 6 types of Log events: + * The {@code Logger} interface predefines 6 types of Log events: *

    *
  • SECURITY_SUCCESS
  • *
  • SECURITY_FAILURE
  • @@ -44,47 +44,54 @@ *
  • EVENT_FAILURE
  • *
  • EVENT_UNSPECIFIED
  • *
- *

- * Your implementation can extend or change this list if desired. - *

- * This Logger allows callers to determine which logging levels are enabled, and to submit events + *

+ * Your custom implementation can extend or change this list if desired. + *

+ * This {@code Logger} allows callers to determine which logging levels are enabled, and to submit events * at different severity levels.
*
Implementors of this interface should: * *

    - *
  1. provide a mechanism for setting the logging level threshold that is currently enabled. This usually works by logging all + *
  2. Provide a mechanism for setting the logging level threshold that is currently enabled. This usually works by logging all * events at and above that severity level, and discarding all events below that level. * This is usually done via configuration, but can also be made accessible programmatically.
  3. - *
  4. ensure that dangerous HTML characters are encoded before they are logged to defend against malicious injection into logs + *
  5. Ensure that dangerous HTML characters are encoded before they are logged to defend against malicious injection into logs * that might be viewed in an HTML based log viewer.
  6. - *
  7. encode any CRLF characters included in log data in order to prevent log injection attacks.
  8. - *
  9. avoid logging the user's session ID. Rather, they should log something equivalent like a + *
  10. Encode any CRLF characters included in log data in order to prevent log injection attacks.
  11. + *
  12. Avoid logging the user's session ID. Rather, they should log something equivalent like a * generated logging session ID, or a hashed value of the session ID so they can track session specific * events without risking the exposure of a live session's ID.
  13. - *
  14. record the following information with each event:
  15. + *
  16. Record the following information with each event:
  17. *
      - *
    1. identity of the user that caused the event,
    2. - *
    3. a description of the event (supplied by the caller),
    4. - *
    5. whether the event succeeded or failed (indicated by the caller),
    6. - *
    7. severity level of the event (indicated by the caller),
    8. - *
    9. that this is a security relevant event (indicated by the caller),
    10. - *
    11. hostname or IP where the event occurred (and ideally the user's source IP as well),
    12. - *
    13. a time stamp
    14. + *
    15. Identity of the user that caused the event.
    16. + *
    17. A description of the event (supplied by the caller).
    18. + *
    19. Whether the event succeeded or failed (indicated by the caller).
    20. + *
    21. Severity level of the event (indicated by the caller).
    22. + *
    23. That this is a security relevant event (indicated by the caller).
    24. + *
    25. Hostname or IP where the event occurred (and ideally the user's source IP as well).
    26. + *
    27. A date/time stamp.
    28. *
    *
* * Custom logger implementations might also: *
    - *
  1. filter out any sensitive data specific to the current application or organization, such as credit cards, + *
  2. Filter out any sensitive data specific to the current application or organization, such as credit cards, * social security numbers, etc.
  3. *
* - * There are both Log4j and native Java Logging default implementations. JavaLogger uses the java.util.logging package as the basis for its logging - * implementation. Both default implementations implements requirements #1 thru #5 above.
- *
- * Customization: It is expected that most organizations will implement their own custom Logger class in - * order to integrate ESAPI logging with their logging infrastructure. The ESAPI Reference Implementation - * is intended to provide a simple functional example of an implementation. + * There are both SLF4J and native Java Logging (i.e., {@code java.util.logging}, aka JUL) implementations + * of the ESAPI logger with JUL being our default logger for our stock ESAPI.properties file that + * is delivered along with ESAPI releases in a separate esapi-configuration jar available from the + * releases mentioned on + * ESAPI's GitHub Releases page. + *

+ * The {@code org.owasp.esapi.logging.java.JavaLogger} class uses the {@code java.util.logging} package as + * the basis for its logging implementation. Both provided implementations implement requirements #1 through #5 above. + *

+ * Customization: It is expected that most organizations may wish to implement their own custom {@code Logger} class in + * order to integrate ESAPI logging with their specific logging infrastructure. The ESAPI feference implementations + * can serve as a useful starting point to intended to provide a simple functional example of an implementation, but + * they are also largely usuable out-of-the-box with some additional minimal log configuration. * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security From 49983aa83ba0bcbc7be513f2f729889440d76d4e Mon Sep 17 00:00:00 2001 From: kwwall Date: Sun, 10 Jul 2022 00:17:28 -0400 Subject: [PATCH 017/197] Change Javadoc link from Log4JLoggerTest to JavaLoggerTest. --- src/test/java/org/owasp/esapi/reference/TestDebug.java | 2 +- src/test/java/org/owasp/esapi/reference/TestError.java | 2 +- src/test/java/org/owasp/esapi/reference/TestFatal.java | 2 +- src/test/java/org/owasp/esapi/reference/TestInfo.java | 2 +- src/test/java/org/owasp/esapi/reference/TestTrace.java | 2 +- src/test/java/org/owasp/esapi/reference/TestUnspecified.java | 2 +- src/test/java/org/owasp/esapi/reference/TestWarning.java | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/java/org/owasp/esapi/reference/TestDebug.java b/src/test/java/org/owasp/esapi/reference/TestDebug.java index 4be138f0c..53ffd77b3 100644 --- a/src/test/java/org/owasp/esapi/reference/TestDebug.java +++ b/src/test/java/org/owasp/esapi/reference/TestDebug.java @@ -8,7 +8,7 @@ * @author August Detlefsen (augustd at codemagi dot com) * CodeMagi, Inc. * @since October 15, 2010 - * @see org.owasp.esapi.logging.log4j.Log4JLoggerTest + * @see org.owasp.esapi.logging.java.JavaLoggerTest */ public class TestDebug extends TestCase { diff --git a/src/test/java/org/owasp/esapi/reference/TestError.java b/src/test/java/org/owasp/esapi/reference/TestError.java index 323cbe11a..17e889fd7 100644 --- a/src/test/java/org/owasp/esapi/reference/TestError.java +++ b/src/test/java/org/owasp/esapi/reference/TestError.java @@ -8,7 +8,7 @@ * @author August Detlefsen (augustd at codemagi dot com) * CodeMagi, Inc. * @since October 15, 2010 - * @see org.owasp.esapi.logging.log4j.Log4JLoggerTest + * @see org.owasp.esapi.logging.java.JavaLoggerTest */ public class TestError extends TestCase { diff --git a/src/test/java/org/owasp/esapi/reference/TestFatal.java b/src/test/java/org/owasp/esapi/reference/TestFatal.java index 9d7615048..a8176a2c1 100644 --- a/src/test/java/org/owasp/esapi/reference/TestFatal.java +++ b/src/test/java/org/owasp/esapi/reference/TestFatal.java @@ -8,7 +8,7 @@ * @author August Detlefsen (augustd at codemagi dot com) * CodeMagi, Inc. * @since October 15, 2010 - * @see org.owasp.esapi.logging.log4j.Log4JLoggerTest + * @see org.owasp.esapi.logging.java.JavaLoggerTest */ public class TestFatal extends TestCase { diff --git a/src/test/java/org/owasp/esapi/reference/TestInfo.java b/src/test/java/org/owasp/esapi/reference/TestInfo.java index e4cb72599..f404ecbbb 100644 --- a/src/test/java/org/owasp/esapi/reference/TestInfo.java +++ b/src/test/java/org/owasp/esapi/reference/TestInfo.java @@ -8,7 +8,7 @@ * @author August Detlefsen (augustd at codemagi dot com) * CodeMagi, Inc. * @since October 15, 2010 - * @see org.owasp.esapi.logging.log4j.Log4JLoggerTest + * @see org.owasp.esapi.logging.java.JavaLoggerTest */ public class TestInfo extends TestCase { diff --git a/src/test/java/org/owasp/esapi/reference/TestTrace.java b/src/test/java/org/owasp/esapi/reference/TestTrace.java index d6516fbeb..3e7b841ea 100644 --- a/src/test/java/org/owasp/esapi/reference/TestTrace.java +++ b/src/test/java/org/owasp/esapi/reference/TestTrace.java @@ -8,7 +8,7 @@ * @author August Detlefsen (augustd at codemagi dot com) * CodeMagi, Inc. * @since October 15, 2010 - * @see org.owasp.esapi.logging.log4j.Log4JLoggerTest + * @see org.owasp.esapi.logging.java.JavaLoggerTest */ public class TestTrace extends TestCase { diff --git a/src/test/java/org/owasp/esapi/reference/TestUnspecified.java b/src/test/java/org/owasp/esapi/reference/TestUnspecified.java index d8138d550..c8c9c2651 100644 --- a/src/test/java/org/owasp/esapi/reference/TestUnspecified.java +++ b/src/test/java/org/owasp/esapi/reference/TestUnspecified.java @@ -8,7 +8,7 @@ * @author August Detlefsen (augustd at codemagi dot com) * CodeMagi, Inc. * @since October 15, 2010 - * @see org.owasp.esapi.logging.log4j.Log4JLoggerTest + * @see org.owasp.esapi.logging.java.JavaLoggerTest */ public class TestUnspecified extends TestCase { diff --git a/src/test/java/org/owasp/esapi/reference/TestWarning.java b/src/test/java/org/owasp/esapi/reference/TestWarning.java index eb28c9ad4..0d80c1c7e 100644 --- a/src/test/java/org/owasp/esapi/reference/TestWarning.java +++ b/src/test/java/org/owasp/esapi/reference/TestWarning.java @@ -8,7 +8,7 @@ * @author August Detlefsen (augustd at codemagi dot com) * CodeMagi, Inc. * @since October 15, 2010 - * @see org.owasp.esapi.logging.log4j.Log4JLoggerTest + * @see org.owasp.esapi.logging.java.JavaLoggerTest */ public class TestWarning extends TestCase { From 84ab63c78b2a419a12c94e03f68822a271deac04 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sun, 10 Jul 2022 00:21:51 -0400 Subject: [PATCH 018/197] Remove reference to log4j.jar since we no longer need/use it. --- src/examples/java/DisplayEncryptedProperties.java | 2 +- src/examples/java/ESAPILogging.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/examples/java/DisplayEncryptedProperties.java b/src/examples/java/DisplayEncryptedProperties.java index d71ac7d83..ba0ce15ef 100644 --- a/src/examples/java/DisplayEncryptedProperties.java +++ b/src/examples/java/DisplayEncryptedProperties.java @@ -8,7 +8,7 @@ // that were encrypted using ESAPI's EncryptedProperties class. // // Usage: java -classpath DisplayEncryptedProperties encryptedPropFileName -// where is proper classpath, which minimally include esapi.jar & log4j.jar +// where is proper classpath, which minimally includes the esapi.jar. public class DisplayEncryptedProperties { public DisplayEncryptedProperties() { diff --git a/src/examples/java/ESAPILogging.java b/src/examples/java/ESAPILogging.java index 338e77e89..b085c66d2 100644 --- a/src/examples/java/ESAPILogging.java +++ b/src/examples/java/ESAPILogging.java @@ -4,7 +4,7 @@ // Purpose: Short code snippet to show how ESAPI logging works. // // Usage: java -classpath ESAPILogging -// where is proper classpath, which minimally include esapi.jar & log4j.jar +// where is proper classpath, which minimally includes the esapi.jar. public class ESAPILogging { public static void main(String[] args) { From 040dfbb55afabd05e9b8962c2e6de697019535c7 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sun, 10 Jul 2022 00:25:54 -0400 Subject: [PATCH 019/197] Delete obsolete reference to log4j. --- documentation/LoggerDesignAndTesting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/LoggerDesignAndTesting.md b/documentation/LoggerDesignAndTesting.md index 259488a65..d3542a48a 100644 --- a/documentation/LoggerDesignAndTesting.md +++ b/documentation/LoggerDesignAndTesting.md @@ -22,6 +22,6 @@ The general workflow is: Logger.info/warn/etc(message) -> forwards to LogBridgelog(logger, esapiLevel, type, message) -> forwards to LogHandler.log(...) -> forwards to slf4j Logger implementation with appropriate level and composed message. -So each of the tests for each of the classes verifies data in -> data out based on the Logging API. The structure for JUL, Log4J, and SLF4J are almost identical. There are a few differences in the interaction with the underlying Logger interactions and expectations. As a result, the tests are also almost full duplications (again accounting for differences in the underlying logging API). +So each of the tests for each of the classes verifies data in -> data out based on the Logging API. The structure for JUL and SLF4J are almost identical. There are a few differences in the interaction with the underlying Logger interactions and expectations. As a result, the tests are also almost full duplications (again accounting for differences in the underlying logging API). -J From 40564a41c212198765557c5ca3f8f260dbb97c2c Mon Sep 17 00:00:00 2001 From: kwwall Date: Mon, 11 Jul 2022 00:11:33 -0400 Subject: [PATCH 020/197] Remove log4j references and update dependencies where needed. --- src/examples/scripts/encryptProperties.sh | 6 ++---- src/examples/scripts/persistEncryptedData.sh | 7 +++---- src/examples/scripts/runClass.sh | 4 +--- src/examples/scripts/setMasterKey.sh | 3 +-- src/examples/scripts/setenv-svn.sh | 22 +++++--------------- src/examples/scripts/setenv-zip.sh | 12 ++--------- 6 files changed, 14 insertions(+), 40 deletions(-) diff --git a/src/examples/scripts/encryptProperties.sh b/src/examples/scripts/encryptProperties.sh index bc606830b..4ee001d59 100755 --- a/src/examples/scripts/encryptProperties.sh +++ b/src/examples/scripts/encryptProperties.sh @@ -49,8 +49,7 @@ cd ../java if [[ "$action" == "-display" ]] then set -x - java -Dlog4j.configuration="file:$log4j_properties" \ - -Dorg.owasp.esapi.resources="$esapi_resources_test" \ + java -Dorg.owasp.esapi.resources="$esapi_resources_test" \ -classpath "$esapi_classpath" \ DisplayEncryptedProperties "$filename" else @@ -65,8 +64,7 @@ else echo echo "Hit to continue..."; read GO set -x - java -Dlog4j.configuration="file:$log4j_properties" \ - -Dorg.owasp.esapi.resources="$esapi_resources_test" \ + java -Dorg.owasp.esapi.resources="$esapi_resources_test" \ -classpath "$esapi_classpath" \ org.owasp.esapi.reference.crypto.DefaultEncryptedProperties "$filename" && echo "Output of encrypted properties in file: $filename" diff --git a/src/examples/scripts/persistEncryptedData.sh b/src/examples/scripts/persistEncryptedData.sh index e7dbbe42b..fc4a5ed46 100755 --- a/src/examples/scripts/persistEncryptedData.sh +++ b/src/examples/scripts/persistEncryptedData.sh @@ -23,7 +23,6 @@ set -x # Since this is just an illustration, we will use the test ESAPI.properties in # $esapi_resources_test. That way, it won't matter if the user has neglected # to run the 'setMasterKey.sh' example before running this one. -java -Dlog4j.configuration="file:$log4j_properties" \ - -Dorg.owasp.esapi.resources="$esapi_resources_test" \ - -ea -classpath "$esapi_classpath" \ - PersistedEncryptedData "$@" +java -Dorg.owasp.esapi.resources="$esapi_resources_test" \ + -ea -classpath "$esapi_classpath" \ + PersistedEncryptedData "$@" diff --git a/src/examples/scripts/runClass.sh b/src/examples/scripts/runClass.sh index 1c79082c9..2b28a4a4c 100755 --- a/src/examples/scripts/runClass.sh +++ b/src/examples/scripts/runClass.sh @@ -19,10 +19,8 @@ then echo >2&1 "Can't find class file: ${className}.class" exit 1 fi echo "Your ESAPI.properties file: ${esapi_resources_test:?}/ESAPI.properties" -echo "Your log4j properties file: ${log4j_properties:?}" echo set -x -java -Dlog4j.configuration="file:$log4j_properties" \ - -Dorg.owasp.esapi.resources="$esapi_resources_test" \ +java -Dorg.owasp.esapi.resources="$esapi_resources_test" \ -classpath "$esapi_classpath" \ ${className} "$@" diff --git a/src/examples/scripts/setMasterKey.sh b/src/examples/scripts/setMasterKey.sh index 7075532bc..ecd0937f7 100755 --- a/src/examples/scripts/setMasterKey.sh +++ b/src/examples/scripts/setMasterKey.sh @@ -16,7 +16,6 @@ echo # set -x # This should use the real ESAPI.properties in $esapi_resources that does # not yet have Encryptor.MasterKey and Encryptor.MasterSalt yet set. -java -Dlog4j.configuration="file:$log4j_properties" \ - -Dorg.owasp.esapi.resources="$esapi_resources" \ +java -Dorg.owasp.esapi.resources="$esapi_resources" \ -classpath "$esapi_classpath" \ org.owasp.esapi.reference.crypto.JavaEncryptor "$@" diff --git a/src/examples/scripts/setenv-svn.sh b/src/examples/scripts/setenv-svn.sh index db4846e7c..d8ab6d727 100755 --- a/src/examples/scripts/setenv-svn.sh +++ b/src/examples/scripts/setenv-svn.sh @@ -9,23 +9,17 @@ # where '$' represents the shell command line prompt. ########################################################################### -# IMPORTANT NOTE: Since you may have multiple (say) log4j jars under -# your Maven2 repository under $HOME/.m2/respository, we -# look for the specific versions that ESAPI was using as of -# ESAPI 2.0_RC10 release on 2010/10/18. If these versions -# changed, they will have to be reflected here. -# +# IMPORTANT NOTE: These dependency versions may need updated. Should match +# what is in ESAPI's pom.xml. esapi_classpath=".:\ ../../../target/classes:\ $(ls ../../../target/esapi-*.jar 2>&- || echo .):\ -$(./findjar.sh log4j-1.2.17.jar):\ -$(./findjar.sh commons-fileupload-1.3.1.jar):\ -$(./findjar.sh servlet-api-2.5.jar)" +$(./findjar.sh commons-fileupload-1.4.jar):\ +$(./findjar.sh servlet-api-3.1.0.jar)" esapi_resources="$(\cd ../../../configuration/esapi >&- 2>&- && pwd)" esapi_resources_test="$(\cd ../../../src/test/resources/esapi >&- 2>&- && pwd)" -log4j_properties="../../../src/test/resources/log4j.xml" if [[ ! -r "$esapi_resources"/ESAPI.properties ]] then echo 2>&1 "setenv-svn.sh: Can't read ESAPI.properties in $esapi_resources" @@ -37,16 +31,10 @@ then echo 2>&1 "setenv-svn.sh: Can't read ESAPI.properties in $esapi_resources_t return 1 # Don't use 'exit' here or it will kill their current shell. fi -if [[ ! -r "$log4j_properties" ]] -then echo 2>&1 "setenv-svn.sh: Can't read log4j.xml: $log4j_properties" - return 1 # Don't use 'exit' here or it will kill their current shell. -fi - echo ############################################################ echo "esapi_resources=$esapi_resources" echo "esapi_resources_test=$esapi_resources_test" -echo "log4j_properties=$log4j_properties" echo "esapi_classpath=$esapi_classpath" echo ############################################################ -export esapi_classpath esapi_resources esapi_resources_test log4j_properties +export esapi_classpath esapi_resources esapi_resources_test diff --git a/src/examples/scripts/setenv-zip.sh b/src/examples/scripts/setenv-zip.sh index 310864ac0..199d9c055 100755 --- a/src/examples/scripts/setenv-zip.sh +++ b/src/examples/scripts/setenv-zip.sh @@ -12,18 +12,15 @@ # Here we don't look for the specific versions of the dependent libraries # since the specific version of the library is delivered as part of the # ESAPI zip file. In this manner, we do not have to update this if these -# versions change. For the record, at the time of this writing, these were -# log4j-1.2.17.jar, commons-fileupload-1.3.1.jar, and servlet-api-2.5.jar. +# versions change. esapi_classpath=".:\ $(ls ../../../esapi*.jar):\ -$(./findjar.sh -start ../../../libs log4j-*.jar):\ $(./findjar.sh -start ../../../libs commons-fileupload-*.jar):\ $(./findjar.sh -start ../../../libs servlet-api-*.jar)" esapi_resources="$(\cd ../../../configuration/esapi >&- 2>&- && pwd)" esapi_resources_test="$(\cd ../../../src/test/resources/esapi >&- 2>&- && pwd)" -log4j_properties="../../../src/test/resources/log4j.xml" if [[ ! -r "$esapi_resources"/ESAPI.properties ]] then echo 2>&1 "setenv-svn.sh: Can't read ESAPI.properties in $esapi_resources" @@ -35,16 +32,11 @@ then echo 2>&1 "setenv-svn.sh: Can't read ESAPI.properties in $esapi_resources_t return 1 # Don't use 'exit' here or it will kill their current shell. fi -if [[ ! -r "$log4j_properties" ]] -then echo 2>&1 "setenv-svn.sh: Can't read log4j.xml: $log4j_properties" - return 1 # Don't use 'exit' here or it will kill their current shell. -fi echo ############################################################ echo "esapi_resources=$esapi_resources" echo "esapi_resources_test=$esapi_resources_test" -echo "log4j_properties=$log4j_properties" echo "esapi_classpath=$esapi_classpath" echo ############################################################ -export esapi_classpath esapi_resources esapi_resources_test log4j_properties +export esapi_classpath esapi_resources esapi_resources_test From 6630df5f51d2cbf054dfa0327501c876d003bbcb Mon Sep 17 00:00:00 2001 From: kwwall Date: Mon, 11 Jul 2022 00:34:47 -0400 Subject: [PATCH 021/197] Add warning if log_settings init parameter is specified as it is now ignored. --- .../esapi/waf/ESAPIWebApplicationFirewallFilter.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java b/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java index 0879ac516..7f47ae43e 100644 --- a/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java +++ b/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java @@ -139,8 +139,18 @@ public void init(FilterConfig fc) throws ServletException { logger.debug(Logger.EVENT_SUCCESS, ">> Initializing WAF"); /* - * Pull logging file. + * Pull logging file. -- We now ignore this arg, but will log something + * letting users know we are ignoring it, because many of them never + * seem to read the release notes. And this is probably better than + * throwing an exception. */ + String logSettingsFilename = fc.getInitParameter(LOGGING_FILE_PARAM); + if ( logSettingsFilename != null ) { + logger.warning(Logger.EVENT_FAILURE, ">> Since ESAPI 2.5.0.0, ESAPI WAF ignoring parameter '" + + LOGGING_FILE_PARAM + "; for further details, see " + + "https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.5.0.0-release-notes.txt"); + + } /* * Pull main configuration file. From 51c5a3a25d4667e9e6d704dfeff3a3d06797d23e Mon Sep 17 00:00:00 2001 From: kwwall Date: Mon, 11 Jul 2022 00:36:16 -0400 Subject: [PATCH 022/197] Change log4j.xml to prop value that's obviously ignored. Also added explanatory comment. --- .../java/org/owasp/esapi/waf/WAFTestUtility.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/owasp/esapi/waf/WAFTestUtility.java b/src/test/java/org/owasp/esapi/waf/WAFTestUtility.java index 284efb9c0..ca1d524cd 100644 --- a/src/test/java/org/owasp/esapi/waf/WAFTestUtility.java +++ b/src/test/java/org/owasp/esapi/waf/WAFTestUtility.java @@ -39,7 +39,19 @@ public class WAFTestUtility { public static void setWAFPolicy( ESAPIWebApplicationFirewallFilter waf, String policyFile ) throws Exception { Map map = new HashMap(); map.put( "configuration", policyFile ); - map.put( "log_settings", "../log4j.xml"); + + // As of ESAPI 2.5.0.0 (when Log4J 1 dependency was removed), thsi + // init parameter is not ignored. However, it will produce a warning + // log message that looks something like this: + // + // [2022-07-11 00:25:45] [org.owasp.esapi.waf.ESAPIWebApplicationFirewallFilter] [EVENT FAILURE Anonymous:90471@unknown -> 10.1.43.6:80/ExampleApplication/org.owasp.esapi.waf.ESAPIWebApplicationFirewallFilter] >> Since ESAPI 2.5.0.0, ESAPI WAF ignoring parameter 'log_settings; for further details, see https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.5.0.0-release-notes.txt + // + // Without getting really fancy and making this test way more + // complicated than I want though, I am not sure how to test for + // some specicif log output. It's been manually verified (once). + // Hopefully, that is good enough. -kwwall + // + map.put( "log_settings", "parameter-now-ignored!!!"); FilterConfig mfc = new MockWafFilterConfig( map ); waf.init( mfc ); } From 92239e8f87db96155e9aadec9217fa4e17f428a5 Mon Sep 17 00:00:00 2001 From: kwwall Date: Mon, 11 Jul 2022 21:35:43 -0400 Subject: [PATCH 023/197] Update Maven plugins and dependencies. Still waiting for AntiSamy 1.7.0 to become official. --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 317d5c189..e8743c1a1 100644 --- a/pom.xml +++ b/pom.xml @@ -140,7 +140,7 @@ 2.0.9 4.7.1 1.12.0 - 4.7.0.0 + 4.7.1.0 3.0.0-M7 1.8 @@ -406,7 +406,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.4.0 + 3.4.1 org.apache.maven.plugins @@ -538,7 +538,7 @@ org.codehaus.mojo extra-enforcer-rules - 1.5.1 + 1.6.0 org.codehaus.mojo From d6251b5e5ade0bfe312efbb1d798af266ec70e0d Mon Sep 17 00:00:00 2001 From: "Kevin W. Wall" Date: Sun, 17 Jul 2022 14:35:52 -0400 Subject: [PATCH 024/197] Changes to prepare for 2.5.0.0 release. (#719) * Changes to prepare for 2.5.0.0 release. * More 2.5.0.0 release preparation: * Fix typos in 2.5.0.0 release notes. * Emblesh section in release notes about AntiSamy as well as 'Know Issues / Problems' section. * Fix pom.xml to address dependency convergence issue caused by AntiSamy 1.7.0 and drop '-SNAPSHOT' on ESAPI version. * Address previously deprecated and not deleted AntiSamy Policy method in HTMLValidationRuleAntisamyPropertyTest.java JUnit test. --- README.md | 17 +- .../esapi4java-core-2.5.0.0-release-notes.txt | 243 ++++++++++++++++++ pom.xml | 15 +- scripts/README.txt | 1 + ...esapi4java-core-TEMPLATE-release-notes.txt | 103 +++----- scripts/vars.2.4.0.0 | 14 + scripts/vars.2.5.0.0 | 14 + ...TMLValidationRuleAntisamyPropertyTest.java | 22 +- 8 files changed, 332 insertions(+), 97 deletions(-) create mode 100644 documentation/esapi4java-core-2.5.0.0-release-notes.txt create mode 100644 scripts/vars.2.4.0.0 create mode 100644 scripts/vars.2.5.0.0 diff --git a/README.md b/README.md index 43bb29711..8e4933f1e 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,11 @@ Development for the "next generation" of ESAPI (starting with ESAPI 3.0), will b GitHub repository at [https://github.com/ESAPI/esapi-java](https://github.com/ESAPI/esapi-java). **IMPORTANT NOTES:** -* The default branch for ESAPI legacy is the 'develop' branch (rather than the 'main' (formerly 'master') branch), where future development, bug fixes, etc. are now being done. The 'main' branch is now marked as "protected"; it reflects the latest stable ESAPI release (2.4.0.0 as of this date). Note that this change of making the 'develop' branch the default may affect any pull requests that you were intending to make. +* The default branch for ESAPI legacy is the 'develop' branch (rather than the 'main' (formerly 'master') branch), where future development, bug fixes, etc. are now being done. The 'main' branch is now marked as "protected"; it reflects the latest stable ESAPI release (2.5.0.0 as of this date). Note that this change of making the 'develop' branch the default may affect any pull requests that you were intending to make. * Also, the *minimal* baseline Java version to use ESAPI is now Java 8. (This was changed from Java 7 during the 2.4.0.0 release.) +* Support was dropped for Log4J 1 during ESAPI 2.5.0.0 release. If you need it, configure it via SLF4J. See the + [2.5.0.0 release notes](https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.5.0.0-release-notes.txt) +for details. # Where can I find ESAPI 3.x? As mentioned above, you can find it at [https://github.com/ESAPI/esapi-java](https://github.com/ESAPI/esapi-java). @@ -63,7 +66,7 @@ link to the specific release notes. Starting with release 2.4.0.0, Java 8 or later is required. # Locating ESAPI Jar files -The [latest ESAPI release](https://github.com/ESAPI/esapi-java-legacy/releases/latest) is 2.4.0.0. +The [latest ESAPI release](https://github.com/ESAPI/esapi-java-legacy/releases/latest) is 2.5.0.0. All the *regular* ESAPI jars, with the exception of the ESAPI configuration jar (i.e., esapi-2.#.#.#-configuration.jar) and its associated detached GPG signature, are available from Maven Central. The ESAPI configuration @@ -85,11 +88,11 @@ to be using such classes directly in your code. At the ESAPI team's discretion, it will also not apply for any known exploitable vulnerabilities for which no available workaround exists. -**IMPORTANT NOTES:** The next planned removal of deprecated code is for us to -remove all the Log4J 1.x related ESAPI Logger code. The Log4J 1 ESAPI Logger -was first marked deprecated in ESAPI 2.2.1.0, which was released July 13, 2022. -This means that on or shortly after, you can expect a new ESAPI release that -will no longer have a dependency on Log4J 1. **YOU HAVE BEEN WARNED!!!** +**IMPORTANT NOTES:** As of ESAPI 2.5.0.0, all the Log4J 1.x related code +has been removed from the ESAPI code base (with the exception of some +references in documentation). If you must, you still should be able to +use Log4J 1.x logging via ESAPI SLF4J support. See the ESAPI 2.5.0.0 release +notes for further details. # Contributing to ESAPI legacy ### How can I contribute or help with fix bugs? diff --git a/documentation/esapi4java-core-2.5.0.0-release-notes.txt b/documentation/esapi4java-core-2.5.0.0-release-notes.txt new file mode 100644 index 000000000..67186f17f --- /dev/null +++ b/documentation/esapi4java-core-2.5.0.0-release-notes.txt @@ -0,0 +1,243 @@ +Release notes for ESAPI 2.5.0.0 + Release date: 2022-07-17 + Project leaders: + -Kevin W. Wall + -Matt Seil + +Previous release: ESAPI 2.4.0.0, 2022-04-24 + + +Executive Summary: Important Things to Note for this Release +------------------------------------------------------------ + +In addition to this summary, please also be sure to thoroughly read the section "Changes Requiring Special Attention", below. + +Major changes: + Logging: + The major change in ESAPI 2.5.0.0 is the removal of the Log4J 1 dependency (specifically, log4j-1.2.17). It has been removed because in accordance with the ESAPI deprecation policy (see the README.md file), the Log4J supported logger has been deprecated for 2 years. + + For those of you using a Software Configuration Analysis (SCA) services such as Snyk, BlackDuck, Veracode SourceClear, OWASP Dependency Check, etc., you will notice that the 4 Log4J 1.x related CVEs are no longer flagged. This is because of removal of the Log4J 1.2.17 dependency. + + Any remaining flagged vulnerabilities (e.g., CVE-2020-7791 for transitive dependency batik-i18n-1.14) are believed to be false positives. + + You are encouraged to review the vulnerability analysis written up in https://github.com/ESAPI/esapi-java-legacy/blob/develop/Vulnerability-Summary.md and email us or contact us in our GitHub Discussions page if you have questions. + + AntiSamy 1.7.0 and potentially breaking changes + We have updated to AntiSamy 1.7.0. If you have a custom version of antisamy-esapi.xml,then be sure to read the section "Changes Requiring Special Attention", below. + +Minor changes: + Miscellaneous bug fixes, Javadoc enhancements, and minor dependency updates. + +================================================================================================================= + +Basic ESAPI facts +----------------- + +ESAPI 2.4.0.0 release: + 212 Java source files + 4325 JUnit tests in 136 Java source files (1 test skipped) + +ESAPI 2.5.0.0 release: + 206 Java source files + 4274 JUnit tests in 131 Java source files (0 tests skipped) + +18 GitHub Issues closed in this release, including those we've decided not to fix (marked 'wontfix' and 'falsepositive'). +(Reference: https://github.com/ESAPI/esapi-java-legacy/issues?q=is%3Aissue+state%3Aclosed+updated%3A%3E%3D2022-04-24) + +Issue # GitHub Issue Title +---------------------------------------------------------------------------------------------- +717 Update to AntiSamy 1.7.0 once it is officially released +715 ESAPI - Not working with Eclipse bug +713 Should '/' be encoded for LDAP searches? bug +705 Add more details to DefaultValidator class-level javadoc on ESAPI canonicalization properties Component-Docs Component-Validator javadoc +702 ValidatorTest#testIsValidDirectoryPathGHSL_POC fails on Mac +695 Esapi 2.3.0.0 does not supported in opensaml 2.6.6 bug +692 Multiple (2x) encoding detected in from PercentCodec question +690 Plugin/Dependency Version Updates +689 Clean-up ESAPI Javadoc Component-Docs javadoc +686 ESAPI canonicalization in DefaultEncoder ignoring Encoder.DefaultCodecList property bug Component-Encoder +684 Hello world +682 Update baseline to java 1.8 +674 Add the missing Javadoc for the Validator interface Component-Docs Component-Validator good first issue +656 DefaultHTTPUtility uses hard coded Header name/value lengths (Note: Actually fixed in ESAPI 2.3.0.0, but just closed this release. - kww) +644 Do not include a logging implementation as a dependency slf4j-simple +620 Move the default property names and values out of a reference implementation class Component-SecurityConfiguration +587 Drop Xerces dependency from pom.xml Build-Maven Vulnerable Dependencies +534 Delete Deprecated Log4J implementation and Dependencies wait4future + +----------------------------------------------------------------------------- + + Changes Requiring Special Attention + +----------------------------------------------------------------------------- + +Important ESAPI Logging Changes + +* Since ESAPI 2.5.0.0, support for logging directly via Log4J 1 has been removed. (This was two years after it having first been deprecated.) Thus, your only choice for ESAPI logging are: + - java.util.logging (JUL), which as been the default since ESAPI 2.2.1.0. + * Set ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory in your ESAPI.properties file. + - SLF4J (which your choice of supported SLF4J logging implementation) + * Set ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory in your ESAPI.properties file. + * Create your own custom logger. +* Logger configuration notes - If you are migrating from prior to ESAPI 2.2.1.1, you will need to update your ESAPI.properties file as logging-related configuration as per the ESAPI 2.2.1.1 release notes, which may be found at: + https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.2.1.1-release-notes.txt#L39-L78 + +If you use ESAPI 2.5.0.0 or later, you will get an ClassNotFoundException as the root cause if you still have your ESAPI.Logger property set to use Log4J because the org.owasp.esapi.logger.log4j.Log4JFactory class has been completely removed from the ESAPI jar. If you are dead set on continuing to use Log4J 1, you ought to be able to do so via SLF4J. The set up for Log4J 1 (which has not be tested), should be similar to configure ESAPI to use SLF4J with Log4J 2 as described here: + https://github.com/ESAPI/esapi-java-legacy/wiki/Using-ESAPI-with-SLF4J#slf4j-using-log4j-2x + +Potentially Breaking Changes in AntiSamy 1.7.0 + +* This version of ESAPI has upgraded to the latest version of AntiSamy (1.7.0 at the time of our release). AntiSamy 1.7.0 has some breaking changes to its SDK and the way that it processes AntiSamy policy files, of which the antisamy-esapi.xml file, included in our esapi-2.5.0.0-configuration.jar found at https://github.com/ESAPI/esapi-java-legacy/releases/download/esapi-2.5.0.0/esapi-2.4.0.0-configuration.jar, is the one we include. + +* None of the AntiSamy SDK changes affected how ESAPI, in its default configuration, uses it, but you may be affected if you have customized your AntiSamy policy file. If your regression tests fail when you upgrade to ESAPI 2.5.0.0 sand they seem to be related to AntiSamy, then please review https://github.com/nahsra/antisamy/blob/main/README.md#important---api-breaking-changes-in-170. Also, as a temporary workaround, you could do something like this (in Maven, but similar exclusion can be done with Gradle) to allow you time to correct your customized AntiSamy policy file: + + + org.owasp.esapi + esapi + 2.5.0.0 + + + + org.owasp.antisamy + antisamy + + + + + org.owasp.antisamy + antisamy + 1.6.8 + + +Indeed the only change that we had to make is to alter a JUnit test that was intended to ensure that invalid AntiSamy policy files could be disabled by setting + Policy.setSchemaValidation(false); +before processing any AntiSamy policy file not conforming to its schema. This specific (previously deprecated) method was removed in AntiSamy 1.7.0 so the schema validation checks can no longer be ignored. (And hence the reason for the workaround noted above.) + +Instead, we simply changed the JUnit test to check that the expected AntiSamy org.owasp.validator.html.PolicyException class is thrown when the invalid policy file is loaded. + +----------------------------------------------------------------------------- + + Remaining Known Issues / Problems + +----------------------------------------------------------------------------- +'mvn site' fails to build these two reports: + "Tag reference" report --- maven-taglib-plugin:2.4:tagreference + "Taglibdoc documentation" report --- maven-taglib-plugin:2.4:taglibdoc + +Thus no tag library documentation will be generated. :-( + +We are attempting to find a solution, but on the surface, it seems like the maven-taglib-plugin does not play nicely with versions of Java after Java 6. (So, this probably has been happening for a while and we just noticed it.) + +No others problems are known, other than the remaining open issues on GitHub. + +----------------------------------------------------------------------------- + + Other changes in this release, some of which not tracked via GitHub issues + +----------------------------------------------------------------------------- + +* Minor updates to README.md file with respect to version information. + +----------------------------------------------------------------------------- + +Developer Activity Report (Changes between release 2.4.0.0 and 2.5.0.0, i.e., between 2022-04-24 and 2022-07-17) +Generated manually (this time) -- all errors are the fault of kwwall and his inability to do simple arithmetic. + +# +# 34 PRs merged since ESAPI 2.4.0.0 release +# +Developer Total Total Number # Merged +(GitHub ID) commits of Files Changed PRs +======================================================== +jeremiahjstacey 265 180 24 +kwwall 35 64 5 +xeno6696 1 267 1 +noloader 5 2 1 +stevebosman-oc 4 3 2 +VinodAnandan 1 1 1 +======================================================== + Total PRs: 34 + +----------------------------------------------------------------------------- + +CHANGELOG: Create your own. May I suggest: + + git log --stat --since=2022-04-24 --reverse --pretty=medium + + which will show all the commits since just after the previous (2.4.0.0) release. + + Alternately, you can download the most recent ESAPI source and run + + mvn site + + which will create a CHANGELOG file named 'target/site/changelog.html' + + +----------------------------------------------------------------------------- + +Direct and Transitive Runtime and Test Dependencies: + + $ mvn -B dependency:tree + ... + [INFO] --- maven-dependency-plugin:3.3.0:tree (default-cli) @ esapi --- + [INFO] org.owasp.esapi:esapi:jar:2.5.0.0 + [INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided + [INFO] +- javax.servlet.jsp:javax.servlet.jsp-api:jar:2.3.3:provided + [INFO] +- xom:xom:jar:1.3.7:compile + [INFO] +- commons-beanutils:commons-beanutils:jar:1.9.4:compile + [INFO] | +- commons-logging:commons-logging:jar:1.2:compile + [INFO] | \- commons-collections:commons-collections:jar:3.2.2:compile + [INFO] +- commons-configuration:commons-configuration:jar:1.10:compile + [INFO] +- commons-lang:commons-lang:jar:2.6:compile + [INFO] +- commons-fileupload:commons-fileupload:jar:1.4:compile + [INFO] +- org.apache.commons:commons-collections4:jar:4.4:compile + [INFO] +- org.apache-extras.beanshell:bsh:jar:2.0b6:compile + [INFO] +- org.owasp.antisamy:antisamy:jar:1.7.0:compile + [INFO] | +- net.sourceforge.htmlunit:neko-htmlunit:jar:2.63.0:compile + [INFO] | +- org.apache.httpcomponents.client5:httpclient5:jar:5.1.3:compile + [INFO] | | \- org.apache.httpcomponents.core5:httpcore5-h2:jar:5.1.3:compile + [INFO] | +- org.apache.httpcomponents.core5:httpcore5:jar:5.1.4:compile + [INFO] | +- org.apache.xmlgraphics:batik-css:jar:1.14:compile + [INFO] | | +- org.apache.xmlgraphics:batik-shared-resources:jar:1.14:compile + [INFO] | | +- org.apache.xmlgraphics:batik-util:jar:1.14:compile + [INFO] | | | +- org.apache.xmlgraphics:batik-constants:jar:1.14:compile + [INFO] | | | \- org.apache.xmlgraphics:batik-i18n:jar:1.14:compile + [INFO] | | \- org.apache.xmlgraphics:xmlgraphics-commons:jar:2.6:compile + [INFO] | +- xerces:xercesImpl:jar:2.12.2:compile + [INFO] | \- xml-apis:xml-apis-ext:jar:1.3.04:compile + [INFO] +- org.slf4j:slf4j-api:jar:1.7.36:compile + [INFO] +- xml-apis:xml-apis:jar:1.4.01:compile + [INFO] +- commons-io:commons-io:jar:2.11.0:compile + [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.7.1:compile + [INFO] | \- com.google.code.findbugs:jsr305:jar:3.0.2:compile + [INFO] +- commons-codec:commons-codec:jar:1.15:test + [INFO] +- junit:junit:jar:4.13.2:test + [INFO] +- org.bouncycastle:bcprov-jdk15on:jar:1.70:test + [INFO] +- org.hamcrest:hamcrest-core:jar:2.2:test + [INFO] | \- org.hamcrest:hamcrest:jar:2.2:test + [INFO] +- org.powermock:powermock-api-mockito2:jar:2.0.9:test + [INFO] | \- org.powermock:powermock-api-support:jar:2.0.9:test + [INFO] +- org.mockito:mockito-core:jar:3.12.4:test + [INFO] | +- net.bytebuddy:byte-buddy:jar:1.11.13:test + [INFO] | +- net.bytebuddy:byte-buddy-agent:jar:1.11.13:test + [INFO] | \- org.objenesis:objenesis:jar:3.2:test + [INFO] +- org.powermock:powermock-core:jar:2.0.9:test + [INFO] | \- org.javassist:javassist:jar:3.27.0-GA:test + [INFO] +- org.powermock:powermock-module-junit4:jar:2.0.9:test + [INFO] | \- org.powermock:powermock-module-junit4-common:jar:2.0.9:test + [INFO] +- org.powermock:powermock-reflect:jar:2.0.9:test + [INFO] \- org.openjdk.jmh:jmh-core:jar:1.35:test + [INFO] +- net.sf.jopt-simple:jopt-simple:jar:5.0.4:test + [INFO] \- org.apache.commons:commons-math3:jar:3.2:test + ... + + +----------------------------------------------------------------------------- + +Acknowledgments: + A special shout-out our new contributors noloader, stevebosman-oc, and VinodAnandan. + Another hat tip to Dave Wichers, Sebastián Passaro, and the rest of the AntiSamy crew for promptly releasing AntiSamy 1.7.0. And thanks to Matt Seil, Jeremiah Stacey, and all the ESAPI users who make this worthwhile. This is for you. + +A special thanks to the ESAPI community from the ESAPI project co-leaders: + Kevin W. Wall (kwwall) <== The irresponsible party for these release notes! + Matt Seil (xeno6696) diff --git a/pom.xml b/pom.xml index e8743c1a1..05bb55181 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.owasp.esapi esapi - 2.4.1.0-SNAPSHOT + 2.5.0.0 jar @@ -149,6 +149,17 @@ 2021-05-07 00:00:00 + + + + + org.apache.httpcomponents.core5 + httpcore5 + 5.1.4 + + + + javax.servlet @@ -248,7 +259,7 @@ org.owasp.antisamy antisamy - 1.6.8 + 1.7.0 org.slf4j diff --git a/scripts/README.txt b/scripts/README.txt index 61df78f20..b61b287da 100644 --- a/scripts/README.txt +++ b/scripts/README.txt @@ -12,4 +12,5 @@ newReleaseNotes.sh -- Bash script to create the release notes boillerplate from vars.2.2.3.0 -- File that is 'sourced' (as in "source ./filename") and used with newReleaseNotes.sh vars.2.2.3.1 -- File that is 'sourced' (as in "source ./filename") and used with newReleaseNotes.sh vars.2.3.0.0 -- File that is 'sourced' (as in "source ./filename") and used with newReleaseNotes.sh +vars.2.4.0.0 -- File that is 'sourced' (as in "source ./filename") and used with newReleaseNotes.sh vars.template -- Template to construct the release specific vars files diff --git a/scripts/esapi4java-core-TEMPLATE-release-notes.txt b/scripts/esapi4java-core-TEMPLATE-release-notes.txt index b4a953bf9..1d7c8c460 100644 --- a/scripts/esapi4java-core-TEMPLATE-release-notes.txt +++ b/scripts/esapi4java-core-TEMPLATE-release-notes.txt @@ -1,6 +1,7 @@ @@@@ IMPORTANT: Be sure to 1) save in DOS text format, and 2) Delete this line and others starting with @@@@ @@@@ Edit this file in vim with :set tw=0 @@@@ Meant to be used with scripts/newReleaseNotes.sh and the 'vars.*' scripts there. +@@@@ There are specific references to ESAPI 2.5.0.0 and other old releases in this file. Do NOT change the version #s. They are there for a reason. Release notes for ESAPI ${VERSION} Release date: ${YYYY_MM_DD_RELEASE_DATE} Project leaders: @@ -13,11 +14,14 @@ Previous release: ESAPI ${PREV_VERSION}, ${PREV_RELEASE_DATE} Executive Summary: Important Things to Note for this Release ------------------------------------------------------------ @@@@ View previous release notes to see examples of what to put here. This is typical. YMMV. +@@@@ Obviously, you should summarize any major changes / new features here. This is a patch release with the primary intent of updating some dependencies, some with known vulnerabilities. Details follow. -For those of you using a Software Configuration Analysis (SCA) services such as Snyk, BlackDuck, Veracode SourceClear, OWASP Dependency Check, etc., you might notice that there is vulnerability in xerces:xercesImpl:2.12.0 that ESAPI uses (also a transitive dependency) that is similar to CVE-2020-14621. Unfortunately there is no official patch for this in the regular Maven Central repository. Further details are described in Security Bulletin #3, which is viewable here - https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin3.pdf -and associated with this release on GitHub. Manual workarounds possible. See the security bulletin for further details. +For those of you using a Software Configuration Analysis (SCA) services such as Snyk, BlackDuck, Veracode SourceClear, OWASP Dependency Check, etc., you will notice that the 4 Log4J 1.x related CVEs are no longer flagged. This is because we have finally removed the Log4J 1.2.17 dependency in ESAPI 2.5.0.0. + +Any remaining flagged vulnerabilities (e.g., CVE-2020-7791 for transitive dependency batik-i18n-1.14) are believed to be false postives. + +You are encouraged to review the vulnerability analysis written up in https://github.com/ESAPI/esapi-java-legacy/blob/develop/Vulnerability-Summary.md and email us or contact us in our GitHub Discussions page if you have questions. ================================================================================================================= @@ -49,78 +53,30 @@ Issue # GitHub Issue Title ----------------------------------------------------------------------------- @@@@ NOTE any special notes here. Probably leave this one, but I would suggest noting additions BEFORE this. -[If you have already successfully been using ESAPI 2.2.1.0 or later, you probably can skip this section.] - -Since ESAPI 2.2.1.0, the new default ESAPI logger is JUL (java.util.logging packages) and we had deprecated the use of Log4J 1.x because was way past its end-of-life. (Note: As of ESAPI 2.5.0.0, we have officially removed all Log4J 1 dependencies, after it had been deprecated for 2 years as per our deprecation policy.) We did not want to make SLF4J the default logger (at least not yet) as we did not want to have the default ESAPI use require additional dependencies. However, SLF4J is likely to be the future choice, at least once we start on ESAPI 3.0. A special shout-out to Jeremiah Stacey for making this possible by re-factoring much of the ESAPI logger code. Note, the straw that broke the proverbial camel's back was the announcement of CVE-2019-17571 (rated Critical), for which there is no fix available and likely will never be. - -However, if you try to juse the new ESAPI 2.2.1.0 or later logging you will notice that you need to change ESAPI.Logger and also possibly provide some other properties as well to get the logging behavior that you desire. - -To use ESAPI logging in ESAPI 2.2.1.0 (and later), you will need to set the ESAPI.Logger property to - org.owasp.esapi.logging.java.JavaLogFactory - To use the new default, java.util.logging (JUL) - org.owasp.esapi.logging.slf4j.Slf4JLogFactory - To use the new (to release 2.2.0.0) SLF4J logger +Important JDK Support Announcement +* ESAPI 2.3.0.0 was the last Java release to support Java 7. ESAPI 2.4.0 requires using Java 8 or later. See the ESAPI 2.4.0.0 release notes (https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.4.0.0-release-notes.txt) for details as to the reason. + - This means if your project requires Java 7, you must use ESAPI 2.3.0.0 or earlier. -In addition, if you wish to use JUL for logging, you *MUST* supply an "esapi-java-logging.properties" file in your classpath. This file is included in the 'esapi-2.2.2.0-configuration.jar' file provided under the 'Assets' section of the GitHub Release at - https://github.com/ESAPI/esapi-java-legacy/releases/esapi-2.2.2.0 +Important ESAPI Logging Changes -Unfortunately, there was a logic error in the static initializer of JavaLogFactory (now fixed in this release) that caused a NullPointerException to be thrown so that the message about the missing "esapi-java-logging.properties" file was never seen. +* Since ESAPI 2.5.0.0, support for logging directly via Log4J 1 has been removed. (This was two years after it haveing first been deprecated.) Thus, you only choice of ESAPI logging are + - java.util.logging (JUL), which as been the default since ESAPI 2.2.1.0. + * Set ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory in your ESAPI.properties file. + - SLF4J (which your choice of supported SLF4J logging implemmentation) + * Set ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory in your ESAPI.properties file. +* Logger configuration notes - If you are migrating from prior to ESAPI 2.2.1.1, you will need to update your ESAPI.properties file as logging-related configuration as per the ESAPI 2.2.1.1 release notes, which may be found at: + https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.2.1.1-release-notes.txt#L39-L78 -If you are using JavaLogFactory, you will also want to ensure that you have the following ESAPI logging properties set: - # Set the application name if these logs are combined with other applications - Logger.ApplicationName=ExampleApplication - # If you use an HTML log viewer that does not properly HTML escape log data, you can set LogEncodingRequired to true - Logger.LogEncodingRequired=false - # Determines whether ESAPI should log the application name. This might be clutter in some single-server/single-app environments. - Logger.LogApplicationName=true - # Determines whether ESAPI should log the server IP and port. This might be clutter in some single-server environments. - Logger.LogServerIP=true - # LogFileName, the name of the logging file. Provide a full directory path (e.g., C:\\ESAPI\\ESAPI_logging_file) if you - # want to place it in a specific directory. - Logger.LogFileName=ESAPI_logging_file - # MaxLogFileSize, the max size (in bytes) of a single log file before it cuts over to a new one (default is 10,000,000) - Logger.MaxLogFileSize=10000000 - # Determines whether ESAPI should log the user info. - Logger.UserInfo=true - # Determines whether ESAPI should log the session id and client IP. - Logger.ClientInfo=true - -See GitHub issue #560 for additional details. - - -Finally, while ESAPI still supports JDK 7 (even though that too is way past end-of-life), the next ESAPI release will move to JDK 8 as the minimal baseline. (We already use Java 8 for development but still to Java 7 source and runtime compatibility.) We need to do this out of necessity because some of our dependencies are no longer doing updates that support Java 7. +If you use ESAPI 2.5.0.0 or later, you will get an ClassNotFoundException as the root cause if you still have your ESAPI.Logger property set to use Log4J because the org.owasp.esapi.logger.log4j.Log4JFactory class has been completely removed from the ESAPI jar. If you are dead set on continuing to use Log4J 1, you ought to be able to do so via SLF4J. The set up for Log4J 1 (which has not be tested), should be similar to configure ESAPI to use SLF4J with Log4J 2 as described here: + https://github.com/ESAPI/esapi-java-legacy/wiki/Using-ESAPI-with-SLF4J#slf4j-using-log4j-2x ----------------------------------------------------------------------------- Remaining Known Issues / Problems ----------------------------------------------------------------------------- -If you use Java 7 (the minimal Java baseline supported by ESAPI) and try to run 'mvn test' there is one test that fails. This test passes with Java 8. The failing test is: - - [ERROR] Tests run: 5, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.203 s - <<< FAILURE! - in org.owasp.esapi.crypto.SecurityProviderLoaderTest - [ERROR] org.owasp.esapi.crypto.SecurityProviderLoaderTest.testWithBouncyCastle - Time elapsed: 0.116 s <<< FAILURE! - java.lang.AssertionError: Encryption w/ Bouncy Castle failed with - EncryptionException for preferred cipher transformation; exception was: - org.owasp.esapi.errors.EncryptionException: Encryption failure (unavailable - cipher requested) - at - org.owasp.esapi.crypto.SecurityProviderLoaderTest.testWithBouncyCastle(Security - ProviderLoaderTest.java:133) - -I will spare you all the details and tell you that this has to do with Java 7 not being able to correctly parse the signed Bouncy Castle JCE provider jar. More details are available at: - https://www.bouncycastle.org/latest_releases.html -and - https://github.com/bcgit/bc-java/issues/477 -I am sure that there are ways of making Bouncy Castle work with Java 7, but since ESAPI does not rely on Bouncy Castle (it can use any compliant JCE provider), this should not be a problem. (It works fine with the default SunJCE provider.) If it is important to get the BC provider working with the ESAPI Encryptor and Java 7, then open a GitHub issue and we will take a deeper look at it and see if we can suggest something. - - - -Another problem is if you run 'mvn test' from the 'cmd' prompt (and possibly PowerShell as well), you will get intermittent failures (generally between 10-25% of the time) at arbitrary spots. If you run it again without any changes it will work fine without any failures. We have discovered that it doesn't seem to fail if you run the tests from an IDE like Eclipse or if you redirect both stdout and stderr to a file; e.g., - - C:\code\esapi-java-legacy> mvn test >testoutput.txt 2>&1 - -We believe these failures is because the maven-surefire-plugin is by default not forking a new JVM process for each test class. We are looking into this. For now, we have only have observed this behavior on Windows 10. If you see this error, please do NOT report it as a GitHub issue unless you know a fix for it. (And yes, we are aware of 'false' in the pom for the maven-surefire-plugin, but that causes other tests to fail that we haven't had time to fix.) +None known, other than the remaining open issues on GitHub. ----------------------------------------------------------------------------- @@ -128,13 +84,16 @@ We believe these failures is because the maven-surefire-plugin is by default not ----------------------------------------------------------------------------- -* Minor updates to README.md file +* Minor updates to README.md file with respect to version information. ----------------------------------------------------------------------------- Developer Activity Report (Changes between release ${PREV_VERSION} and ${VERSION}, i.e., between ${PREV_RELEASE_DATE} and ${YYYY_MM_DD_RELEASE_DATE}) Generated manually (this time) -- all errors are the fault of kwwall and his inability to do simple arithmetic. +@@@@ +@@@@ This section needs to be manually updated. +@@@@ Developer Total Total Number # Merged (GitHub ID) commits of Files Changed PRs ======================================================== @@ -144,8 +103,6 @@ kwwall 7 8 0 ======================================================== Total PRs: 2 -There were also several snyk-bot PRs that were rejected for various reasons, mostly because 1) I was already making the proposed changes and preferred to do them in single commit or 2) there were other reasons for rejecting them (such as the dependency requiring Java 8). The proposed changes that were not outright rejected were included as part of commit a8a79bc5196653500ce664b7b063284e60bddaa0. - ----------------------------------------------------------------------------- CHANGELOG: Create your own. May I suggest: @@ -154,6 +111,13 @@ CHANGELOG: Create your own. May I suggest: which will show all the commits since just after the previous (${PREV_VERSION}) release. + Alternately, you can download the most recent ESAPI source and run + + mvn site + + which will create a CHANGELOG file named 'target/site/changelog.html' + + ----------------------------------------------------------------------------- Direct and Transitive Runtime and Test Dependencies: @@ -163,8 +127,9 @@ Direct and Transitive Runtime and Test Dependencies: ----------------------------------------------------------------------------- +@@@@ Review these notes, especially the reference to the AntiSamy version information. Acknowledgments: - Another hat tip to Dave Wichers for promptly releasing AntiSamy 1.6.1. And thanks to Matt Seil, Jeremiah Stacey, and all the ESAPI users who make this worthwhile. This is for you. + Another hat tip to Dave Wichers and the AntiSamy crew for promptly releasing AntiSamy 1.7.0. And thanks to Matt Seil, Jeremiah Stacey, and all the ESAPI users who make this worthwhile. This is for you. A special thanks to the ESAPI community from the ESAPI project co-leaders: Kevin W. Wall (kwwall) <== The irresponsible party for these release notes! diff --git a/scripts/vars.2.4.0.0 b/scripts/vars.2.4.0.0 new file mode 100644 index 000000000..9e2f84ded --- /dev/null +++ b/scripts/vars.2.4.0.0 @@ -0,0 +1,14 @@ +# Do NOT edit this file directly. It will be created by the new createVarsFile.sh script, +# which should be run prior to the newReleaseNotes.sh script. + +# ESAPI (new / current) version +VERSION=2.4.0.0 + +# Previous ESAPI version +PREV_VERSION=2.3.0.0 + +# Release date of current version in yyyy-mm-dd format +YYYY_MM_DD_RELEASE_DATE=2022-04-24 + +# Previous ESAPI release date in same format +PREV_RELEASE_DATE=2022-04-16 diff --git a/scripts/vars.2.5.0.0 b/scripts/vars.2.5.0.0 new file mode 100644 index 000000000..e01d7dd54 --- /dev/null +++ b/scripts/vars.2.5.0.0 @@ -0,0 +1,14 @@ +# Do NOT edit this file directly. It will be created by the new createVarsFile.sh script, +# which should be run prior to the newReleaseNotes.sh script. + +# ESAPI (new / current) version +VERSION=2.5.0.0 + +# Previous ESAPI version +PREV_VERSION=2.4.0.0 + +# Release date of current version in yyyy-mm-dd format +YYYY_MM_DD_RELEASE_DATE=2022-07-17 + +# Previous ESAPI release date in same format +PREV_RELEASE_DATE=2022-04-24 diff --git a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleAntisamyPropertyTest.java b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleAntisamyPropertyTest.java index ccd2e1d6d..082bd626c 100644 --- a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleAntisamyPropertyTest.java +++ b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleAntisamyPropertyTest.java @@ -15,12 +15,8 @@ */ package org.owasp.esapi.reference.validation; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.owasp.validator.html.Policy; +import org.owasp.validator.html.PolicyException; /** * Isolate scope test to assert the behavior of the HTMLValidationRule @@ -32,21 +28,9 @@ public class HTMLValidationRuleAntisamyPropertyTest { */ private static final String INVALID_ANTISAMY_POLICY_FILE = "antisamy-InvalidPolicy.xml"; - @AfterClass - public static void enableAntisamySchemaValidation() { - Policy.setSchemaValidation(true); - } - - @BeforeClass - public static void disableAntisamySchemaValidation() { - Policy.setSchemaValidation(false); - //System property is read once, so we're preferring the static method for testing. - //System.setProperty( "owasp.validator.validateschema", "false" ); - } - - @Test + @Test( expected = PolicyException.class ) public void checkAntisamySystemPropertyWorksAsAdvertised() throws Exception { HTMLValidationRule.loadAntisamyPolicy(INVALID_ANTISAMY_POLICY_FILE); } - + } From 1117006dc1e0746bac9ec1efdd0e16c694348669 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sun, 17 Jul 2022 17:23:50 -0400 Subject: [PATCH 025/197] Final adjustments to pom.xml for 2.5.0.0 release. --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 05bb55181..9ffdc56a2 100644 --- a/pom.xml +++ b/pom.xml @@ -146,7 +146,7 @@ - 2021-05-07 00:00:00 + 2021-05-24 00:00:00 @@ -683,7 +683,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.3.0 + 3.4.0 From 930e390c095020c26ac776459faff652c4a93460 Mon Sep 17 00:00:00 2001 From: kwwall Date: Sun, 17 Jul 2022 17:24:37 -0400 Subject: [PATCH 026/197] Added note regarding why PR figures different than Change Log Report. --- documentation/esapi4java-core-2.5.0.0-release-notes.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/documentation/esapi4java-core-2.5.0.0-release-notes.txt b/documentation/esapi4java-core-2.5.0.0-release-notes.txt index 67186f17f..2fd859f7c 100644 --- a/documentation/esapi4java-core-2.5.0.0-release-notes.txt +++ b/documentation/esapi4java-core-2.5.0.0-release-notes.txt @@ -145,6 +145,8 @@ Generated manually (this time) -- all errors are the fault of kwwall and his ina # # 34 PRs merged since ESAPI 2.4.0.0 release +# Note: Figures here may not agree with generated Change Log Report, which is date-based, +# as some commits included in this release were prior to ESAPI 2.4.0.0. # Developer Total Total Number # Merged (GitHub ID) commits of Files Changed PRs From 84cceeff4e8f7601a0ff9fdbe05b8fd2aee04e47 Mon Sep 17 00:00:00 2001 From: kwwall Date: Tue, 19 Jul 2022 22:25:38 -0400 Subject: [PATCH 027/197] Add (multiple) suppression rules for CVE-2017-10355 as it's an FP. --- suppressions.xml | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/suppressions.xml b/suppressions.xml index b367558ce..c0146386e 100644 --- a/suppressions.xml +++ b/suppressions.xml @@ -11,4 +11,50 @@ ^pkg:maven/org\.apache\.xmlgraphics/batik\-i18n@.*$ CVE-2020-7791 + + + + + + f051f988aa2c9b4d25d05f95742ab0cc3ed789e2 + cpe:/a:apache:xerces-j + + + + f051f988aa2c9b4d25d05f95742ab0cc3ed789e2 + cpe:/a:apache:xerces2_java + + + + ^pkg:maven/xerces/xercesImpl@.*$ + CVE-2017-10355 + + + + CVE-2017-10355 + + From d3b40cf56d71681c9bfae3d32c4ee859c57bfecb Mon Sep 17 00:00:00 2001 From: kwwall Date: Tue, 19 Jul 2022 22:40:53 -0400 Subject: [PATCH 028/197] Update the slipped release date. --- scripts/vars.2.5.0.0 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/vars.2.5.0.0 b/scripts/vars.2.5.0.0 index e01d7dd54..4d33532ea 100644 --- a/scripts/vars.2.5.0.0 +++ b/scripts/vars.2.5.0.0 @@ -8,7 +8,7 @@ VERSION=2.5.0.0 PREV_VERSION=2.4.0.0 # Release date of current version in yyyy-mm-dd format -YYYY_MM_DD_RELEASE_DATE=2022-07-17 +YYYY_MM_DD_RELEASE_DATE=2022-07-20 # Previous ESAPI release date in same format PREV_RELEASE_DATE=2022-04-24 From 177b5168318a62d0fcbeb00679656c9a036c0952 Mon Sep 17 00:00:00 2001 From: kwwall Date: Tue, 19 Jul 2022 23:10:24 -0400 Subject: [PATCH 029/197] Update Maven plougins. maven-deploy-plugin ............................. 3.0.0-M2 -> 3.0.0 maven-install-plugin ............................ 3.0.0-M1 -> 3.0.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9ffdc56a2..3a8f27819 100644 --- a/pom.xml +++ b/pom.xml @@ -529,7 +529,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.0.0-M2 + 3.0.0 @@ -633,7 +633,7 @@ org.apache.maven.plugins maven-install-plugin - 3.0.0-M1 + 3.0.0 From 8993a1ac07157e3207c342d915da6ee0cfc40c55 Mon Sep 17 00:00:00 2001 From: kwwall Date: Tue, 19 Jul 2022 23:14:32 -0400 Subject: [PATCH 030/197] Further updates needed for 2.5.0.0 release notes. --- .../esapi4java-core-2.5.0.0-release-notes.txt | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/documentation/esapi4java-core-2.5.0.0-release-notes.txt b/documentation/esapi4java-core-2.5.0.0-release-notes.txt index 2fd859f7c..b47b084e0 100644 --- a/documentation/esapi4java-core-2.5.0.0-release-notes.txt +++ b/documentation/esapi4java-core-2.5.0.0-release-notes.txt @@ -1,5 +1,5 @@ Release notes for ESAPI 2.5.0.0 - Release date: 2022-07-17 + Release date: 2022-07-20 Project leaders: -Kevin W. Wall -Matt Seil @@ -41,7 +41,7 @@ ESAPI 2.5.0.0 release: 206 Java source files 4274 JUnit tests in 131 Java source files (0 tests skipped) -18 GitHub Issues closed in this release, including those we've decided not to fix (marked 'wontfix' and 'falsepositive'). +19 GitHub Issues closed in this release, including those we've decided not to fix (marked 'wontfix' and 'falsepositive'). (Reference: https://github.com/ESAPI/esapi-java-legacy/issues?q=is%3Aissue+state%3Aclosed+updated%3A%3E%3D2022-04-24) Issue # GitHub Issue Title @@ -64,6 +64,7 @@ Issue # GitHub Issue Title 620 Move the default property names and values out of a reference implementation class Component-SecurityConfiguration 587 Drop Xerces dependency from pom.xml Build-Maven Vulnerable Dependencies 534 Delete Deprecated Log4J implementation and Dependencies wait4future +507 LDAP encoding of slash character ----------------------------------------------------------------------------- @@ -120,15 +121,19 @@ Instead, we simply changed the JUnit test to check that the expected AntiSamy or Remaining Known Issues / Problems ----------------------------------------------------------------------------- -'mvn site' fails to build these two reports: +* 'mvn site' fails to build these two reports: "Tag reference" report --- maven-taglib-plugin:2.4:tagreference "Taglibdoc documentation" report --- maven-taglib-plugin:2.4:taglibdoc -Thus no tag library documentation will be generated. :-( + Thus no tag library documentation will be generated. :-( -We are attempting to find a solution, but on the surface, it seems like the maven-taglib-plugin does not play nicely with versions of Java after Java 6. (So, this probably has been happening for a while and we just noticed it.) + We are attempting to find a solution, but on the surface, it seems like the maven-taglib-plugin does not play nicely with versions of Java after Java 6. (So, this probably has been happening for a while and we just noticed it.) -No others problems are known, other than the remaining open issues on GitHub. +* We have had to suppress CVE-2017-10355, related to the transitive dependency xercesImpl-2.12.2.jar via antisamy-1.7.0.jar. It is the same jar that has been used for the past 2 years but the CVE just started popping up now, apparently because of changes to Sonatype's OSS Index. More details are available in the OWASP Dependency Check suppression rules contained in the 'suppressions.xml' file. Note that other SCA tools such as Snyk or GitHub Dependabot are not presently reporting it, but it bears watching. + +* Trying to run 'mvn test' with Java 11 or later results in multiple errors in maven-surefire-plugin, so for now, that should be avoided. We think we may have a solution, but at this point, it is too late to test for this release. + +* No others problems are known, other than the remaining open issues on GitHub. ----------------------------------------------------------------------------- @@ -140,19 +145,23 @@ No others problems are known, other than the remaining open issues on GitHub. ----------------------------------------------------------------------------- -Developer Activity Report (Changes between release 2.4.0.0 and 2.5.0.0, i.e., between 2022-04-24 and 2022-07-17) +Developer Activity Report (Changes between release 2.4.0.0 and 2.5.0.0, i.e., between 2022-04-24 and 2022-07-20) Generated manually (this time) -- all errors are the fault of kwwall and his inability to do simple arithmetic. # # 34 PRs merged since ESAPI 2.4.0.0 release -# Note: Figures here may not agree with generated Change Log Report, which is date-based, -# as some commits included in this release were prior to ESAPI 2.4.0.0. +# Apparent disparement in the figures below may be explained by serveral things: +# * My failure to do proper counting and basic arithmetic after 4 hours of tweak release notes. +# * Different basis for calculations: +# - Figures here may not agree with generated Change Log Report, which is date-based, as some commits included in this release were prior to ESAPI 2.4.0.0 and thus not included in the Change Log Report. +# - Some commits are done without PRs. Generally, we don't require PRs when we don't require code reviews. That generally is restricted to documenation files, making simple config file changes, and correcting obvious typos. Commits without PRs are resricted to the 3 ESAPI core team members. +# - Sometimes in a PR, multiple commits touch a file multiple times so we count those files once for each commit. # Developer Total Total Number # Merged (GitHub ID) commits of Files Changed PRs ======================================================== jeremiahjstacey 265 180 24 -kwwall 35 64 5 +kwwall 39 69 5 xeno6696 1 267 1 noloader 5 2 1 stevebosman-oc 4 3 2 From 2042bf13b96359edff42354fced33da7acfc5b59 Mon Sep 17 00:00:00 2001 From: "Kevin W. Wall" Date: Wed, 20 Jul 2022 20:52:39 -0400 Subject: [PATCH 031/197] Fixed botched 2.5.0.0 release date. Started release on 7/17, but stopped because 'mvn deploy' failed due to Dependency Check issues. Once resolved, I forgot to adjust the official release date. --- documentation/esapi4java-core-2.5.0.0-release-notes.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/esapi4java-core-2.5.0.0-release-notes.txt b/documentation/esapi4java-core-2.5.0.0-release-notes.txt index 67186f17f..1177b4820 100644 --- a/documentation/esapi4java-core-2.5.0.0-release-notes.txt +++ b/documentation/esapi4java-core-2.5.0.0-release-notes.txt @@ -1,5 +1,5 @@ Release notes for ESAPI 2.5.0.0 - Release date: 2022-07-17 + Release date: 2022-07-20 Project leaders: -Kevin W. Wall -Matt Seil @@ -140,7 +140,7 @@ No others problems are known, other than the remaining open issues on GitHub. ----------------------------------------------------------------------------- -Developer Activity Report (Changes between release 2.4.0.0 and 2.5.0.0, i.e., between 2022-04-24 and 2022-07-17) +Developer Activity Report (Changes between release 2.4.0.0 and 2.5.0.0, i.e., between 2022-04-24 and 2022-07-20) Generated manually (this time) -- all errors are the fault of kwwall and his inability to do simple arithmetic. # From 7f829a3885f453f1e9a10bbf1d9c771ec0d95383 Mon Sep 17 00:00:00 2001 From: kwwall Date: Wed, 20 Jul 2022 21:03:48 -0400 Subject: [PATCH 032/197] Bump ESAPI version for next planned release. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3a8f27819..e830a2f3d 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.owasp.esapi esapi - 2.5.0.0 + 2.5.1.0-SNAPSHOT jar From a37e63b6fe1105709279e4976908068f2c2c81d2 Mon Sep 17 00:00:00 2001 From: kwwall Date: Wed, 20 Jul 2022 21:06:43 -0400 Subject: [PATCH 033/197] Bump cyclonedx-maven-plugin version to 2.7.1. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e830a2f3d..80bf09583 100644 --- a/pom.xml +++ b/pom.xml @@ -445,7 +445,7 @@ org.cyclonedx cyclonedx-maven-plugin - 2.7.0 + 2.7.1 package From 0f4442d7432d2825799dde2b739099826cbf9fe0 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Tue, 26 Jul 2022 23:04:00 -0400 Subject: [PATCH 034/197] Fix typos (#724) Future note: We need to address the 2 comments, but not wanting the perfect to become the enemy of the good, I'm merging this now. --- CONTRIBUTING-TO-ESAPI.txt | 32 ++++++++++++++++---------------- README.md | 4 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/CONTRIBUTING-TO-ESAPI.txt b/CONTRIBUTING-TO-ESAPI.txt index c6ad2bcfc..ee0df0eb3 100644 --- a/CONTRIBUTING-TO-ESAPI.txt +++ b/CONTRIBUTING-TO-ESAPI.txt @@ -3,12 +3,12 @@ Getting Started: If you have not already done so, go back and read the section "Contributing to ESAPI legacy" in ESAPI's README.md file. It - make contain updates and advice not contained herein. + may contain updates and advice not contained herein. A Special Note on GitHub Authentication: - GitHub has announced that they are deprecating authentiation based on - username / password and beginning 2021-08-13, you will no longer be able - to your password to authenticate to 'git' operations on GitHub.com. + GitHub has announced that they are deprecating password based authentication + using username / password and beginning 2021-08-13, you will no longer be + able to your password to authenticate to 'git' operations on GitHub.com. Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for details and plan accordingly. @@ -21,22 +21,23 @@ Finding Something Interesting to Work on: or "help wanted", those are good places to start for someone not yet familiar with the ESAPI code base. - You will need a account on GitHub though. Once you create one, let me know + You will need a account on GitHub though. Once you create one, let us know what it is. Then if you want to work on a particular issue, we can assign it to you so someone else won't take it. - If you have questions, email Kevin Wall (Kevin.W.Wall@gmail.com) or Matt Seil (xeno6696@gmail.com). + If you have questions, email Kevin Wall (Kevin.W.Wall@gmail.com) or Matt + Seil (xeno6696@gmail.com). Overview: We are following the branching model described in https://nvie.com/posts/a-successful-git-branching-model - If you are unfamiliar with it, you would be advised to give it a - quick perusal. The major point is that the 'main' (formerly 'master') branch - is reserved for official releases (which will be tagged), the 'develop' branch is - used for ongoing development work and is the default branch, and we generally work - off 'issue' branches named 'issue-#' where # is the GitHub issue number. - (The last is not an absolute requirement, but rather a suggested - approach.) + If you are unfamiliar with it, you would be advised to give it a quick + perusal. The major point is that the 'main' (formerly 'master') branch is + reserved for official releases (which will be tagged), the 'develop' branch + is used for ongoing development work and is the default branch, and we + generally work off 'issue' branches named 'issue-#' where # is the GitHub + issue number. (The last is not an absolute requirement, but rather a + suggested approach.) Finally, we recommend setting the git property 'core.autocrlf' to 'input' in your $HOME/.gitconfig file; e.g., that file should contain something @@ -47,8 +48,7 @@ Overview: Required Software: We use Maven for building. Maven 3.3.9 or later is required. You also need - JDK 8 or later. - [Note: If you use JDK 9 or later, there will be multiple + JDK 8 or later. [Note: If you use JDK 9 or later, there will be multiple failures when you try to run 'mvn test' as well as some general warnings. See ESAPI GitHub issue #496 for details. We welcome volunteers to address this.] @@ -106,7 +106,7 @@ Steps to work with ESAPI: 9. Go to your personal, forked ESAPI GitHub repo (web interface) and create a 'Pull Request' from your 'issue-#' branch. 10. Back on your local personal laptop / desktop, merge your issue branch with - your local 'develop' branch. I.e. + your local 'develop' branch. I.e., $ git checkout develop $ git merge issue-444 diff --git a/README.md b/README.md index 8e4933f1e..1fac65501 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ before posting your issue. If believe you have found a vulnerability in ESAPI legacy, for the sake of the ESAPI community, please practice Responsible Disclosure. (Note: We will be sure you get credit and will work with you to create a GitHub Security Advisory, and -if you so choose, to persue filing a CVE via the GitHub CNA.) +if you so choose, to pursue filing a CVE via the GitHub CNA.) You are of course encouraged to first search our GitHub issues list (see above) to see if it has already been reported. If it has not, then please contact @@ -175,7 +175,7 @@ In mid-2014 ESAPI migrated all code and issues from Google Code to GitHub. This ### What about the issues still located on Google Code? All issues from Google Code have been migrated to GitHub issues. We now use GitHut Issues for reporting everything *except* security vulnerabilities. -Other bug tracking sites are undoubtably more advanced, but as developers, +Other bug tracking sites are undoubtedly more advanced, but as developers, we do not want to spent time having to close issues from multiple bug-tracking systems. Therefore, until the synchronization happens with the Atlassian Jira instance that we have (but are not using; see GitHub issue #371), please From 952e3b1b0d1fb88c8c97d23afbc9a0a74aa2f793 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Tue, 26 Jul 2022 23:09:31 -0400 Subject: [PATCH 035/197] Whitespace check-in (#720) @xeno6696 - Since @noloader touched all these files last, he owns them and is forever stuck doing bug fixes on them, right? Seriously, thanks Jeff. This is one of those bookkeeping matters that I generally don't require a GitHub issue for, but feel free to create one, assign it to yourself, and reference this PR if you would like. Up to you. --- README.md | 2 +- .../ESAPI-configuration-user-guide.md | 8 +- documentation/esapi4java-2.0-readme.txt | 2 +- ...va-2.0rc6-override-log4jloggingfactory.txt | 14 +- ...i4java-core-2.0-readme-crypto-changes.html | 26 +- ...-core-2.0-symmetric-crypto-user-guide.html | 18 +- .../esapi4java-core-2.1-release-notes.txt | 4 +- .../esapi4java-core-2.2.0.0-release-notes.txt | 16 +- .../esapi4java-core-2.2.1.0-release-notes.txt | 42 +-- .../esapi4java-core-2.2.1.1-release-notes.txt | 14 +- .../esapi4java-core-2.2.2.0-release-notes.txt | 18 +- .../esapi4java-core-2.2.3.0-release-notes.txt | 18 +- .../esapi4java-core-2.2.3.1-release-notes.txt | 14 +- .../esapi4java-core-2.3.0.0-release-notes.txt | 4 +- .../esapi4java-core-2.4.0.0-release-notes.txt | 16 +- ...esapi4java-core-TEMPLATE-release-notes.txt | 4 +- src/examples/java/ESAPILogging.java | 2 +- src/examples/java/PersistedEncryptedData.java | 2 +- .../org/owasp/esapi/AccessController.java | 252 +++++++++--------- .../org/owasp/esapi/AccessReferenceMap.java | 58 ++-- .../java/org/owasp/esapi/Authenticator.java | 158 +++++------ src/main/java/org/owasp/esapi/ESAPI.java | 46 ++-- src/main/java/org/owasp/esapi/Encoder.java | 208 +++++++-------- .../org/owasp/esapi/EncoderConstants.java | 20 +- .../org/owasp/esapi/EncryptedProperties.java | 54 ++-- src/main/java/org/owasp/esapi/Encryptor.java | 92 +++---- .../java/org/owasp/esapi/ExecuteResult.java | 4 +- src/main/java/org/owasp/esapi/Executor.java | 16 +- .../java/org/owasp/esapi/HTTPUtilities.java | 16 +- .../org/owasp/esapi/IntrusionDetector.java | 28 +- src/main/java/org/owasp/esapi/LogFactory.java | 34 +-- src/main/java/org/owasp/esapi/Logger.java | 226 ++++++++-------- .../java/org/owasp/esapi/PreparedString.java | 24 +- src/main/java/org/owasp/esapi/PropNames.java | 2 +- src/main/java/org/owasp/esapi/Randomizer.java | 4 +- src/main/java/org/owasp/esapi/SafeFile.java | 18 +- .../owasp/esapi/SecurityConfiguration.java | 180 ++++++------- .../java/org/owasp/esapi/StringUtilities.java | 18 +- src/main/java/org/owasp/esapi/User.java | 186 ++++++------- .../org/owasp/esapi/ValidationErrorList.java | 48 ++-- .../java/org/owasp/esapi/ValidationRule.java | 10 +- src/main/java/org/owasp/esapi/Validator.java | 18 +- .../esapi/codecs/AbstractCharacterCodec.java | 14 +- .../org/owasp/esapi/codecs/AbstractCodec.java | 28 +- .../esapi/codecs/AbstractIntegerCodec.java | 12 +- .../codecs/AbstractPushbackSequence.java | 14 +- .../java/org/owasp/esapi/codecs/CSSCodec.java | 30 +-- .../java/org/owasp/esapi/codecs/Codec.java | 36 +-- .../java/org/owasp/esapi/codecs/DB2Codec.java | 2 +- .../owasp/esapi/codecs/HTMLEntityCodec.java | 94 +++---- .../java/org/owasp/esapi/codecs/HashTrie.java | 6 +- src/main/java/org/owasp/esapi/codecs/Hex.java | 12 +- .../owasp/esapi/codecs/JavaScriptCodec.java | 32 +-- .../esapi/codecs/LegacyHTMLEntityCodec.java | 70 ++--- .../org/owasp/esapi/codecs/MySQLCodec.java | 68 ++--- .../org/owasp/esapi/codecs/OracleCodec.java | 12 +- .../org/owasp/esapi/codecs/PercentCodec.java | 14 +- .../esapi/codecs/PushBackSequenceImpl.java | 20 +- .../owasp/esapi/codecs/PushbackSequence.java | 12 +- .../owasp/esapi/codecs/PushbackString.java | 28 +- .../org/owasp/esapi/codecs/UnixCodec.java | 24 +- .../org/owasp/esapi/codecs/VBScriptCodec.java | 30 +-- .../org/owasp/esapi/codecs/WindowsCodec.java | 24 +- .../owasp/esapi/codecs/XMLEntityCodec.java | 14 +- .../java/org/owasp/esapi/codecs/package.html | 2 +- .../ref/EncodingPatternPreservation.java | 12 +- .../EsapiPropertyLoaderFactory.java | 2 +- .../StandardEsapiPropertyLoader.java | 2 +- .../configuration/XmlEsapiPropertyLoader.java | 2 +- .../consts/EsapiConfiguration.java | 4 +- .../org/owasp/esapi/crypto/CipherSpec.java | 48 ++-- .../org/owasp/esapi/crypto/CipherText.java | 112 ++++---- .../esapi/crypto/CipherTextSerializer.java | 46 ++-- .../owasp/esapi/crypto/CryptoDiscoverer.java | 2 +- .../org/owasp/esapi/crypto/CryptoHelper.java | 36 +-- .../org/owasp/esapi/crypto/CryptoToken.java | 98 +++---- .../esapi/crypto/KeyDerivationFunction.java | 56 ++-- .../org/owasp/esapi/crypto/PlainText.java | 20 +- .../esapi/crypto/SecurityProviderLoader.java | 12 +- .../esapi/errors/AccessControlException.java | 10 +- .../AuthenticationAccountsException.java | 16 +- .../AuthenticationCredentialsException.java | 12 +- .../esapi/errors/AuthenticationException.java | 12 +- .../errors/AuthenticationHostException.java | 12 +- .../errors/AuthenticationLoginException.java | 12 +- .../esapi/errors/AvailabilityException.java | 12 +- .../esapi/errors/CertificateException.java | 12 +- .../esapi/errors/ConfigurationException.java | 4 +- .../owasp/esapi/errors/EncodingException.java | 12 +- .../esapi/errors/EncryptionException.java | 12 +- .../errors/EncryptionRuntimeException.java | 10 +- .../errors/EnterpriseSecurityException.java | 18 +- .../EnterpriseSecurityRuntimeException.java | 18 +- .../owasp/esapi/errors/ExecutorException.java | 12 +- .../esapi/errors/IntegrityException.java | 12 +- .../esapi/errors/IntrusionException.java | 18 +- .../ValidationAvailabilityException.java | 8 +- .../esapi/errors/ValidationException.java | 26 +- .../errors/ValidationUploadException.java | 10 +- .../owasp/esapi/filters/ClickjackFilter.java | 30 +-- .../org/owasp/esapi/filters/ESAPIFilter.java | 18 +- .../filters/RequestRateThrottleFilter.java | 16 +- .../owasp/esapi/filters/SecurityWrapper.java | 8 +- .../esapi/filters/SecurityWrapperRequest.java | 16 +- .../filters/SecurityWrapperResponse.java | 58 ++-- .../logging/appender/ClientInfoSupplier.java | 8 +- .../appender/EventTypeLogSupplier.java | 8 +- .../esapi/logging/appender/LogAppender.java | 6 +- .../logging/appender/LogPrefixAppender.java | 20 +- .../logging/appender/ServerInfoSupplier.java | 12 +- .../logging/appender/UserInfoSupplier.java | 20 +- .../logging/cleaning/CodecLogScrubber.java | 8 +- .../cleaning/CompositeLogScrubber.java | 8 +- .../esapi/logging/cleaning/LogScrubber.java | 8 +- .../logging/cleaning/NewlineLogScrubber.java | 6 +- .../logging/java/ESAPICustomJavaLevel.java | 10 +- .../logging/java/ESAPIErrorJavaLevel.java | 8 +- .../esapi/logging/java/JavaLogBridge.java | 8 +- .../esapi/logging/java/JavaLogBridgeImpl.java | 6 +- .../esapi/logging/java/JavaLogFactory.java | 24 +- .../logging/java/JavaLogLevelHandler.java | 8 +- .../logging/java/JavaLogLevelHandlers.java | 10 +- .../owasp/esapi/logging/java/JavaLogger.java | 12 +- .../esapi/logging/slf4j/Slf4JLogBridge.java | 10 +- .../logging/slf4j/Slf4JLogBridgeImpl.java | 10 +- .../esapi/logging/slf4j/Slf4JLogFactory.java | 40 +-- .../logging/slf4j/Slf4JLogLevelHandler.java | 8 +- .../logging/slf4j/Slf4JLogLevelHandlers.java | 8 +- .../esapi/logging/slf4j/Slf4JLogger.java | 46 ++-- src/main/java/org/owasp/esapi/package.html | 32 +-- .../reference/AbstractAccessReferenceMap.java | 20 +- .../reference/AbstractAuthenticator.java | 26 +- .../reference/DefaultAccessController.java | 22 +- .../owasp/esapi/reference/DefaultEncoder.java | 122 ++++----- .../esapi/reference/DefaultExecutor.java | 32 +-- .../esapi/reference/DefaultHTTPUtilities.java | 22 +- .../reference/DefaultIntrusionDetector.java | 36 +-- .../esapi/reference/DefaultRandomizer.java | 22 +- .../DefaultSecurityConfiguration.java | 2 +- .../owasp/esapi/reference/DefaultUser.java | 76 +++--- .../esapi/reference/DefaultValidator.java | 26 +- .../reference/FileBasedAuthenticator.java | 12 +- .../reference/IntegerAccessReferenceMap.java | 8 +- .../accesscontrol/AlwaysTrueACR.java | 2 +- .../reference/accesscontrol/BaseACR.java | 4 +- .../accesscontrol/DelegatingACR.java | 30 +-- .../accesscontrol/DynaBeanACRParameter.java | 36 +-- .../ExperimentalAccessController.java | 30 +-- .../accesscontrol/FileBasedACRs.java | 164 ++++++------ .../ACRParameterLoaderHelper.java | 30 +-- .../policyloader/ACRPolicyFileLoader.java | 30 +-- .../DynaBeanACRParameterLoader.java | 10 +- .../EchoDynaBeanPolicyParameterACR.java | 2 +- .../accesscontrol/policyloader/PolicyDTO.java | 10 +- .../policyloader/PolicyParameters.java | 18 +- .../crypto/DefaultEncryptedProperties.java | 22 +- .../crypto/EncryptedPropertiesUtils.java | 4 +- .../crypto/ReferenceEncryptedProperties.java | 4 +- .../validation/BaseValidationRule.java | 42 +-- .../validation/CreditCardValidationRule.java | 38 +-- .../validation/DateValidationRule.java | 22 +- .../validation/HTMLValidationRule.java | 46 ++-- .../validation/IntegerValidationRule.java | 22 +- .../validation/NumberValidationRule.java | 38 +-- .../validation/StringValidationRule.java | 12 +- .../esapi/reference/validation/package.html | 2 +- .../owasp/esapi/util/ByteConversionUtil.java | 2 +- .../org/owasp/esapi/util/CollectionsUtil.java | 10 +- .../owasp/esapi/util/DefaultMessageUtil.java | 12 +- .../java/org/owasp/esapi/util/ObjFactory.java | 4 +- .../esapi/waf/ConfigurationException.java | 8 +- .../ESAPIWebApplicationFirewallFilter.java | 16 +- .../org/owasp/esapi/waf/actions/Action.java | 8 +- .../owasp/esapi/waf/actions/BlockAction.java | 8 +- .../esapi/waf/actions/DefaultAction.java | 8 +- .../esapi/waf/actions/DoNothingAction.java | 8 +- .../esapi/waf/actions/RedirectAction.java | 8 +- .../org/owasp/esapi/waf/actions/package.html | 4 +- .../AppGuardianConfiguration.java | 14 +- .../configuration/ConfigurationParser.java | 80 +++--- .../esapi/waf/configuration/package.html | 6 +- .../InterceptingHTTPServletRequest.java | 52 ++-- .../InterceptingHTTPServletResponse.java | 14 +- .../waf/internal/InterceptingPrintWriter.java | 10 +- .../InterceptingServletOutputStream.java | 52 ++-- .../owasp/esapi/waf/internal/Parameter.java | 8 +- .../org/owasp/esapi/waf/internal/package.html | 4 +- .../java/org/owasp/esapi/waf/package.html | 2 +- .../esapi/waf/rules/AddHTTPOnlyFlagRule.java | 8 +- .../owasp/esapi/waf/rules/AddHeaderRule.java | 12 +- .../esapi/waf/rules/AddSecureFlagRule.java | 10 +- .../esapi/waf/rules/AuthenticatedRule.java | 8 +- .../owasp/esapi/waf/rules/BeanShellRule.java | 6 +- .../waf/rules/DetectOutboundContentRule.java | 20 +- .../esapi/waf/rules/EnforceHTTPSRule.java | 8 +- .../waf/rules/GeneralAttackSignatureRule.java | 10 +- .../owasp/esapi/waf/rules/HTTPMethodRule.java | 8 +- .../org/owasp/esapi/waf/rules/IPRule.java | 14 +- .../owasp/esapi/waf/rules/MustMatchRule.java | 6 +- .../esapi/waf/rules/PathExtensionRule.java | 8 +- .../esapi/waf/rules/ReplaceContentRule.java | 20 +- .../waf/rules/RestrictContentTypeRule.java | 8 +- .../waf/rules/RestrictUserAgentRule.java | 16 +- .../java/org/owasp/esapi/waf/rules/Rule.java | 6 +- .../org/owasp/esapi/waf/rules/RuleUtil.java | 6 +- .../waf/rules/SimpleVirtualPatchRule.java | 10 +- .../org/owasp/esapi/waf/rules/package.html | 6 +- .../org/owasp/esapi/ESAPIContractAPITest.java | 18 +- .../esapi/SecurityConfigurationWrapper.java | 50 ++-- .../org/owasp/esapi/StringUtilitiesTest.java | 6 +- src/test/java/org/owasp/esapi/UserTest.java | 12 +- .../owasp/esapi/ValidationErrorListTest.java | 6 +- .../owasp/esapi/codecs/AbstractCodecTest.java | 26 +- .../org/owasp/esapi/codecs/CSSCodecTest.java | 2 +- .../owasp/esapi/codecs/CodecImmunityTest.java | 6 +- .../esapi/codecs/HTMLEntityCodecTest.java | 10 +- .../owasp/esapi/codecs/MySQLCodecTest.java | 68 ++--- .../owasp/esapi/codecs/PercentCodecTest.java | 4 +- .../esapi/codecs/PushBackStringTest.java | 20 +- .../esapi/codecs/XMLEntityCodecTest.java | 6 +- .../AbstractCodecCharacterTest.java | 20 +- .../abstraction/AbstractCodecStringTest.java | 14 +- .../percent/PercentCodecCharacterTest.java | 2 +- .../percent/PercentCodecKnownIssuesTest.java | 10 +- .../percent/PercentCodecStringTest.java | 12 +- .../ref/EncodingPatternPreservationTest.java | 28 +- .../EsapiPropertyManagerTest.java | 4 +- .../StandardEsapiPropertyLoaderTest.java | 28 +- .../XmlEsapiPropertyLoaderTest.java | 2 +- .../owasp/esapi/crypto/CipherSpecTest.java | 20 +- .../owasp/esapi/crypto/CipherTextTest.java | 34 +-- .../owasp/esapi/crypto/CryptoHelperTest.java | 10 +- .../owasp/esapi/crypto/CryptoTokenTest.java | 30 +-- .../crypto/ESAPICryptoMACByPassTest.java | 6 +- .../org/owasp/esapi/crypto/PlainTextTest.java | 16 +- .../crypto/SecurityProviderLoaderTest.java | 10 +- .../EnterpriseSecurityExceptionTest.java | 22 +- .../esapi/filters/ClickjackFilterTest.java | 18 +- .../owasp/esapi/filters/SafeRequestTest.java | 14 +- .../filters/SecurityWrapperRequestTest.java | 140 +++++----- .../filters/SecurityWrapperResponseTest.java | 20 +- .../org/owasp/esapi/http/MockFilterChain.java | 6 +- .../owasp/esapi/http/MockFilterConfig.java | 8 +- .../esapi/http/MockHttpServletRequest.java | 18 +- .../esapi/http/MockHttpServletResponse.java | 18 +- .../org/owasp/esapi/http/MockHttpSession.java | 32 +-- .../esapi/http/MockRequestDispatcher.java | 8 +- .../owasp/esapi/http/MockServletContext.java | 6 +- .../esapi/http/MockServletInputStream.java | 8 +- .../appender/ClientInfoSupplierTest.java | 82 +++--- .../appender/EventTypeLogSupplierTest.java | 8 +- .../appender/LogPrefixAppenderTest.java | 14 +- .../appender/UserInfoSupplierTest.java | 40 +-- .../cleaning/CodecLogScrubberTest.java | 6 +- .../cleaning/CompositeLogScrubberTest.java | 6 +- .../cleaning/NewlineLogScrubberTest.java | 6 +- .../logging/java/JavaLogBridgeImplTest.java | 6 +- .../logging/java/JavaLogFactoryTest.java | 12 +- .../java/JavaLogLevelHandlersTest.java | 8 +- .../esapi/logging/java/JavaLoggerTest.java | 6 +- .../logging/slf4j/Slf4JLogBridgeImplTest.java | 14 +- .../logging/slf4j/Slf4JLogFactoryTest.java | 32 +-- .../slf4j/Slf4JLogLevelHandlersTest.java | 6 +- .../esapi/logging/slf4j/Slf4JLoggerTest.java | 88 +++--- .../AbstractAccessReferenceMapTest.java | 24 +- .../esapi/reference/AccessControllerTest.java | 46 ++-- .../reference/AccessReferenceMapTest.java | 62 ++--- .../esapi/reference/AuthenticatorTest.java | 88 +++--- .../DefaultSecurityConfigurationTest.java | 140 +++++----- .../DefaultValidaterDateAPITest.java | 62 ++--- .../DefaultValidatorInputStringAPITest.java | 56 ++-- .../owasp/esapi/reference/EncoderTest.java | 200 +++++++------- .../owasp/esapi/reference/ExecutorTest.java | 18 +- .../reference/ExtensiveEncoderURITest.java | 6 +- .../esapi/reference/HTTPUtilitiesTest.java | 40 +-- .../IntegerAccessReferenceMapTest.java | 62 ++--- .../reference/IntrusionDetectorTest.java | 24 +- .../owasp/esapi/reference/RandomizerTest.java | 36 +-- .../owasp/esapi/reference/SafeFileTest.java | 22 +- .../org/owasp/esapi/reference/TestDebug.java | 2 +- .../org/owasp/esapi/reference/UserTest.java | 110 ++++---- .../owasp/esapi/reference/ValidatorTest.java | 20 +- .../accesscontrol/AccessControllerTest.java | 72 ++--- .../policyloader/ACRPolicyFileLoaderTest.java | 2 +- .../esapi/reference/crypto/CryptoPolicy.java | 4 +- .../crypto/EncryptedPropertiesTest.java | 22 +- .../crypto/EncryptedPropertiesUtilsTest.java | 26 +- .../esapi/reference/crypto/EncryptorTest.java | 100 +++---- .../ReferenceEncryptedPropertiesTest.java | 20 +- .../validation/BaseValidationRuleTest.java | 22 +- .../DateValidationRulePowerMockTest.java | 74 ++--- .../validation/DateValidationRuleTest.java | 70 ++--- .../HTMLValidationRuleClasspathTest.java | 8 +- .../HTMLValidationRuleCleanTest.java | 6 +- .../validation/StringValidationRuleTest.java | 62 ++--- .../org/owasp/esapi/util/FileTestUtils.java | 4 +- .../org/owasp/esapi/util/ObjFactoryTest.java | 34 +-- .../org/owasp/esapi/waf/AddHeaderTest.java | 26 +- .../org/owasp/esapi/waf/BeanShellTest.java | 10 +- .../owasp/esapi/waf/DetectOutboundTest.java | 34 +-- .../owasp/esapi/waf/DynamicInsertionTest.java | 30 +-- .../esapi/waf/EnforceAuthenticationTest.java | 12 +- .../org/owasp/esapi/waf/EnforceHTTPSTest.java | 16 +- .../org/owasp/esapi/waf/GoodRequestTest.java | 10 +- .../org/owasp/esapi/waf/HttpOnlyTest.java | 40 +-- .../esapi/waf/MockWafServletContext.java | 6 +- .../org/owasp/esapi/waf/MustMatchTest.java | 12 +- .../esapi/waf/RestrictContentTypeTest.java | 22 +- .../esapi/waf/RestrictExtensionTest.java | 20 +- .../owasp/esapi/waf/RestrictMethodTest.java | 18 +- .../esapi/waf/RestrictUserAgentTest.java | 26 +- .../org/owasp/esapi/waf/VirtualPatchTest.java | 10 +- .../org/owasp/esapi/waf/WAFFilterTest.java | 26 +- .../java/org/owasp/esapi/waf/WAFTestCase.java | 24 +- .../org/owasp/esapi/waf/WAFTestUtility.java | 34 +-- .../InterceptingHttpServletResponseTest.java | 14 +- 316 files changed, 4190 insertions(+), 4190 deletions(-) diff --git a/README.md b/README.md index 1fac65501..1a7b0c782 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,7 @@ ONLY use GitHub Issues for reporting bugs. # References: Where to Find More Information on ESAPI **OWASP Wiki:** https://owasp.org/www-project-enterprise-security-api/ -**GitHub ESAPI Wiki:** https://github.com/ESAPI/esapi-java-legacy/wiki +**GitHub ESAPI Wiki:** https://github.com/ESAPI/esapi-java-legacy/wiki **General Documentation:** Under the '[documentation](https://github.com/ESAPI/esapi-java-legacy/tree/develop/documentation)' folder. diff --git a/documentation/ESAPI-configuration-user-guide.md b/documentation/ESAPI-configuration-user-guide.md index 72694bb05..420a4fb27 100644 --- a/documentation/ESAPI-configuration-user-guide.md +++ b/documentation/ESAPI-configuration-user-guide.md @@ -41,7 +41,7 @@ until these deprecated methods are removed, but it will be a minumum of 2 years or 1 major release [e.g., 3.x], whichever comes first. Also, we may not necessarily remove all of them at once, depending on community feedback.) -DefaultSecurityConfiguration implements the new contract. New contract methods implementations work as described in +DefaultSecurityConfiguration implements the new contract. New contract methods implementations work as described in 'Multiple configuration files support' paragraph. ## Multiple configuration files support @@ -49,7 +49,7 @@ DefaultSecurityConfiguration implements the new contract. New contract methods i EsapiPropertyManager is the new implementation for getting properties, which uses prioritized property loaders (each one associated with a specific configuration file). This allows to have multiple configuration files existing with priority connected to each one. At this moment, there are two configuration files possible to use, the path to them is set through following Java system properties: - + * org.owasp.esapi.opsteam = (higher priority config) * org.owasp.esapi.devteam = (lower priority config) @@ -86,9 +86,9 @@ ESAPI.securityConfiguration().getBooleanProp("propertyXXX"); where "propertyXXX" is some property name relevant to ESAPI (and in this case, one that would hold a boolean value). See ESAPI.properties for a list of current property names known to ESAPI. - + In above example, following happens: - + 1. org.owasp.esapi.opsteam configuration is used to get propertyXXX and return it as boolean. 2. If (1) fails to find property, org.owasp.esapi.devteam is used to get propertyXXX and return it as boolean. 3. If (2) fails to find property, ESAPI.properties is used to get propertyXXX and return it as boolean. diff --git a/documentation/esapi4java-2.0-readme.txt b/documentation/esapi4java-2.0-readme.txt index 7f568fb06..7fd25e068 100644 --- a/documentation/esapi4java-2.0-readme.txt +++ b/documentation/esapi4java-2.0-readme.txt @@ -7,7 +7,7 @@ Here are the most significant directories and files included the zip file for th File / Directory Description ========================================================================================= -/ +/ | +---configuration/ Directory of ESAPI configuration files | | diff --git a/documentation/esapi4java-2.0rc6-override-log4jloggingfactory.txt b/documentation/esapi4java-2.0rc6-override-log4jloggingfactory.txt index 49accdbfc..35290f5e6 100644 --- a/documentation/esapi4java-2.0rc6-override-log4jloggingfactory.txt +++ b/documentation/esapi4java-2.0rc6-override-log4jloggingfactory.txt @@ -1,4 +1,4 @@ -This release includes critical changes to the ESAPI Log4JLogger that will now allow you to over-ride the user specific +This release includes critical changes to the ESAPI Log4JLogger that will now allow you to over-ride the user specific message using your own User or java.security.Principal implementation. There are a three critical steps that need to be taken to over-ride the ESAPI Log4JLogger: @@ -23,8 +23,8 @@ ESAPI.Logger=com.yourcompany.logging.ExtendedLog4JFactory And you should be all set! -PS: The original ESAPI Log4JLogging class used a secure random number as a replacement to logging the session ID. This allowed -us to tie log messages from the same session together, without exposing the actual session id in the log file. The code looks +PS: The original ESAPI Log4JLogging class used a secure random number as a replacement to logging the session ID. This allowed +us to tie log messages from the same session together, without exposing the actual session id in the log file. The code looks like this, and you may wish to use it in your over-ridden version of getUserInfo. HttpServletRequest request = ESAPI.httpUtilities().getCurrentRequest(); @@ -40,7 +40,7 @@ if ( request != null ) { } } -In fact, here is the entire original getUserInfo() implementation (that was tied to the ESAPI request and user object) – +In fact, here is the entire original getUserInfo() implementation (that was tied to the ESAPI request and user object) – you may wish to emulate some of this. public String getUserInfo() { @@ -58,14 +58,14 @@ public String getUserInfo() { } } } - + // log user information - username:session@ipaddr - User user = ESAPI.authenticator().getCurrentUser(); + User user = ESAPI.authenticator().getCurrentUser(); String userInfo = ""; //TODO - make type logging configurable if ( user != null) { userInfo += user.getAccountName()+ ":" + sid + "@"+ user.getLastHostAddress(); } - + return userInfo; } diff --git a/documentation/esapi4java-core-2.0-readme-crypto-changes.html b/documentation/esapi4java-core-2.0-readme-crypto-changes.html index 8687f5ca6..db403b9c9 100644 --- a/documentation/esapi4java-core-2.0-readme-crypto-changes.html +++ b/documentation/esapi4java-core-2.0-readme-crypto-changes.html @@ -63,7 +63,7 @@

Symmetric Encryption in ESAPI 2.0rc1 and 2.0rc2

always encrypt to the same ciphertext block, thus revealing patterns in the plaintext input. For example, these images from Wikipedia's Block -cipher modes of operation illustrate this point well: +cipher modes of operation illustrate this point well:

@@ -92,7 +92,7 @@

Symmetric Encryption in ESAPI 2.0rc1 and 2.0rc2

Ciphertext encrypted with ECB cipher mode are also subject to "block replay attacks". See Bruce Schneier's Applied Cryptography: protocols, algorithms, and source code for -details. +details.

In both ESAPI 2.0-rc1 and 2.0-rc2, one can choose other block ciphers (e.g. Blowfish) or other key sizes (e.g., 512-bit AES), but @@ -123,7 +123,7 @@

Problems with Symmetric Encryption in ESAPI 2.0-rc1 and 2.0-rc2

The Encryption Changes in ESAPI 2.0-rc3 and Later

Briefly speaking, the changes being implemented for ESAPI Java 2.0 -are: +are:

  1. Starting in ESAPI Java 2.0-rc3, @@ -156,7 +156,7 @@

    The Encryption Changes in ESAPI 2.0-rc3 and Later

    response was deafening. There literally was but a single response and that was to kill off LegacyJavaEncryptor. (By this time, the two symmetric encryption interfaces in Encryptor - had already been deprecated.) + had already been deprecated.)

  2. The byte-encoding has been changed from native byte encoding to UTF-8 byte-encoding throughout ESAPI 2.0 and not just for @@ -167,7 +167,7 @@

    The Encryption Changes in ESAPI 2.0-rc3 and Later

    guaranteed.

The Good, the Bad, and the Ugly

-

Or put another way, there are always trade-offs to be made... +

Or put another way, there are always trade-offs to be made...

The Good

We get improved security by encouraging the use of stronger cipher @@ -205,9 +205,9 @@

The Bad

both to encrypt and decrypt. While it is not required that the IV be kept secret from adversaries, there are some attacks that are possible if the adversary is permitted to alter the IV at will and -observe the results of the ensuing decryption attempt. +observe the results of the ensuing decryption attempt.

-

So that leaves two choices for the IV: +

So that leaves two choices for the IV:

  • Using a fixed IV: @@ -223,7 +223,7 @@

    The Bad

    persisted (e.g., to a database) or transmitted to the recipient this random IV must be stored / made known. Therefore, the raw ciphertext can no longer suffice; whatever random IV that was chosen must be - communicated. + communicated.

Likewise, the use of padding is going to add some overhead to the @@ -360,7 +360,7 @@

The Bad

cipher block size is 128-bits, but more typically, a cipher's block size is 64-bits so the padding would be between 1 to 16 bytes for AES and 1 to 8 bytes for a 64-bit block size cipher and the IV would be -IV would be 16 bytes for AES and 8 bytes for most other ciphers. +IV would be 16 bytes for AES and 8 bytes for most other ciphers.

The Ugly

Well, so far, this "bad" news may be bad for you but @@ -370,7 +370,7 @@

The Ugly

But wait Skippy, don't go running off just quite yet. As Robert Heinlein wrote in his 1966 novel The Moon is a Harsh Mistress "There ain't no such thing as a free lunch". (Some of us -more hardened cynics know it more commonly as TANSTAAFL.) +more hardened cynics know it more commonly as TANSTAAFL.)

As mentioned earlier, backward compatibility with ESAPI 1.4 (originally planned via LegacyJavaEncryptor) has been @@ -395,11 +395,11 @@

The Ugly

complexity of handling the ciphertext result from encryption operations. And then there are new encryption and decryption methods for the Encryptor interface. Specifically, the encrypt -and decrypt methods have been generalized as: +and decrypt methods have been generalized as:

CipherText encrypt(SecretKey key, PlainText plaintext)
         throws EncryptionException;

-and +and

PlainText decrypt(SecretKey key, CipherText ciphertext)
         throws EncryptionException

@@ -409,7 +409,7 @@

The Ugly

based on Encryptor.MasterKey.)

The two existing interfaces from ESAPI 1.4 and earlier:

String encrypt(String plaintext) throws EncryptionException

-and +and

String decrypt(String ciphertext) throws EncryptionException

are still supported but have been deprecated, mainly because diff --git a/documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html b/documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html index d0ecfb2f9..19298d4c2 100644 --- a/documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html +++ b/documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html @@ -353,7 +353,7 @@

ESAPI.properties Properties Relevant to Symmetric Encryption

How the Old (Deprecated) Methods Were Used

To encrypt / decrypt using the String-based, deprecated methods carried over from ESAPI 1.4, code similar to the following would be -used. +used.

    String myplaintext = "My plaintext";
     try {
@@ -411,10 +411,10 @@ 

Encrypting / Decrypting with the New Methods -- The Simple Usage

Using the new encryption / decryption methods is somewhat more complicated, but this is in part because they are more flexible and that flexibility means that more information needs to be communicated -as to the details of the encryption. +as to the details of the encryption.

A code snippet using the new methods that use the master -encryption key would look something like this: +encryption key would look something like this:

    String myplaintext = "My plaintext";
     try {
@@ -432,7 +432,7 @@ 

Encrypting / Decrypting with the New Methods -- The Simple Usage

mode is chosen.

Also, these new methods allow a general byte array to be encrypted, not just a Java String. If one needed to encrypt a byte -array with the old deprecated method, one would first have to use +array with the old deprecated method, one would first have to use

    byte[] plaintextByteArray = { /* byte array to be encrypted */ };
     String plaintext = new String(plaintextByteArray, "UTF-8");

@@ -541,7 +541,7 @@

Encrypting / Decrypting with the New Methods

encrypted bank account numbers are to be sent to one recipient and the encrypted credit card numbers are to be sent to a different recipient. Obviously in such cases, you do not want to share the same -key for both recipients. +key for both recipients.

In ESAPI 1.4 there was not much you can do, but in ESAPI 2.0 and later, there are new encryption / decryption methods that allow you @@ -553,14 +553,14 @@

Encrypting / Decrypting with the New Methods

distributed to the recipients out-of-band. On you could distribute them dynamically via asymmetric encryption assuming that you've previously exchanged public keys with the recipients.)

-

The following illustrates how these new methods might be used. +

The following illustrates how these new methods might be used.

First, we would generate some appropriate secret keys and distribute them securely (e.g., perhaps over SSL/TLS) or exchange them earlier out-of-band to the intended recipients. (E.g., one could put them on two separate thumb drives and use a trusted courier to distribute them to the recipients or one could use PGP-mail or S/MIME -to securely email them, etc.) +to securely email them, etc.)

    // Generate two random, 128-bit AES keys to be distributed out-of-band.
     import javax.crypto.SecretKey;
@@ -587,10 +587,10 @@ 

Encrypting / Decrypting with the New Methods

Second, these keys would be printed out and stored somewhere secure by our application, perhaps using something like ESAPI's EncryptedProperties class, where they could later be -retrieved and used. +retrieved and used.

In the following code, we assume that the SecretKey -values have already been initialized elsewhere. +values have already been initialized elsewhere.

    SecretKey bankAcctKey = ...;        // These might be read from EncryptedProperties
     SecretKey credCardKey = ...;        // or from a restricted database, etc.
diff --git a/documentation/esapi4java-core-2.1-release-notes.txt b/documentation/esapi4java-core-2.1-release-notes.txt
index d84097d80..e97e56c93 100644
--- a/documentation/esapi4java-core-2.1-release-notes.txt
+++ b/documentation/esapi4java-core-2.1-release-notes.txt
@@ -8,7 +8,7 @@ ESAPI for Java - 2.1.0 Release Notes
    deprecated more than 2 years ago and they are known to be insecure
    (they are vulnerable to padding oracle attacks), the ESAPI team has
    decided to remove them in accordance to their support policy.
-   
+
    See comments for issue #306 for further details, as well as additional
    safety precautions that you may wish to take in the unlikely, but possible
    event that this vulnerability resulted in an actual security breach.
@@ -64,5 +64,5 @@ NOTE: A follow-up patch release is scheduled within the next few months to
       based on findings in Google Issue # 306. I will periodically try
       to keep the ESAPI mailing lists updated with the progress so watch
       there for emerging details and anticipated schedule.
-      
+
 -Kevin W. Wall , 2013-08-30
diff --git a/documentation/esapi4java-core-2.2.0.0-release-notes.txt b/documentation/esapi4java-core-2.2.0.0-release-notes.txt
index 8deafbb9d..b43efc743 100644
--- a/documentation/esapi4java-core-2.2.0.0-release-notes.txt
+++ b/documentation/esapi4java-core-2.2.0.0-release-notes.txt
@@ -46,7 +46,7 @@ Issue #			GitHub Issue Title
 37		RandomAccessReferenceMap.update() can randomly corrupt the map
 71		java.lang.ExceptionInInitializerError in 2.0 version
 129		Add Logging support for SLF4J
-157		minimum-config deployment fails 
+157		minimum-config deployment fails
 188		SecurityWrapperRequest seems to mishandle/swallow allowNull argument
 209		Build an encoding function specific to HTTP/Response Splitting (tactical remediation)
 213		Provide a taglib descriptor (.tld file)
@@ -116,7 +116,7 @@ Issue #			GitHub Issue Title
 386		Avoid using System.err in EsapiPropertyManager
 387		'mvn site' fails for FindBugs report, causing 'site' goal to fail
 389		Provide an option for the encodeForLDAP method to not encode wildcard characters
-394		Refactor Validator.getCanonicalizedUri into Encoder.  
+394		Refactor Validator.getCanonicalizedUri into Encoder.
 395		Issues when I am passing htttp://localhost:8080/user=admin&prodversion=no
 396		Trust Boundary Violation - while triggering veracode
 397		Update Resource path search to maintain legacy behavior in DefaultSecurityConfiguration.java
@@ -128,7 +128,7 @@ Issue #			GitHub Issue Title
 417		Add additional protection against CVE-2016-1000031
 422		Inconsistent dependency structure and vulnerable xml (xerces, xalan, xml-apis ...) dependencies
 424		issue with Filename encoding for executeSystemCommand
-425		Project build error: Non-resolvable parent POM for org.owasp.esapi:esapi:2.1.0.2-SNAPSHOT: Could not transfer artifact 
+425		Project build error: Non-resolvable parent POM for org.owasp.esapi:esapi:2.1.0.2-SNAPSHOT: Could not transfer artifact
 427		HTTP cookie validation rules too restrictive?
 429		Miscellaneous updates to pom.xml
 432		ESAPI.properties not found.
@@ -140,7 +140,7 @@ Issue #			GitHub Issue Title
 442		Remove deprecated fields in Encoder interface
 444		Delete deprecated method Base64.decodeToObject() and related methods
 445		A bunch of dependencies are out of date , I will list them below with the associated vulnerability
-447		can't generate MasterKey / MasterSalt 
+447		can't generate MasterKey / MasterSalt
 448		Clean up pom.xml
 454		about code eclipse formatter template question
 455		New release for mitigation of CVEs
@@ -194,7 +194,7 @@ Issue #			GitHub Issue Title
 
     Issue 483     More miscellaneous prep work for ESAPI 2.2.0.0 release
         Specifically, CipherText.getSerialVersionUID() and DefaultSecurityConfiguration.MAX_FILE_NAME_LENGTH have actually been deleted from the ESAPI code base. For the former, use CipherText.cipherTextVersion() instead. For the latter, there is no replacement. (This wasn't being used, but it was set to 1000 in case you're wondering.)
-        
+
 * Various properties in ESAPI.properties were changed in a way that might affect your application:
     Issue 439		Tighten ESAPI defaults to disallow dubious file suffixes
 
@@ -220,10 +220,10 @@ Issue #			GitHub Issue Title
                                                     Validator.HTTPQueryString=^([a-zA-Z0-9_\\-]{1,32}=[\\p{L}\\p{N}.\\-/+=_ !$*?@%]*&?)*$
                                                 (Left as an exercise for the reader to figure out what exactly this means. ;-)
             Validator.HTTPURI:              Changed to be much more restrictive; i.e., changed from:
-                                                    Validator.HTTPURI=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$ 
+                                                    Validator.HTTPURI=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$
                                                 to:
                                                     Validator.HTTPURI=^/([a-zA-Z0-9.\\-_]*/?)*$
-            
+
 * Other changes:
     Issue 500		Suppress noise from ESAPI searching for properties and stop ignoring important IOExceptions
 
@@ -241,7 +241,7 @@ Issue #			GitHub Issue Title
 
         Other changes in this release, some of which not tracked via GitHub issues
 
-* Updated minimal version of Maven from 3.0 to 3.1 required to build ESAPI. 
+* Updated minimal version of Maven from 3.0 to 3.1 required to build ESAPI.
 * Miscellaneous minor javadoc fixes and updates.
 * Added the Maven plug-in for OWASP Dependency Check so 3rd party dependencies can be kept up-to-date.
 * Updated .gitignore file with additional files to be ignored.
diff --git a/documentation/esapi4java-core-2.2.1.0-release-notes.txt b/documentation/esapi4java-core-2.2.1.0-release-notes.txt
index 6119a5c4c..e32e0ad8c 100644
--- a/documentation/esapi4java-core-2.2.1.0-release-notes.txt
+++ b/documentation/esapi4java-core-2.2.1.0-release-notes.txt
@@ -80,7 +80,7 @@ Issue #         GitHub Issue Title
 The new default ESAPI logger is JUL (java.util.logging packages) and we have deprecated the use of Log4J 1.x because we now support SLF4J and Log4J 1.x is way past its end-of-life. We did not want to make SLF4J the default logger (at least not yet) as we did not want to have the default ESAPI use require additional dependencies. However, SLF4J is likely to be the future choice, at least once we start on ESAPI 3.0. A special shout-out to Jeremiah Stacey for making this possible by re-factoring much of the ESAPI logger code. Note, the straw that broke the proverbial camel's back was the announcement of CVE-2019-17571 (rated Critical), for which there is no fix available and likely will never be.
 
 Related to that CVE and how it affects ESAPI, be sure to read
-   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf 
+   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf
 which describes CVE-2019-17571, a deserialization vulnerability in Log4J 1.2.17. ESAPI is not affected by this (even if you chose to use Log4J 1 as you default ESAPI logger). This security bulletin describes why this CVE is not exploitable as used by ESAPI.
 
 Notable dependency updates (excludes those only used with JUnit tests):
@@ -204,21 +204,21 @@ PR#    GitHub ID                Description
 506 -- kwwall           -- Closes Issue 245
 508 -- Michael-Ziluck   -- Resolves #226 - Corrected docs for the bounded, numeric, random methods
 510 -- Michael-Ziluck   -- Resolve #509 - Properly throw exception when HTML fails
-513 -- kwwall           -- Close issue #512 by updating to 1.9.4 of Commons Beans Util. 
-514 -- xeno6696         -- Fixed issues #503 by writing a new addReferer method, also temporarily… 
-516 -- jeremiahjstacey  -- Issue 515 
-518 -- jeremiahjstacey  -- Issue #511 Copying Docs from DefaultValidator 
-519 -- jeremiahjstacey  -- Issue 494 CSSCodec RGB Triplets 
-520 -- jeremiahjstacey  -- OS Name DefaultExecutorTests #143 
-533 -- jeremiahjstacey  -- #532 JUL and Log4J match SLF4J class structure and Workflow 
-535 -- kwwall           -- Issue 521 
-537 -- jeremiahjstacey  -- Issue 536 
-539 -- wiiitek          -- upgrade for convergence 
-540 -- wiiitek          -- Issue 382: Build Fails on path with space 
-541 -- HJW8472          -- Fixed issue #310 
-543 -- sempf            -- Release notes for 2.2.1.0 
-551 -- kwwall           -- Misc cleanup 
-553 -- kwwall           -- Fix for GitHub Issue 552 
+513 -- kwwall           -- Close issue #512 by updating to 1.9.4 of Commons Beans Util.
+514 -- xeno6696         -- Fixed issues #503 by writing a new addReferer method, also temporarily…
+516 -- jeremiahjstacey  -- Issue 515
+518 -- jeremiahjstacey  -- Issue #511 Copying Docs from DefaultValidator
+519 -- jeremiahjstacey  -- Issue 494 CSSCodec RGB Triplets
+520 -- jeremiahjstacey  -- OS Name DefaultExecutorTests #143
+533 -- jeremiahjstacey  -- #532 JUL and Log4J match SLF4J class structure and Workflow
+535 -- kwwall           -- Issue 521
+537 -- jeremiahjstacey  -- Issue 536
+539 -- wiiitek          -- upgrade for convergence
+540 -- wiiitek          -- Issue 382: Build Fails on path with space
+541 -- HJW8472          -- Fixed issue #310
+543 -- sempf            -- Release notes for 2.2.1.0
+551 -- kwwall           -- Misc cleanup
+553 -- kwwall           -- Fix for GitHub Issue 552
 557 -- kwwall           -- Final prep for 2.2.1.0 release
 
 
@@ -234,11 +234,11 @@ Direct and Transitive Runtime and Test Dependencies:
 
         $ mvn dependency:tree
         [INFO] Scanning for projects...
-        [INFO] 
+        [INFO]
         [INFO] -----------------------< org.owasp.esapi:esapi >------------------------
         [INFO] Building ESAPI 2.2.1.0
         [INFO] --------------------------------[ jar ]---------------------------------
-        [INFO] 
+        [INFO]
         [INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ esapi ---
         [INFO] org.owasp.esapi:esapi:jar:2.2.1.0
         [INFO] +- javax.servlet:javax.servlet-api:jar:3.0.1:provided
@@ -271,9 +271,9 @@ Direct and Transitive Runtime and Test Dependencies:
         [INFO] |  \- xalan:serializer:jar:2.7.2:compile
         [INFO] +- xerces:xercesImpl:jar:2.12.0:compile
         [INFO] +- xml-apis:xml-apis:jar:1.4.01:compile
-        [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.0.4:compile (optional) 
-        [INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.2:compile (optional) 
-        [INFO] +- net.jcip:jcip-annotations:jar:1.0:compile (optional) 
+        [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.0.4:compile (optional)
+        [INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.2:compile (optional)
+        [INFO] +- net.jcip:jcip-annotations:jar:1.0:compile (optional)
         [INFO] +- junit:junit:jar:4.13:test
         [INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
         [INFO] +- org.bouncycastle:bcprov-jdk15on:jar:1.65.01:test
diff --git a/documentation/esapi4java-core-2.2.1.1-release-notes.txt b/documentation/esapi4java-core-2.2.1.1-release-notes.txt
index 7fa3ffc35..4670706f7 100644
--- a/documentation/esapi4java-core-2.2.1.1-release-notes.txt
+++ b/documentation/esapi4java-core-2.2.1.1-release-notes.txt
@@ -79,7 +79,7 @@ See GitHub issue #560 for additional details.
 
 
 Related to that aforemented Log4J 1.x CVE and how it affects ESAPI, be sure to read
-   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf 
+   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf
 which describes CVE-2019-17571, a deserialization vulnerability in Log4J 1.2.17. ESAPI is *NOT* affected by this (even if you chose to use Log4J 1 as you default ESAPI logger). This security bulletin describes why this CVE is not exploitable as used by ESAPI.
 
 
@@ -150,7 +150,7 @@ kwwall          67             64               8
 PR#    GitHub ID                Description
 ----------------------------------------------------------------------
 559 -- synk-bot         -- Upgrade com.github.spotbugs:spotbugs-annotations from 4.0.4 to 4.0.5
-562 -- jeremiahjstacey  -- Issue #560 JUL fixes 
+562 -- jeremiahjstacey  -- Issue #560 JUL fixes
 
 CHANGELOG:      Create your own. May I suggest:
 
@@ -164,11 +164,11 @@ Direct and Transitive Runtime and Test Dependencies:
 
         $ mvn dependency:tree
         [INFO] Scanning for projects...
-        [INFO] 
+        [INFO]
         [INFO] -----------------------< org.owasp.esapi:esapi >------------------------
         [INFO] Building ESAPI 2.2.1.1
         [INFO] --------------------------------[ jar ]---------------------------------
-        [INFO] 
+        [INFO]
         [INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ esapi ---
         [INFO] org.owasp.esapi:esapi:jar:2.2.1.1
         [INFO] +- javax.servlet:javax.servlet-api:jar:3.0.1:provided
@@ -201,9 +201,9 @@ Direct and Transitive Runtime and Test Dependencies:
         [INFO] |  \- xalan:serializer:jar:2.7.2:compile
         [INFO] +- xerces:xercesImpl:jar:2.12.0:compile
         [INFO] +- xml-apis:xml-apis:jar:1.4.01:compile
-        [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.0.5:compile (optional) 
-        [INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.2:compile (optional) 
-        [INFO] +- net.jcip:jcip-annotations:jar:1.0:compile (optional) 
+        [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.0.5:compile (optional)
+        [INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.2:compile (optional)
+        [INFO] +- net.jcip:jcip-annotations:jar:1.0:compile (optional)
         [INFO] +- junit:junit:jar:4.13:test
         [INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
         [INFO] +- org.bouncycastle:bcprov-jdk15on:jar:1.65.01:test
diff --git a/documentation/esapi4java-core-2.2.2.0-release-notes.txt b/documentation/esapi4java-core-2.2.2.0-release-notes.txt
index 4920a296f..833d1b94e 100644
--- a/documentation/esapi4java-core-2.2.2.0-release-notes.txt
+++ b/documentation/esapi4java-core-2.2.2.0-release-notes.txt
@@ -13,7 +13,7 @@ Executive Summary: Important Things to Note for this Release
 This is a patch release with the primary intent of updating some dependencies with known vulnerabilities.  The main vulnerability that was remediated was CVE-2020-13956, which was a vulnerability introduced through the ESAPI transitive dependency org.apache.httpcomponents:httpclient:4.5.12, potentially exposed through org.owasp.antisamy:antisamy:1.5.10. Updating to AntiSamy 1.5.11 remediated that issue.  In addition, that update to AntiSamy 1.5.11 also addressed AntiSamy issue #48 (https://github.com/nahsra/antisamy/issues/48), which was a low risk security issue that potentially could be exposed via phishing.
 
 For those of you using a Software Configuration Analysis (SCA) services such as Snyk, BlackDuck, Veracode SourceClear, OWASP Dependency Check, etc., you might notice that there is vulnerability in xerces:xercesImpl:2.12.0 that ESAPI uses (also a transitive dependency) that is similar to CVE-2020-14621. Unfortunately there is no official patch for this in the regular Maven Central repository. Further details are described in Security Bulletin #3, which is viewable here
-   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin3.pdf 
+   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin3.pdf
 and associated with this release on GitHub. Manual workarounds possible. See the security bulletin for further details.
 
 
@@ -91,7 +91,7 @@ See GitHub issue #560 for additional details.
 
 
 Related to that aforemented Log4J 1.x CVE and how it affects ESAPI, be sure to read
-   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf 
+   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf
 which describes CVE-2019-17571, a deserialization vulnerability in Log4J 1.2.17. ESAPI is *NOT* affected by this (even if you chose to use Log4J 1 as you default ESAPI logger). This security bulletin describes why this CVE is not exploitable as used by ESAPI.
 
 
@@ -132,9 +132,9 @@ We do not know the reason for these failures, but only that we have observed the
 
 
 Lastly, some SCA services may continue to flag vulnerabilties in ESAPI 2.2.2.0 related to log4j 1.2.17 and xerces 2.12.0.  We do not believe the way that ESAPI uses either of these in a manner that leads to any exploitable behavior.  See the security bulletins
-   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf 
+   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf
 and
-   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin3.pdf 
+   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin3.pdf
 respectively, for additional details.
 
 -----------------------------------------------------------------------------
@@ -175,11 +175,11 @@ Direct and Transitive Runtime and Test Dependencies:
 
         $ mvn dependency:tree
         [INFO] Scanning for projects...
-        [INFO] 
+        [INFO]
         [INFO] -----------------------< org.owasp.esapi:esapi >------------------------
         [INFO] Building ESAPI 2.2.2.0
         [INFO] --------------------------------[ jar ]---------------------------------
-        [INFO] 
+        [INFO]
         [INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ esapi ---
         [INFO] org.owasp.esapi:esapi:jar:2.2.2.0-SNAPSHOT
         [INFO] +- javax.servlet:javax.servlet-api:jar:3.0.1:provided
@@ -212,9 +212,9 @@ Direct and Transitive Runtime and Test Dependencies:
         [INFO] |  \- xalan:serializer:jar:2.7.2:compile
         [INFO] +- xerces:xercesImpl:jar:2.12.0:compile
         [INFO] +- xml-apis:xml-apis:jar:1.4.01:compile
-        [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.1.4:compile (optional) 
-        [INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.2:compile (optional) 
-        [INFO] +- net.jcip:jcip-annotations:jar:1.0:compile (optional) 
+        [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.1.4:compile (optional)
+        [INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.2:compile (optional)
+        [INFO] +- net.jcip:jcip-annotations:jar:1.0:compile (optional)
         [INFO] +- junit:junit:jar:4.13.1:test
         [INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
         [INFO] +- org.bouncycastle:bcprov-jdk15on:jar:1.65.01:test
diff --git a/documentation/esapi4java-core-2.2.3.0-release-notes.txt b/documentation/esapi4java-core-2.2.3.0-release-notes.txt
index df95a77fd..1b96a6657 100644
--- a/documentation/esapi4java-core-2.2.3.0-release-notes.txt
+++ b/documentation/esapi4java-core-2.2.3.0-release-notes.txt
@@ -16,7 +16,7 @@ This is a patch release with the primary intent of updating some dependencies, s
         -- AntiSamy, from 1.5.11 to 1.6.2.
         -- As a result of the AntiSamy upgrade, the transitive dependency xercesImpl was updated from 2.12.0 to 2.12.1 which should address CVE-2020-14338.
         -- Apache batik-css, updated from 1.13 to 1.14.
-        
+
 Details follow.
 
     * IMPORTANT: Effects of updating to AntiSamy 1.6.2
@@ -30,7 +30,7 @@ Details follow.
                         
                   in your dependency for ESAPI in your application's pom.xml. (You Gradle, Ivy, etc. other build tool users will have to figure out how to do this yourself.)
                   This is especially important if you are using SLF4J logging in ESAPI with some other SLF4J logger such as slf4j-log4j2, etc. If you don't do that, your logging may not come out as expected. See , under its section discussing Logging for more details.
-        
+
                 o Previously, ESAPI shipped with a default AntiSamy policy file called 'antisamy-esapi.xml'. For 10 plus years, unbeknownst to anyone, that file contained an unused '' node that not only did ESAPI not directly used, but was also completely ignored by AntiSamy! However, starting with AntiSamy 1.6.0, AntiSamy does XML schema validation by default, so that causes any non-compliant AntiSamy policy file to be rejected. This may result in some rather obtuse error messages and you may want to set the AntiSamy system property 'owasp.validator.validateschema' to "false" temporarily until you have time to correct your AntiSamy policy file(s).
 
     Old News
@@ -72,7 +72,7 @@ Issue #         GitHub Issue Title
 602             Update failing ValidatorTest in 'Java CI with Maven' GitHub workflow
 606             Vulnerability in transitive dependency of esapi
 609             Change log4j dependency scope to provided Build-Maven Component-Docs Component-Logger Configuration
-614             Potentlial XXE Injection vulnerability in loading XML version of ESAPI properties file 
+614             Potentlial XXE Injection vulnerability in loading XML version of ESAPI properties file
 
 -----------------------------------------------------------------------------
 
@@ -125,7 +125,7 @@ See GitHub issue #560 for additional details.
 
 
 Related to that aforemented Log4J 1.x CVE and how it affects ESAPI, be sure to read
-   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf 
+   https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/ESAPI-security-bulletin2.pdf
 which describes CVE-2019-17571, a deserialization vulnerability in Log4J 1.2.17. ESAPI is *NOT* affected by this (even if you chose to use Log4J 1 as you default ESAPI logger). This security bulletin describes why this CVE is not exploitable as used by ESAPI.
 
 
@@ -211,11 +211,11 @@ Direct and Transitive Runtime and Test Dependencies:
 
         $ mvn -B dependency:tree
         [INFO] Scanning for projects...
-        [INFO] 
+        [INFO]
         [INFO] -----------------------< org.owasp.esapi:esapi >------------------------
         [INFO] Building ESAPI 2.2.3.0-SNAPSHOT
         [INFO] --------------------------------[ jar ]---------------------------------
-        [INFO] 
+        [INFO]
         [INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ esapi ---
         [INFO] org.owasp.esapi:esapi:jar:2.2.3.0-SNAPSHOT
         [INFO] +- javax.servlet:javax.servlet-api:jar:3.0.1:provided
@@ -249,9 +249,9 @@ Direct and Transitive Runtime and Test Dependencies:
         [INFO] +- xalan:xalan:jar:2.7.2:compile
         [INFO] |  \- xalan:serializer:jar:2.7.2:compile
         [INFO] +- xml-apis:xml-apis:jar:1.4.01:compile
-        [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.2.0:compile (optional) 
-        [INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.2:compile (optional) 
-        [INFO] +- net.jcip:jcip-annotations:jar:1.0:compile (optional) 
+        [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.2.0:compile (optional)
+        [INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.2:compile (optional)
+        [INFO] +- net.jcip:jcip-annotations:jar:1.0:compile (optional)
         [INFO] +- junit:junit:jar:4.13.1:test
         [INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
         [INFO] +- org.bouncycastle:bcprov-jdk15on:jar:1.68:test
diff --git a/documentation/esapi4java-core-2.2.3.1-release-notes.txt b/documentation/esapi4java-core-2.2.3.1-release-notes.txt
index b76e9c695..f53aa8360 100644
--- a/documentation/esapi4java-core-2.2.3.1-release-notes.txt
+++ b/documentation/esapi4java-core-2.2.3.1-release-notes.txt
@@ -43,7 +43,7 @@ Issue #         GitHub Issue Title
         Changes Requiring Special Attention
 
 -----------------------------------------------------------------------------
-See this section from the previous release notes at: 
+See this section from the previous release notes at:
     https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.2.3.0-release-notes.txt
 
 -----------------------------------------------------------------------------
@@ -51,12 +51,12 @@ See this section from the previous release notes at:
         Remaining Known Issues / Problems
 
 -----------------------------------------------------------------------------
-See this section from the previous release notes at: 
+See this section from the previous release notes at:
     https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.2.3.0-release-notes.txt
 
 NEW since last release (ESAPI 2.2.3.0) - CVE-2021-29425
     https://nvd.nist.gov/vuln/detail/CVE-2021-29425
-    
+
 
 -----------------------------------------------------------------------------
 
@@ -93,11 +93,11 @@ Direct and Transitive Runtime and Test Dependencies:
 
         $ mvn dependency:tree
         [INFO] Scanning for projects...
-        [INFO] 
+        [INFO]
         [INFO] -----------------------< org.owasp.esapi:esapi >------------------------
         [INFO] Building ESAPI 2.2.3.1-SNAPSHOT
         [INFO] --------------------------------[ jar ]---------------------------------
-        [INFO] 
+        [INFO]
         [INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ esapi ---
         [INFO] org.owasp.esapi:esapi:jar:2.2.3.1-SNAPSHOT
         [INFO] +- javax.servlet:javax.servlet-api:jar:3.0.1:provided
@@ -128,8 +128,8 @@ Direct and Transitive Runtime and Test Dependencies:
         [INFO] +- org.slf4j:slf4j-api:jar:1.7.30:compile
         [INFO] +- xml-apis:xml-apis:jar:1.4.01:compile
         [INFO] +- commons-io:commons-io:jar:2.6:compile
-        [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.2.2:compile (optional) 
-        [INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.2:compile (optional) 
+        [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.2.2:compile (optional)
+        [INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.2:compile (optional)
         [INFO] +- commons-codec:commons-codec:jar:1.15:test
         [INFO] +- junit:junit:jar:4.13.2:test
         [INFO] +- org.bouncycastle:bcprov-jdk15on:jar:1.68:test
diff --git a/documentation/esapi4java-core-2.3.0.0-release-notes.txt b/documentation/esapi4java-core-2.3.0.0-release-notes.txt
index b21fafd7f..e4cdefb1d 100644
--- a/documentation/esapi4java-core-2.3.0.0-release-notes.txt
+++ b/documentation/esapi4java-core-2.3.0.0-release-notes.txt
@@ -39,7 +39,7 @@ ESAPI 2.3.0.0 release (current / new release):
 
 Issue #         GitHub Issue Title
 ----------------------------------------------------------------------------------------------
-163             Limit max size of entire cookies Component-Validator enhancement good first issue help wanted imported Priority-High 
+163             Limit max size of entire cookies Component-Validator enhancement good first issue help wanted imported Priority-High
 198             Uninitialized esapi logging assumes logging to System.out/System.err - Make configurable/extensible bug imported wontfix
 324             ClassCastException during web application redeploy due to the grift logging classes enhancement imported
 564             Create release notes for 2.2.1.1 patch release Component-Docs
@@ -70,7 +70,7 @@ Issue #         GitHub Issue Title
 
 -----------------------------------------------------------------------------
 
-1) This likely will be the LAST ESAPI release supporting Java 7. There are just some vulnerabilities (notably a DoS one in Neko HtmlUnit that was assigned CVE-2022-28366 after the ESAPI 2.3.0.0 release) that because they are transitive dependencies, that we simply cannot remediate without at least moving on to Java 8 as the minimally supported JDK. Please plan accordingly.  
+1) This likely will be the LAST ESAPI release supporting Java 7. There are just some vulnerabilities (notably a DoS one in Neko HtmlUnit that was assigned CVE-2022-28366 after the ESAPI 2.3.0.0 release) that because they are transitive dependencies, that we simply cannot remediate without at least moving on to Java 8 as the minimally supported JDK. Please plan accordingly.
 
 2) If you are not upgrading to ESAPI release 2.3.0.0 from 2.2.3.1 (the previous release), then you NEED to read at least the release notes in 2.2.3.1 and ideally, all the ones in all the previous ESAPI release notes from where you are updating to 2.3.0.0. In particular, if you were using ESAPI 2.2.1.0 or earlier, you need to see those ESAPI release notes in regards to changes in the ESAPI.Logger property.
 
diff --git a/documentation/esapi4java-core-2.4.0.0-release-notes.txt b/documentation/esapi4java-core-2.4.0.0-release-notes.txt
index c5bf51173..bfc50362d 100644
--- a/documentation/esapi4java-core-2.4.0.0-release-notes.txt
+++ b/documentation/esapi4java-core-2.4.0.0-release-notes.txt
@@ -13,7 +13,7 @@ Do NOT:  Do NOT use GitHub Issues to ask questions about this of future releases
 
 Executive Summary: Important Things to Note for this Release
 ------------------------------------------------------------
-This is a very important ESAPI release as it is the first release to be FULLY INCOMPATIBLE WITH JAVA 1.7!  This was expedited in response to some dependencies to resolve prior CVEs (see release notes in 2.3.0.0) that could not be updated as those versions required a JDK > 1.7 which we were forced to.  The slightly premature update to Java 1.8 is done to address CVE-2022-28366 that had to be fixed with a version of the transitive depenedency via AntiSamy of NekoHTML that was Java 1.8+ only.  (Wrapped into issue #682)  It is important to note that the solution to fix CVE-2022-28366 does not exist in ESAPI 2.3.0.0 and there is no intention to fix it for Java 1.7.    
+This is a very important ESAPI release as it is the first release to be FULLY INCOMPATIBLE WITH JAVA 1.7!  This was expedited in response to some dependencies to resolve prior CVEs (see release notes in 2.3.0.0) that could not be updated as those versions required a JDK > 1.7 which we were forced to.  The slightly premature update to Java 1.8 is done to address CVE-2022-28366 that had to be fixed with a version of the transitive depenedency via AntiSamy of NekoHTML that was Java 1.8+ only.  (Wrapped into issue #682)  It is important to note that the solution to fix CVE-2022-28366 does not exist in ESAPI 2.3.0.0 and there is no intention to fix it for Java 1.7.
 
 =================================================================================================================
 
@@ -33,10 +33,10 @@ ESAPI 2.4.0.0 release (current / new release):
 
 Issue #         GitHub Issue Title
 ----------------------------------------------------------------------------------------------
-644             Do not include a logging implementation as a dependency slf4j-simple 
+644             Do not include a logging implementation as a dependency slf4j-simple
 672             (wontfix) HTMLEntityCodec Bug Decoding "Left Angular Bracket" Symbol
 679             Completely remove support for fixed IVs and throw a ConfigurationException if encountered.
-682             Update baseline to Java 1.8 
+682             Update baseline to Java 1.8
 
 -----------------------------------------------------------------------------
 
@@ -44,21 +44,21 @@ Issue #         GitHub Issue Title
 
 -----------------------------------------------------------------------------
 
-1) This is the first ESAPI release that does not support Java 1.7.  This library will no longer work if your application is that old.  
+1) This is the first ESAPI release that does not support Java 1.7.  This library will no longer work if your application is that old.
 
                                         !!!!! VULNERABILITY ALERTS !!!!!
 
-2) This release fixes the known vulnerability ESAPI 2.3.0.0 that had to wait until we supported Java 8 to be patched. The patch was in Neko-HtmlUntil and was fixed in version 2.27, which required Java 8 or later. It was a transitive dependency via AntiSamy and we picked it up by updating to AntiSamy 1.6.8.  This was a DoS vulnerability discovered in HtmlUnit-Neko affecting all versions up to 2.26.  Full details from MITRE are here:  https://cve.mitre.org/cgi-bin/cvename.cgi?name=2022-28366  
+2) This release fixes the known vulnerability ESAPI 2.3.0.0 that had to wait until we supported Java 8 to be patched. The patch was in Neko-HtmlUntil and was fixed in version 2.27, which required Java 8 or later. It was a transitive dependency via AntiSamy and we picked it up by updating to AntiSamy 1.6.8.  This was a DoS vulnerability discovered in HtmlUnit-Neko affecting all versions up to 2.26.  Full details from MITRE are here:  https://cve.mitre.org/cgi-bin/cvename.cgi?name=2022-28366
 
-3) This release also patches the (known, but forgotten?) XSS vulnerability ESAPI 2.3.0.0 in AntiSamy 1.6.7 but was fixed in 1.6.8.  (The 2.3.0.0 release notes have been updated to mention this.) Full details from MITRE are here:  https://cve.mitre.org/cgi-bin/cvename.cgi?name=2022-29577  
+3) This release also patches the (known, but forgotten?) XSS vulnerability ESAPI 2.3.0.0 in AntiSamy 1.6.7 but was fixed in 1.6.8.  (The 2.3.0.0 release notes have been updated to mention this.) Full details from MITRE are here:  https://cve.mitre.org/cgi-bin/cvename.cgi?name=2022-29577
 
 -----------------------------------------------------------------------------
 
 Developer Activity Report (Changes between release 2.3.0.0 and 2.4.0.0, i.e., between 2022-04-17 and 2022-04-24)
 
 Special thanks to Dave Wichers and Sebastian Pessaro from AntiSamy for their work to provide version 1.6.8 which patched 2 CVEs.
-Special thanks to Jeremiah J. Stacey for his work to update and prep the library to support java 1.8.  (He literally created the PR the day after 2.3.0.0's release.)  
-Special thanks to Kevin Wall for support in pushing out this release.  
+Special thanks to Jeremiah J. Stacey for his work to update and prep the library to support java 1.8.  (He literally created the PR the day after 2.3.0.0's release.)
+Special thanks to Kevin Wall for support in pushing out this release.
 
 
 -----------------------------------------------------------------------------
diff --git a/scripts/esapi4java-core-TEMPLATE-release-notes.txt b/scripts/esapi4java-core-TEMPLATE-release-notes.txt
index 1d7c8c460..0decbe0e7 100644
--- a/scripts/esapi4java-core-TEMPLATE-release-notes.txt
+++ b/scripts/esapi4java-core-TEMPLATE-release-notes.txt
@@ -91,9 +91,9 @@ None known, other than the remaining open issues on GitHub.
 Developer Activity Report (Changes between release ${PREV_VERSION} and ${VERSION}, i.e., between ${PREV_RELEASE_DATE} and ${YYYY_MM_DD_RELEASE_DATE})
 Generated manually (this time) -- all errors are the fault of kwwall and his inability to do simple arithmetic.
 
-@@@@ 
+@@@@
 @@@@ This section needs to be manually updated.
-@@@@ 
+@@@@
 Developer       Total       Total Number        # Merged
 (GitHub ID)     commits   of Files Changed        PRs
 ========================================================
diff --git a/src/examples/java/ESAPILogging.java b/src/examples/java/ESAPILogging.java
index b085c66d2..e2b1fc85c 100644
--- a/src/examples/java/ESAPILogging.java
+++ b/src/examples/java/ESAPILogging.java
@@ -11,7 +11,7 @@ public static void main(String[] args) {
 
         try {
             Logger logger = ESAPI.getLogger("ESAPILogging");
-            
+
             logger.warning(Logger.SECURITY_FAILURE, "This is a warning.");
             logger.always(Logger.SECURITY_AUDIT, "This is an audit log. It always logs.");
         } catch(Throwable t) {
diff --git a/src/examples/java/PersistedEncryptedData.java b/src/examples/java/PersistedEncryptedData.java
index 06a0512eb..1cabc04bb 100644
--- a/src/examples/java/PersistedEncryptedData.java
+++ b/src/examples/java/PersistedEncryptedData.java
@@ -71,7 +71,7 @@ public static int persistEncryptedData(PlainText plaintext,
         fos.close();
         return serializedBytes.length;
     }
- 
+
     /** Read the specified file name containing encoded encrypted data,
      *  and then decode it and decrypt it to retrieve the original plaintext.
      *
diff --git a/src/main/java/org/owasp/esapi/AccessController.java b/src/main/java/org/owasp/esapi/AccessController.java
index 2aa8e84e0..ad23d14c7 100644
--- a/src/main/java/org/owasp/esapi/AccessController.java
+++ b/src/main/java/org/owasp/esapi/AccessController.java
@@ -1,15 +1,15 @@
 /**
  * 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-2019 - 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
  */
@@ -26,18 +26,18 @@
  * The implementation of this interface will need to access the current User object (from Authenticator.getCurrentUser())
  * to determine roles or permissions. In addition, the implementation
  * will also need information about the resources that are being accessed. Using the user information and the resource
- * information, the implementation should return an access control decision. 
+ * information, the implementation should return an access control decision.
  * 

- * Implementers are encouraged to implement the ESAPI access control rules, like assertAuthorizedForFunction() using - * existing access control mechanisms, such as methods like isUserInRole() or hasPrivilege(). While powerful, - * methods like isUserInRole() can be confusing for developers, as users may be in multiple roles or possess multiple - * overlapping privileges. Direct use of these finer grained access control methods encourages the use of complex boolean + * Implementers are encouraged to implement the ESAPI access control rules, like assertAuthorizedForFunction() using + * existing access control mechanisms, such as methods like isUserInRole() or hasPrivilege(). While powerful, + * methods like isUserInRole() can be confusing for developers, as users may be in multiple roles or possess multiple + * overlapping privileges. Direct use of these finer grained access control methods encourages the use of complex boolean * tests throughout the code, which can easily lead to developer mistakes. *

- * The point of the ESAPI access control interface is to centralize access control logic behind easy to use calls like - * assertAuthorized() so that access control is easy to use and easy to verify. Here is an example of a very - * straightforward to implement, understand, and verify ESAPI access control check: - * + * The point of the ESAPI access control interface is to centralize access control logic behind easy to use calls like + * assertAuthorized() so that access control is easy to use and easy to verify. Here is an example of a very + * straightforward to implement, understand, and verify ESAPI access control check: + * *

  * try {
  *     ESAPI.accessController().assertAuthorized("businessFunction", runtimeData);
@@ -46,13 +46,13 @@
  * ... attack in progress
  * }
  * 
- * + * * Note that in the user interface layer, access control checks can be used to control whether particular controls are * rendered or not. These checks are supposed to fail when an unauthorized user is logged in, and do not represent * attacks. Remember that regardless of how the user interface appears, an attacker can attempt to invoke any business * function or access any data in your application. Therefore, access control checks in the user interface should be * repeated in both the business logic and data layers. - * + * *
  * <% if ( ESAPI.accessController().isAuthorized( "businessFunction", runtimeData ) ) { %>
  * <a href="/doAdminFunction">ADMIN</a>
@@ -60,104 +60,104 @@
  * <a href="/doNormalFunction">NORMAL</a>
  * <% } %>
  * 
- * + * * @author Mike H. Fauzy (mike.fauzy@aspectsecurity.com) ESAPI v1.6- * @author Jeff Williams (jeff.williams@aspectsecurity.com) ESAPI v0-1.5 */ public interface AccessController { /** - * isAuthorized executes the AccessControlRule - * that is identified by key and listed in the - * resources/ESAPI-AccessControlPolicy.xml file. It returns - * true if the AccessControlRule decides that the operation - * should be allowed. Otherwise, it returns false. Any exception thrown by - * the AccessControlRule must result in false. If - * key does not map to an AccessControlRule, then - * false is returned. - * - * Developers should call isAuthorized to control execution flow. For - * example, if you want to decide whether to display a UI widget in the + * isAuthorized executes the AccessControlRule + * that is identified by key and listed in the + * resources/ESAPI-AccessControlPolicy.xml file. It returns + * true if the AccessControlRule decides that the operation + * should be allowed. Otherwise, it returns false. Any exception thrown by + * the AccessControlRule must result in false. If + * key does not map to an AccessControlRule, then + * false is returned. + * + * Developers should call isAuthorized to control execution flow. For + * example, if you want to decide whether to display a UI widget in the * browser using the same logic that you will use to enforce permissions * on the server, then isAuthorized is the method that you want to use. - * - * Typically, assertAuthorized should be used to enforce permissions on the + * + * Typically, assertAuthorized should be used to enforce permissions on the * server. - * - * @param key key maps to + * + * @param key key maps to * <AccessControlPolicy><AccessControlRules> * <AccessControlRule name="key" - * @param runtimeParameter runtimeParameter can contain anything that - * the AccessControlRule needs from the runtime system. - * @return Returns true if and only if the AccessControlRule specified - * by key exists and returned true. - * Otherwise returns false + * @param runtimeParameter runtimeParameter can contain anything that + * the AccessControlRule needs from the runtime system. + * @return Returns true if and only if the AccessControlRule specified + * by key exists and returned true. + * Otherwise returns false */ boolean isAuthorized(Object key, Object runtimeParameter); - + /** - * assertAuthorized executes the AccessControlRule - * that is identified by key and listed in the - * resources/ESAPI-AccessControlPolicy.xml file. It does - * nothing if the AccessControlRule decides that the operation - * should be allowed. Otherwise, it throws an + * assertAuthorized executes the AccessControlRule + * that is identified by key and listed in the + * resources/ESAPI-AccessControlPolicy.xml file. It does + * nothing if the AccessControlRule decides that the operation + * should be allowed. Otherwise, it throws an * org.owasp.esapi.errors.AccessControlException. Any exception - * thrown by the AccessControlRule will also result in an - * AccesControlException. If key does not map to + * thrown by the AccessControlRule will also result in an + * AccesControlException. If key does not map to * an AccessControlRule, then an AccessControlException - * is thrown. - * - * Developers should call {@code assertAuthorized} to enforce privileged access to - * the system. It should be used to answer the question: "Should execution + * is thrown. + * + * Developers should call {@code assertAuthorized} to enforce privileged access to + * the system. It should be used to answer the question: "Should execution * continue." Ideally, the call to assertAuthorized should - * be integrated into the application framework so that it is called - * automatically. - * - * @param key key maps to + * be integrated into the application framework so that it is called + * automatically. + * + * @param key key maps to * <AccessControlPolicy><AccessControlRules> * <AccessControlRule name="key" - * @param runtimeParameter runtimeParameter can contain anything that + * @param runtimeParameter runtimeParameter can contain anything that * the AccessControlRule needs from the runtime system. */ void assertAuthorized(Object key, Object runtimeParameter) throws AccessControlException; - - - /*** Below this line has been deprecated as of ESAPI 1.6 ***/ - - - - + + + /*** Below this line has been deprecated as of ESAPI 1.6 ***/ + + + + /** * Checks if the current user is authorized to access the referenced URL. Generally, this method should be invoked in the * application's controller or a filter as follows: *
ESAPI.accessController().isAuthorizedForURL(request.getRequestURI().toString());
- * - * The implementation of this method should call assertAuthorizedForURL(String url), and if an AccessControlException is - * not thrown, this method should return true. This way, if the user is not authorized, false would be returned, and the + * + * The implementation of this method should call assertAuthorizedForURL(String url), and if an AccessControlException is + * not thrown, this method should return true. This way, if the user is not authorized, false would be returned, and the * exception would be logged. - * - * @param url + * + * @param url * the URL as returned by request.getRequestURI().toString() - * - * @return + * + * @return * true, if is authorized for URL */ @Deprecated boolean isAuthorizedForURL(String url); /** - * Checks if the current user is authorized to access the referenced function. - * - * The implementation of this method should call assertAuthorizedForFunction(String functionName), and if an + * Checks if the current user is authorized to access the referenced function. + * + * The implementation of this method should call assertAuthorizedForFunction(String functionName), and if an * AccessControlException is not thrown, this method should return true. - * - * @param functionName + * + * @param functionName * the name of the function - * - * @return + * + * @return * true, if is authorized for function */ @Deprecated @@ -165,34 +165,34 @@ void assertAuthorized(Object key, Object runtimeParameter) /** - * Checks if the current user is authorized to access the referenced data, represented as an Object. - * - * The implementation of this method should call assertAuthorizedForData(String action, Object data), and if an + * Checks if the current user is authorized to access the referenced data, represented as an Object. + * + * The implementation of this method should call assertAuthorizedForData(String action, Object data), and if an * AccessControlException is not thrown, this method should return true. - * + * * @param action - * The action to verify for an access control decision, such as a role, or an action being performed on the object + * The action to verify for an access control decision, such as a role, or an action being performed on the object * (e.g., Read, Write, etc.), or the name of the function the data is being passed to. - * + * * @param data * The actual object or object identifier being accessed or a reference to the object being accessed. - * - * @return + * + * @return * true, if is authorized for the data */ @Deprecated boolean isAuthorizedForData(String action, Object data); - + /** - * Checks if the current user is authorized to access the referenced file. - * - * The implementation of this method should call assertAuthorizedForFile(String filepath), and if an AccessControlException + * Checks if the current user is authorized to access the referenced file. + * + * The implementation of this method should call assertAuthorizedForFile(String filepath), and if an AccessControlException * is not thrown, this method should return true. - * - * @param filepath + * + * @param filepath * the path of the file to be checked, including filename - * - * @return + * + * @return * true, if is authorized for the file */ @Deprecated @@ -201,14 +201,14 @@ void assertAuthorized(Object key, Object runtimeParameter) /** * Checks if the current user is authorized to access the referenced service. This can be used in applications that * provide access to a variety of back end services. - * - * The implementation of this method should call assertAuthorizedForService(String serviceName), and if an + * + * The implementation of this method should call assertAuthorizedForService(String serviceName), and if an * AccessControlException is not thrown, this method should return true. - * - * @param serviceName + * + * @param serviceName * the service name - * - * @return + * + * @return * true, if is authorized for the service */ @Deprecated @@ -218,8 +218,8 @@ void assertAuthorized(Object key, Object runtimeParameter) * Checks if the current user is authorized to access the referenced URL. The implementation should allow * access to be granted to any part of the URL. Generally, this method should be invoked in the * application's controller or a filter as follows: - *
ESAPI.accessController().assertAuthorizedForURL(request.getRequestURI().toString());
- * + *
ESAPI.accessController().assertAuthorizedForURL(request.getRequestURI().toString());
+ * * This method throws an AccessControlException if access is not authorized, or if the referenced URL does not exist. * If the User is authorized, this method simply returns. *

@@ -233,16 +233,16 @@ void assertAuthorized(Object key, Object runtimeParameter) *

  • Access control decisions must deny by default
  • * *
  • If access is not permitted, throw an AccessControlException with details
  • - * - * @param url + * + * @param url * the URL as returned by request.getRequestURI().toString() - * - * @throws AccessControlException + * + * @throws AccessControlException * if access is not permitted */ @Deprecated void assertAuthorizedForURL(String url) throws AccessControlException; - + /** * Checks if the current user is authorized to access the referenced function. The implementation should define the * function "namespace" to be enforced. Choosing something simple like the class name of action classes or menu item @@ -261,20 +261,20 @@ void assertAuthorized(Object key, Object runtimeParameter) *
  • Access control decisions must deny by default
  • * *
  • If access is not permitted, throw an AccessControlException with details
  • - * - * - * @param functionName + * + * + * @param functionName * the function name - * - * @throws AccessControlException + * + * @throws AccessControlException * if access is not permitted */ @Deprecated void assertAuthorizedForFunction(String functionName) throws AccessControlException; - + /** - * Checks if the current user is authorized to access the referenced data. This method simply returns if access is authorized. + * Checks if the current user is authorized to access the referenced data. This method simply returns if access is authorized. * It throws an AccessControlException if access is not authorized, or if the referenced data does not exist. *

    * Specification: The implementation should do the following: @@ -287,23 +287,23 @@ void assertAuthorized(Object key, Object runtimeParameter) *

  • Access control decisions must deny by default
  • * *
  • If access is not permitted, throw an AccessControlException with details
  • - * - * + * + * * @param action - * The action to verify for an access control decision, such as a role, or an action being performed on the object + * The action to verify for an access control decision, such as a role, or an action being performed on the object * (e.g., Read, Write, etc.), or the name of the function the data is being passed to. - * + * * @param data * The actual object or object identifier being accessed or a reference to the object being accessed. - * - * @throws AccessControlException + * + * @throws AccessControlException * if access is not permitted */ @Deprecated void assertAuthorizedForData(String action, Object data) throws AccessControlException; - + /** - * Checks if the current user is authorized to access the referenced file. The implementation should validate and canonicalize the + * Checks if the current user is authorized to access the referenced file. The implementation should validate and canonicalize the * input to be sure the filepath is not malicious. *

    * This method throws an AccessControlException if access is not authorized, or if the referenced File does not exist. @@ -319,15 +319,15 @@ void assertAuthorized(Object key, Object runtimeParameter) *

  • Access control decisions must deny by default
  • * *
  • If access is not permitted, throw an AccessControlException with details
  • - * - * + * + * * @param filepath * Path to the file to be checked * @throws AccessControlException if access is denied */ @Deprecated void assertAuthorizedForFile(String filepath) throws AccessControlException; - + /** * Checks if the current user is authorized to access the referenced service. This can be used in applications that * provide access to a variety of backend services. @@ -345,15 +345,15 @@ void assertAuthorized(Object key, Object runtimeParameter) *
  • Access control decisions must deny by default
  • * *
  • If access is not permitted, throw an AccessControlException with details
  • - * - * - * @param serviceName + * + * + * @param serviceName * the service name - * + * * @throws AccessControlException * if access is not permitted - */ + */ @Deprecated void assertAuthorizedForService(String serviceName) throws AccessControlException; - + } diff --git a/src/main/java/org/owasp/esapi/AccessReferenceMap.java b/src/main/java/org/owasp/esapi/AccessReferenceMap.java index f9e8cdc83..5f7e4e73c 100644 --- a/src/main/java/org/owasp/esapi/AccessReferenceMap.java +++ b/src/main/java/org/owasp/esapi/AccessReferenceMap.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -40,7 +40,7 @@ * references, as opposed to simple integers makes it impossible for an attacker to * guess valid identifiers. So if per-user AccessReferenceMaps are used, then request * forgery (CSRF) attacks will also be prevented. - * + * *
      * Set fileSet = new HashSet();
      * fileSet.addAll(...); // add direct references (e.g. File objects)
    @@ -55,18 +55,18 @@
      * String indref = request.getParameter( "file" );
      * File file = (File)map.getDirectReference( indref );
      * 
    - * + * *

    - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) * @author Chris Schmidt (chrisisbeef@gmail.com) */ public interface AccessReferenceMap extends Serializable { /** - * Get an iterator through the direct object references. No guarantee is made as + * Get an iterator through the direct object references. No guarantee is made as * to the order of items returned. - * + * * @return the iterator */ Iterator iterator(); @@ -76,11 +76,11 @@ public interface AccessReferenceMap extends Serializable { * direct object reference. Developers should use this call when building * URL's, form fields, hidden fields, etc... to help protect their private * implementation information. - * + * * @param directReference * the direct reference - * - * @return + * + * @return * the indirect reference */ K getIndirectReference(T directReference); @@ -122,14 +122,14 @@ public interface AccessReferenceMap extends Serializable { * // ... * } *

    - * + * * @param indirectReference * the indirect reference - * - * @return + * + * @return * the direct reference - * - * @throws AccessControlException + * + * @throws AccessControlException * if no direct reference exists for the specified indirect reference * @throws ClassCastException * if the implied type is not the same as the referenced object type @@ -137,26 +137,26 @@ public interface AccessReferenceMap extends Serializable { T getDirectReference(K indirectReference) throws AccessControlException; /** - * Adds a direct reference to the AccessReferenceMap, then generates and returns + * Adds a direct reference to the AccessReferenceMap, then generates and returns * an associated indirect reference. - * - * @param direct + * + * @param direct * the direct reference - * - * @return + * + * @return * the corresponding indirect reference */ K addDirectReference(T direct); - + /** * Removes a direct reference and its associated indirect reference from the AccessReferenceMap. - * - * @param direct + * + * @param direct * the direct reference to remove - * - * @return + * + * @return * the corresponding indirect reference - * + * * @throws AccessControlException * if the reference does not exist. */ @@ -167,8 +167,8 @@ public interface AccessReferenceMap extends Serializable { * any existing indirect references associated with items that are in the new list. * New indirect references could be generated every time, but that * might mess up anything that previously used an indirect reference, such - * as a URL parameter. - * + * as a URL parameter. + * * @param directReferences * a Set of direct references to add */ diff --git a/src/main/java/org/owasp/esapi/Authenticator.java b/src/main/java/org/owasp/esapi/Authenticator.java index bbc07ab90..e113b0bdd 100644 --- a/src/main/java/org/owasp/esapi/Authenticator.java +++ b/src/main/java/org/owasp/esapi/Authenticator.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -42,7 +42,7 @@ * current request and the name of the parameters containing the username and * password. The implementation should verify the password if necessary, create * a session if necessary, and set the user as the current user. - * + * *
      * public void doPost(ServletRequest request, ServletResponse response) {
      * try {
    @@ -52,7 +52,7 @@
      * // handle failed authentication (it's already been logged)
      * }
      * 
    - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -61,10 +61,10 @@ public interface Authenticator { /** * Clears the current User. This allows the thread to be reused safely. - * + * * This clears all threadlocal variables from the thread. This should ONLY be called after * all possible ESAPI operations have concluded. If you clear too early, many calls will - * fail, including logging, which requires the user identity. + * fail, including logging, which requires the user identity. */ void clearCurrent(); @@ -74,36 +74,36 @@ public interface Authenticator { * @see HTTPUtilities#setCurrentHTTP(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ User login() throws AuthenticationException; - + /** * This method should be called for every HTTP request, to login the current user either from the session of HTTP - * request. This method will set the current user so that getCurrentUser() will work properly. - * + * request. This method will set the current user so that getCurrentUser() will work properly. + * * Authenticates the user's credentials from the HttpServletRequest if * necessary, creates a session if necessary, and sets the user as the * current user. - * + * * Specification: The implementation should do the following: * 1) Check if the User is already stored in the session * a. If so, check that session absolute and inactivity timeout have not expired * b. Step 2 may not be required if 1a has been satisfied * 2) Verify User credentials - * a. It is recommended that you use + * a. It is recommended that you use * loginWithUsernameAndPassword(HttpServletRequest, HttpServletResponse) to verify credentials * 3) Set the last host of the User (ex. user.setLastHostAddress(address) ) * 4) Verify that the request is secure (ex. over SSL) * 5) Verify the User account is allowed to be logged in * a. Verify the User is not disabled, expired or locked - * 6) Assign User to session variable - * + * 6) Assign User to session variable + * * @param request * the current HTTP request * @param response * the HTTP response - * - * @return + * + * @return * the User - * + * * @throws AuthenticationException * if the credentials are not verified, or if the account is disabled, locked, expired, or timed out */ @@ -117,34 +117,34 @@ public interface Authenticator { *

    * This method is typically used for "reauthentication" for the most sensitive functions, such * as transactions, changing email address, and changing other account information. - * - * @param user + * + * @param user * the user who requires verification - * @param password + * @param password * the hashed user-supplied password - * - * @return + * + * @return * true, if the password is correct for the specified user * * @see #hashPassword(String password, String accountName) */ boolean verifyPassword(User user, String password); - + /** * Logs out the current user. - * - * This is usually done by calling User.logout on the current User. + * + * This is usually done by calling User.logout on the current User. */ void logout(); /** * Creates a new User with the information provided. Implementations should check - * accountName and password for proper format and strength against brute force + * accountName and password for proper format and strength against brute force * attacks ( verifyAccountNameStrength(String), verifyPasswordStrength(String, String) ). - * + * * Two copies of the new password are required to encourage user interface designers to - * include a "re-type password" field in their forms. Implementations should verify that - * both are the same. + * include a "re-type password" field in their forms. Implementations should verify that + * both are the same. *

    * WARNING: The implementation of this method as defined in the * default reference implementation class, {@code FileBasedAuthenticator}, @@ -152,18 +152,18 @@ public interface Authenticator { * to replace the default reference implementation class with your own custom * implementation that uses a stronger password hashing algorithm. * See class comments in * {@code FileBasedAuthenticator} for further details. - * - * @param accountName + * + * @param accountName * the account name of the new user - * @param password1 + * @param password1 * the password of the new user - * @param password2 + * @param password2 * the password of the new user. This field is to encourage user interface designers to include two password fields in their forms. - * - * @return - * the User that has been created - * - * @throws AuthenticationException + * + * @return + * the User that has been created + * + * @throws AuthenticationException * if user creation fails due to any of the qualifications listed in this method's description */ User createUser(String accountName, String password1, String password2) throws AuthenticationException; @@ -172,8 +172,8 @@ public interface Authenticator { * Generate a strong password. Implementations should use a large character set that does not * include confusing characters, such as i I 1 l 0 o and O. There are many algorithms to * generate strong memorable passwords that have been studied in the past. - * - * @return + * + * @return * a password with strong password strength */ String generateStrongPassword(); @@ -182,72 +182,72 @@ public interface Authenticator { * Generate strong password that takes into account the user's information and old password. Implementations * should verify that the new password does not include information such as the username, fragments of the * old password, and other information that could be used to weaken the strength of the password. - * - * @param user + * + * @param user * the user whose information to use when generating password - * @param oldPassword + * @param oldPassword * the old password to use when verifying strength of new password. The new password may be checked for fragments of oldPassword. - * - * @return + * + * @return * a password with strong password strength */ String generateStrongPassword(User user, String oldPassword); /** - * Changes the password for the specified user. This requires the current password, as well as + * Changes the password for the specified user. This requires the current password, as well as * the password to replace it with. The new password should be checked against old hashes to be sure the new password does not closely resemble or equal any recent passwords for that User. * Password strength should also be verified. This new password must be repeated to ensure that the user has typed it in correctly. - * - * @param user + * + * @param user * the user to change the password for - * @param currentPassword + * @param currentPassword * the current password for the specified user - * @param newPassword + * @param newPassword * the new password to use - * @param newPassword2 + * @param newPassword2 * a verification copy of the new password - * - * @throws AuthenticationException + * + * @throws AuthenticationException * if any errors occur */ void changePassword(User user, String currentPassword, String newPassword, String newPassword2) throws AuthenticationException; - + /** * Returns the User matching the provided accountId. If the accoundId is not found, an Anonymous * User or null may be returned. - * + * * @param accountId * the account id - * - * @return + * + * @return * the matching User object, or the Anonymous User if no match exists */ User getUser(long accountId); - + /** * Returns the User matching the provided accountName. If the accoundId is not found, an Anonymous * User or null may be returned. - * + * * @param accountName * the account name - * - * @return + * + * @return * the matching User object, or the Anonymous User if no match exists */ User getUser(String accountName); /** * Gets a collection containing all the existing user names. - * - * @return + * + * @return * a set of all user names */ Set getUserNames(); /** * Returns the currently logged in User. - * - * @return + * + * @return * the matching User object, or the Anonymous User if no match * exists */ @@ -255,7 +255,7 @@ public interface Authenticator { /** * Sets the currently logged in User. - * + * * @param user * the user to set as the current user */ @@ -275,13 +275,13 @@ public interface Authenticator { * meant to be an example implementation and generally should be avoided * and replaced with your own implementation. See class comments in * {@code FileBasedAuthenticator} for further details. - * + * * @param password * the password to hash * @param accountName * the account name to use as the salt - * - * @return + * + * @return * the hashed password * @throws EncryptionException * @@ -292,10 +292,10 @@ public interface Authenticator { /** * Removes the account of the specified accountName. - * + * * @param accountName * the account name to remove - * + * * @throws AuthenticationException * the authentication exception if user does not exist */ @@ -303,30 +303,30 @@ public interface Authenticator { /** * Ensures that the account name passes site-specific complexity requirements, like minimum length. - * + * * @param accountName * the account name - * + * * @throws AuthenticationException * if account name does not meet complexity requirements */ void verifyAccountNameStrength(String accountName) throws AuthenticationException; /** - * Ensures that the password meets site-specific complexity requirements, like length or number - * of character sets. This method takes the old password so that the algorithm can analyze the + * Ensures that the password meets site-specific complexity requirements, like length or number + * of character sets. This method takes the old password so that the algorithm can analyze the * new password to see if it is too similar to the old password. Note that this has to be * invoked when the user has entered the old password, as the list of old * credentials stored by ESAPI is all hashed. * Additionally, the user object is taken in order to verify the password and account name differ. - * + * * @param oldPassword * the old password * @param newPassword * the new password * @param user * the user - * + * * @throws AuthenticationException * if newPassword is too similar to oldPassword or if newPassword does not meet complexity requirements */ @@ -334,10 +334,10 @@ public interface Authenticator { /** * Determine if the account exists. - * + * * @param accountName * the account name - * + * * @return true, if the account exists */ boolean exists(String accountName); diff --git a/src/main/java/org/owasp/esapi/ESAPI.java b/src/main/java/org/owasp/esapi/ESAPI.java index 283156edf..ef389d020 100644 --- a/src/main/java/org/owasp/esapi/ESAPI.java +++ b/src/main/java/org/owasp/esapi/ESAPI.java @@ -1,15 +1,15 @@ /** * 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) 2008 - 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 Mike Fauzy Aspect Security * @author Rogan Dawes Aspect Security * @created 2008 @@ -33,7 +33,7 @@ public final class ESAPI { */ private ESAPI() { } - + /** * Clears the current User, HttpRequest, and HttpResponse associated with the current thread. This method * MUST be called as some containers do not properly clear threadlocal variables when the execution of @@ -69,7 +69,7 @@ public static void clearCurrent() { public static HttpServletRequest currentRequest() { return httpUtilities().getCurrentRequest(); } - + /** * Get the current HTTP Servlet Response being generated. * @return the current HTTP Servlet Response. @@ -77,16 +77,16 @@ public static HttpServletRequest currentRequest() { public static HttpServletResponse currentResponse() { return httpUtilities().getCurrentResponse(); } - + /** - * @return the current ESAPI AccessController object being used to maintain the access control rules for this application. + * @return the current ESAPI AccessController object being used to maintain the access control rules for this application. */ public static AccessController accessController() { return ObjFactory.make( securityConfiguration().getAccessControlImplementation(), "AccessController" ); } /** - * @return the current ESAPI Authenticator object being used to authenticate users for this application. + * @return the current ESAPI Authenticator object being used to authenticate users for this application. */ public static Authenticator authenticator() { return ObjFactory.make( securityConfiguration().getAuthenticationImplementation(), "Authenticator" ); @@ -95,50 +95,50 @@ public static Authenticator authenticator() { /** * The ESAPI Encoder is primarilly used to provide output encoding to * prevent Cross-Site Scripting (XSS). - * @return the current ESAPI Encoder object being used to encode and decode data for this application. + * @return the current ESAPI Encoder object being used to encode and decode data for this application. */ public static Encoder encoder() { return ObjFactory.make( securityConfiguration().getEncoderImplementation(), "Encoder" ); } /** - * @return the current ESAPI Encryptor object being used to encrypt and decrypt data for this application. + * @return the current ESAPI Encryptor object being used to encrypt and decrypt data for this application. */ public static Encryptor encryptor() { return ObjFactory.make( securityConfiguration().getEncryptionImplementation(), "Encryptor" ); } /** - * @return the current ESAPI Executor object being used to safely execute OS commands for this application. + * @return the current ESAPI Executor object being used to safely execute OS commands for this application. */ public static Executor executor() { return ObjFactory.make( securityConfiguration().getExecutorImplementation(), "Executor" ); } /** - * @return the current ESAPI HTTPUtilities object being used to safely access HTTP requests and responses - * for this application. + * @return the current ESAPI HTTPUtilities object being used to safely access HTTP requests and responses + * for this application. */ public static HTTPUtilities httpUtilities() { return ObjFactory.make( securityConfiguration().getHTTPUtilitiesImplementation(), "HTTPUtilities" ); } /** - * @return the current ESAPI IntrusionDetector being used to monitor for intrusions in this application. + * @return the current ESAPI IntrusionDetector being used to monitor for intrusions in this application. */ public static IntrusionDetector intrusionDetector() { return ObjFactory.make( securityConfiguration().getIntrusionDetectionImplementation(), "IntrusionDetector" ); } /** - * Get the current LogFactory being used by ESAPI. If there isn't one yet, it will create one, and then + * Get the current LogFactory being used by ESAPI. If there isn't one yet, it will create one, and then * return this same LogFactory from then on. * @return The current LogFactory being used by ESAPI. */ private static LogFactory logFactory() { return ObjFactory.make( securityConfiguration().getLogImplementation(), "LogFactory" ); } - + /** * @param clazz The class to associate the logger with. * @return The current Logger associated with the specified class. @@ -146,7 +146,7 @@ private static LogFactory logFactory() { public static Logger getLogger(Class clazz) { return logFactory().getLogger(clazz); } - + /** * @param moduleName The module to associate the logger with. * @return The current Logger associated with the specified module. @@ -154,16 +154,16 @@ public static Logger getLogger(Class clazz) { public static Logger getLogger(String moduleName) { return logFactory().getLogger(moduleName); } - + /** * @return The default Logger. */ public static Logger log() { return logFactory().getLogger("DefaultLogger"); } - + /** - * @return the current ESAPI Randomizer being used to generate random numbers in this application. + * @return the current ESAPI Randomizer being used to generate random numbers in this application. */ public static Randomizer randomizer() { return ObjFactory.make( securityConfiguration().getRandomizerImplementation(), "Randomizer" ); @@ -172,8 +172,8 @@ public static Randomizer randomizer() { private static volatile SecurityConfiguration overrideConfig = null; /** - * @return the current ESAPI SecurityConfiguration being used to manage the security configuration for - * ESAPI for this application. + * @return the current ESAPI SecurityConfiguration being used to manage the security configuration for + * ESAPI for this application. */ public static SecurityConfiguration securityConfiguration() { // copy the volatile into a non-volatile to prevent TOCTTOU race condition @@ -186,7 +186,7 @@ public static SecurityConfiguration securityConfiguration() { } /** - * @return the current ESAPI Validator being used to validate data in this application. + * @return the current ESAPI Validator being used to validate data in this application. */ public static Validator validator() { return ObjFactory.make( securityConfiguration().getValidationImplementation(), "Validator" ); diff --git a/src/main/java/org/owasp/esapi/Encoder.java b/src/main/java/org/owasp/esapi/Encoder.java index 9d08826be..1106882b7 100644 --- a/src/main/java/org/owasp/esapi/Encoder.java +++ b/src/main/java/org/owasp/esapi/Encoder.java @@ -1,15 +1,15 @@ /** * 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-2019 - 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 */ @@ -148,7 +148,7 @@ * BeEF - The Browser Exploitation Framework Project. * * - * + * * @see OWASP Cross-Site Scripting Prevention Cheat Sheet * @see OWASP Proactive Controls: C4: Encode and Escape Data * @see Properly encoding and escaping for the web @@ -156,7 +156,7 @@ * @since June 1, 2007 */ public interface Encoder { - + /** * This method is equivalent to calling {@code Encoder.canonicalize(input, restrictMultiple, restrictMixed);}. * @@ -177,23 +177,23 @@ public interface Encoder { * * @see #canonicalize(String, boolean, boolean) * @see W3C specifications - * + * * @param input the text to canonicalize * @return a String containing the canonicalized text */ String canonicalize(String input); - + /** * This method is the equivalent to calling {@code Encoder.canonicalize(input, strict, strict);}. * * @see #canonicalize(String, boolean, boolean) * @see W3C specifications - * - * @param input + * + * @param input * the text to canonicalize - * @param strict + * @param strict * true if checking for multiple and mixed encoding is desired, false otherwise - * + * * @return a String containing the canonicalized text */ String canonicalize(String input, boolean strict); @@ -281,7 +281,7 @@ public interface Encoder { * String url = ESAPI.encoder().canonicalize( request.getParameter("url"), false, false); *

    * WARNING #1!!! Please note that this method is incompatible with URLs and if there exist any HTML Entities - * that correspond with parameter values in a URL such as "&para;" in a URL like + * that correspond with parameter values in a URL such as "&para;" in a URL like * "https://foo.com/?bar=foo&parameter=wrong" you will get a mixed encoding validation exception. *

    * If you wish to canonicalize a URL/URI use the method {@code Encoder.getCanonicalizedURI(URI dirtyUri);} @@ -310,30 +310,30 @@ public interface Encoder { /** * Encode data for use in Cascading Style Sheets (CSS) content. - * + * * @see CSS Syntax [w3.org] - * - * @param untrustedData + * + * @param untrustedData * the untrusted data to output encode for CSS - * + * * @return the untrusted data safely output encoded for use in a CSS */ String encodeForCSS(String untrustedData); /** * Encode data for use in HTML using HTML entity encoding - *

    + *

    * Note that the following characters: * 00-08, 0B-0C, 0E-1F, and 7F-9F - *

    cannot be used in HTML. - * - * @see HTML Encodings [wikipedia.org] + *

    cannot be used in HTML. + * + * @see HTML Encodings [wikipedia.org] * @see SGML Specification [w3.org] * @see XML Specification [w3.org] - * - * @param untrustedData + * + * @param untrustedData * the untrusted data to output encode for HTML - * + * * @return the untrusted data safely output encoded for use in a HTML */ String encodeForHTML(String untrustedData); @@ -344,35 +344,35 @@ public interface Encoder { * @return the newly decoded String */ String decodeForHTML(String input); - + /** * Encode data for use in HTML attributes. - * - * @param untrustedData + * + * @param untrustedData * the untrusted data to output encode for an HTML attribute - * + * * @return the untrusted data safely output encoded for use in a use as an HTML attribute */ String encodeForHTMLAttribute(String untrustedData); /** - * Encode data for insertion inside a data value or function argument in JavaScript. Including user data + * Encode data for insertion inside a data value or function argument in JavaScript. Including user data * directly inside a script is quite dangerous. Great care must be taken to prevent including user data * directly into script code itself, as no amount of encoding will prevent attacks there. - * - * Please note there are some JavaScript functions that can never safely receive untrusted data + * + * Please note there are some JavaScript functions that can never safely receive untrusted data * as input – even if the user input is encoded. - * + * * For example: *

          *  <script>
          *      window.setInterval('<%= EVEN IF YOU ENCODE UNTRUSTED DATA YOU ARE XSSED HERE %>');
          *  </script>
          * 
    - * @param untrustedData + * @param untrustedData * the untrusted data to output encode for JavaScript - * + * * @return the untrusted data safely output encoded for use in a use in JavaScript */ String encodeForJavaScript(String untrustedData); @@ -381,119 +381,119 @@ public interface Encoder { * Encode data for insertion inside a data value in a Visual Basic script. Putting user data directly * inside a script is quite dangerous. Great care must be taken to prevent putting user data * directly into script code itself, as no amount of encoding will prevent attacks there. - * + * * This method is not recommended as VBScript is only supported by Internet Explorer - * - * @param untrustedData + * + * @param untrustedData * the untrusted data to output encode for VBScript - * + * * @return the untrusted data safely output encoded for use in a use in VBScript */ String encodeForVBScript(String untrustedData); /** - * Encode input for use in a SQL query, according to the selected codec + * Encode input for use in a SQL query, according to the selected codec * (appropriate codecs include the MySQLCodec and OracleCodec). - * + * * This method is not recommended. The use of the {@code PreparedStatement} - * interface is the preferred approach. However, if for some reason - * this is impossible, then this method is provided as a weaker - * alternative. - * + * interface is the preferred approach. However, if for some reason + * this is impossible, then this method is provided as a weaker + * alternative. + * * The best approach is to make sure any single-quotes are double-quoted. * Another possible approach is to use the {escape} syntax described in the * JDBC specification in section 1.5.6. * * However, this syntax does not work with all drivers, and requires * modification of all queries. - * + * * @see JDBC Specification * @see java.sql.PreparedStatement - * - * @param codec + * + * @param codec * a Codec that declares which database 'input' is being encoded for (ie. MySQL, Oracle, etc.) - * @param input + * @param input * the text to encode for SQL - * + * * @return input encoded for use in SQL */ String encodeForSQL(Codec codec, String input); /** - * Encode for an operating system command shell according to the selected codec (appropriate codecs include the WindowsCodec and UnixCodec). + * Encode for an operating system command shell according to the selected codec (appropriate codecs include the WindowsCodec and UnixCodec). + * + * Please note the following recommendations before choosing to use this method: * - * Please note the following recommendations before choosing to use this method: - * * 1) It is strongly recommended that applications avoid making direct OS system calls if possible as such calls are not portable, and they are potentially unsafe. Please use language provided features if at all possible, rather than native OS calls to implement the desired feature. * 2) If an OS call cannot be avoided, then it is recommended that the program to be invoked be invoked directly (e.g., System.exec("nameofcommand" + "parameterstocommand");) as this avoids the use of the command shell. The "parameterstocommand" should of course be validated before passing them to the OS command. * 3) If you must use this method, then we recommend validating all user supplied input passed to the command shell as well, in addition to using this method in order to make the command shell invocation safe. - * + * * An example use of this method would be: System.exec("dir " + ESAPI.encodeForOS(WindowsCodec, "parameter(s)tocommandwithuserinput"); - * - * @param codec + * + * @param codec * a Codec that declares which operating system 'input' is being encoded for (ie. Windows, Unix, etc.) - * @param input + * @param input * the text to encode for the command shell - * + * * @return input encoded for use in command shell */ String encodeForOS(Codec codec, String input); /** * Encode data for use in LDAP queries. Wildcard (*) characters will be encoded. - * - * @param input + * + * @param input * the text to encode for LDAP - * + * * @return input encoded for use in LDAP */ String encodeForLDAP(String input); /** * Encode data for use in LDAP queries. You have the option whether or not to encode wildcard (*) characters. - * - * @param input + * + * @param input * the text to encode for LDAP - * @param encodeWildcards + * @param encodeWildcards * whether or not wildcard (*) characters will be encoded. * * @return input encoded for use in LDAP */ String encodeForLDAP(String input, boolean encodeWildcards); - + /** * Encode data for use in an LDAP distinguished name. - * - * @param input + * + * @param input * the text to encode for an LDAP distinguished name - * + * * @return input encoded for use in an LDAP distinguished name */ String encodeForDN(String input); /** * Encode data for use in an XPath query. - * - * NB: The reference implementation encodes almost everything and may over-encode. - * + * + * NB: The reference implementation encodes almost everything and may over-encode. + * * The difficulty with XPath encoding is that XPath has no built in mechanism for escaping * characters. It is possible to use XQuery in a parameterized way to - * prevent injection. - * + * prevent injection. + * * For more information, refer to this * article which specifies the following list of characters as the most * dangerous: ^&"*';<>(). This * paper suggests disallowing ' and " in queries. - * + * * @see XPath Injection [ibm.com] * @see Blind XPath Injection [packetstormsecurity.org] - * + * * @param input * the text to encode for XPath - * @return + * @return * input encoded for use in XPath */ String encodeForXPath(String input); @@ -507,12 +507,12 @@ public interface Encoder { * hopefully rare case that you need to make sure that data is safe for * inclusion in an XML document and cannot use a parser, this method provides * a safe mechanism to do so. - * + * * @see Character Encoding in Entities - * + * * @param input * the text to encode for XML - * + * * @return * input encoded for use in XML */ @@ -527,13 +527,13 @@ public interface Encoder { * hopefully rare case that you need to make sure that data is safe for * inclusion in an XML document and cannot use a parse, this method provides * a safe mechanism to do so. - * + * * @see Character Encoding in Entities - * + * * @param input * the text to encode for use as an XML attribute - * - * @return + * + * @return * input encoded for use in an XML attribute */ String encodeForXMLAttribute(String input); @@ -542,16 +542,16 @@ public interface Encoder { * Encode for use in a URL. This method performs URL encoding * on the entire string. - * + * * @see URL encoding - * - * @param input + * + * @param input * the text to encode for use in a URL - * - * @return input + * + * @return input * encoded for use in a URL - * - * @throws EncodingException + * + * @throws EncodingException * if encoding fails */ String encodeForURL(String input) throws EncodingException; @@ -560,47 +560,47 @@ public interface Encoder { * Decode from URL. Implementations should first canonicalize and * detect any double-encoding. If this check passes, then the data is decoded using URL * decoding. - * - * @param input + * + * @param input * the text to decode from an encoded URL - * - * @return + * + * @return * the decoded URL value - * - * @throws EncodingException + * + * @throws EncodingException * if decoding fails */ String decodeFromURL(String input) throws EncodingException; /** * Encode for Base64. - * - * @param input + * + * @param input * the text to encode for Base64 * @param wrap * the encoder will wrap lines every 64 characters of output - * + * * @return input encoded for Base64 */ String encodeForBase64(byte[] input, boolean wrap); /** * Decode data encoded with BASE-64 encoding. - * - * @param input + * + * @param input * the Base64 text to decode - * + * * @return input decoded from Base64 - * + * * @throws IOException */ byte[] decodeFromBase64(String input) throws IOException; /** - * Get a version of the input URI that will be safe to run regex and other validations against. - * It is not recommended to persist this value as it will transform user input. This method + * Get a version of the input URI that will be safe to run regex and other validations against. + * It is not recommended to persist this value as it will transform user input. This method * will not test to see if the URI is RFC-3986 compliant. - * + * * @param dirtyUri * the tainted URI * @return The canonicalized URI diff --git a/src/main/java/org/owasp/esapi/EncoderConstants.java b/src/main/java/org/owasp/esapi/EncoderConstants.java index 724b15ad4..ec2cbfac4 100644 --- a/src/main/java/org/owasp/esapi/EncoderConstants.java +++ b/src/main/java/org/owasp/esapi/EncoderConstants.java @@ -19,7 +19,7 @@ public class EncoderConstants { static { PASSWORD_SPECIALS = CollectionsUtil.arrayToSet(CHAR_PASSWORD_SPECIALS); } - + /** * a-b */ @@ -28,7 +28,7 @@ public class EncoderConstants { static { LOWERS = CollectionsUtil.arrayToSet(CHAR_PASSWORD_SPECIALS); } - + /** * A-Z */ @@ -45,7 +45,7 @@ public class EncoderConstants { static { DIGITS = CollectionsUtil.arrayToSet(CHAR_DIGITS); } - + /** * !$*+-.=?@^_|~ */ @@ -54,7 +54,7 @@ public class EncoderConstants { static { SPECIALS = CollectionsUtil.arrayToSet(CHAR_SPECIALS); } - + /** * CHAR_LOWERS union CHAR_UPPERS */ @@ -63,7 +63,7 @@ public class EncoderConstants { static { LETTERS = CollectionsUtil.arrayToSet(CHAR_LETTERS); } - + /** * CHAR_LETTERS union CHAR_DIGITS */ @@ -72,7 +72,7 @@ public class EncoderConstants { static { ALPHANUMERICS = CollectionsUtil.arrayToSet(CHAR_ALPHANUMERICS); } - + /** * Password character set, is alphanumerics (without l, i, I, o, O, and 0) * selected specials like + (bad for URL encoding, | is like i and 1, @@ -83,16 +83,16 @@ public class EncoderConstants { static { PASSWORD_LOWERS = CollectionsUtil.arrayToSet(CHAR_ALPHANUMERICS); } - + /** - * + * */ public final static char[] CHAR_PASSWORD_UPPERS = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; public final static Set PASSWORD_UPPERS; static { PASSWORD_UPPERS = CollectionsUtil.arrayToSet(CHAR_PASSWORD_UPPERS); } - + /** * 2-9 */ @@ -101,7 +101,7 @@ public class EncoderConstants { static { PASSWORD_DIGITS = CollectionsUtil.arrayToSet(CHAR_PASSWORD_DIGITS); } - + /** * CHAR_PASSWORD_LOWERS union CHAR_PASSWORD_UPPERS */ diff --git a/src/main/java/org/owasp/esapi/EncryptedProperties.java b/src/main/java/org/owasp/esapi/EncryptedProperties.java index fbec7e2c1..b1db53112 100644 --- a/src/main/java/org/owasp/esapi/EncryptedProperties.java +++ b/src/main/java/org/owasp/esapi/EncryptedProperties.java @@ -1,15 +1,15 @@ /** * 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-2019 - 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 */ @@ -41,13 +41,13 @@ public interface EncryptedProperties { /** * Gets the property value from the encrypted store, decrypts it, and * returns the plaintext value to the caller. - * + * * @param key - * the name of the property to get - * - * @return + * the name of the property to get + * + * @return * The decrypted property value. null if the key is not set. - * + * * @throws EncryptionException * if the property could not be decrypted */ @@ -56,57 +56,57 @@ public interface EncryptedProperties { /** * Encrypts the plaintext property value and stores the ciphertext value * in the encrypted store. - * + * * @param key * the name of the property to set * @param value * the value of the property to set - * - * @return + * + * @return * the previously encrypted property value for the specified key, or * {@code null} if it did not have one. - * + * * @throws EncryptionException * if the property could not be encrypted */ String setProperty(String key, String value) throws EncryptionException; - + /** * Returns a {@code Set} view of properties. The {@code Set} is backed by a * {@code java.util.Hashtable}, so changes to the {@code Hashtable} are - * reflected in the {@code Set}, and vice-versa. The {@code Set} supports element + * reflected in the {@code Set}, and vice-versa. The {@code Set} supports element * removal (which removes the corresponding entry from the {@code Hashtable}, * but not element addition. - * - * @return + * + * @return * a set view of the properties contained in this map. */ Set keySet(); - + /** * Reads a property list (key and element pairs) from the input stream. - * + * * @param in * the input stream that contains the properties file - * + * * @throws IOException * Signals that an I/O exception has occurred. */ void load(InputStream in) throws IOException; - + /** - * Writes this property list (key and element pairs) in this Properties table to - * the output stream in a format suitable for loading into a Properties table using the load method. - * + * Writes this property list (key and element pairs) in this Properties table to + * the output stream in a format suitable for loading into a Properties table using the load method. + * * @param out * the output stream that contains the properties file * @param comments * a description of the property list (ex. "Encrypted Properties File"). - * + * * @throws IOException * Signals that an I/O exception has occurred. */ - void store(OutputStream out, String comments) throws IOException; - - + void store(OutputStream out, String comments) throws IOException; + + } diff --git a/src/main/java/org/owasp/esapi/Encryptor.java b/src/main/java/org/owasp/esapi/Encryptor.java index 64134849b..28bb896a3 100644 --- a/src/main/java/org/owasp/esapi/Encryptor.java +++ b/src/main/java/org/owasp/esapi/Encryptor.java @@ -1,15 +1,15 @@ /** * 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 © 2007-2019 - 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 * @author kevin.w.wall@gmail.com * @created 2007 @@ -49,7 +49,7 @@ * section 4 of * * Design Goals in OWASP ESAPI Cryptography. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -65,17 +65,17 @@ public interface Encryptor { * but not to an attacker. * See * this article for more information about hashing as it pertains to password schemes. - * + * * @param plaintext * the plaintext String to encrypt * @param salt * the salt to add to the plaintext String before hashing - * - * @return + * + * @return * the encrypted hash of 'plaintext' stored as a String - * + * * @throws EncryptionException - * if the specified hash algorithm could not be found or another problem exists with + * if the specified hash algorithm could not be found or another problem exists with * the hashing of 'plaintext' */ String hash(String plaintext, String salt) throws EncryptionException; @@ -85,33 +85,33 @@ public interface Encryptor { * salt. The salt helps to protect against a rainbow table attack by mixing * in some extra data with the plaintext. Some good choices for a salt might * be an account name or some other string that is known to the application - * but not to an attacker. + * but not to an attacker. * See * this article for more information about hashing as it pertains to password schemes. - * + * * @param plaintext * the plaintext String to encrypt * @param salt * the salt to add to the plaintext String before hashing * @param iterations * the number of times to iterate the hash - * - * @return + * + * @return * the encrypted hash of 'plaintext' stored as a String - * + * * @throws EncryptionException - * if the specified hash algorithm could not be found or another problem exists with + * if the specified hash algorithm could not be found or another problem exists with * the hashing of 'plaintext' */ String hash(String plaintext, String salt, int iterations) throws EncryptionException; - + /** * Encrypts the provided plaintext bytes using the cipher transformation * specified by the property Encryptor.CipherTransformation * and the master encryption key as specified by the property * {@code Encryptor.MasterKey} as defined in the ESAPI.properties file. *

    - * + * * @param plaintext The {@code PlainText} to be encrypted. * @return the {@code CipherText} object from which the raw ciphertext, the * IV, the cipher transformation, and many other aspects about @@ -175,7 +175,7 @@ CipherText encrypt(SecretKey key, PlainText plaintext) * @see #decrypt(SecretKey, CipherText) */ PlainText decrypt(CipherText ciphertext) throws EncryptionException; - + /** * Decrypts the provided {@link CipherText} using the information from it * and the specified secret key. @@ -199,7 +199,7 @@ CipherText encrypt(SecretKey key, PlainText plaintext) * @see #decrypt(CipherText) */ PlainText decrypt(SecretKey key, CipherText ciphertext) throws EncryptionException; - + /** * Create a digital signature for the provided data and return it in a * string. @@ -213,13 +213,13 @@ CipherText encrypt(SecretKey key, PlainText plaintext) * can not be used with expected results across JVM instances. This limitation * will be addressed in ESAPI 2.1. *

    - * + * * @param data * the data to sign - * - * @return + * + * @return * the digital signature stored as a String - * + * * @throws EncryptionException * if the specified signature algorithm cannot be found */ @@ -242,23 +242,23 @@ CipherText encrypt(SecretKey key, PlainText plaintext) * the signature to verify against 'data' * @param data * the data to verify against 'signature' - * - * @return + * + * @return * true, if the signature is verified, false otherwise */ boolean verifySignature(String signature, String data); /** * Creates a seal that binds a set of data and includes an expiration timestamp. - * + * * @param data * the data to seal * @param timestamp * the absolute expiration date of the data, expressed as seconds since the epoch - * - * @return + * + * @return * the seal - * + * * @throws IntegrityException */ String seal(String data, long timestamp) throws IntegrityException; @@ -267,48 +267,48 @@ CipherText encrypt(SecretKey key, PlainText plaintext) * Unseals data (created with the seal method) and throws an exception * describing any of the various problems that could exist with a seal, such * as an invalid seal format, expired timestamp, or decryption error. - * + * * @param seal * the sealed data - * - * @return + * + * @return * the original (unsealed) data - * - * @throws EncryptionException + * + * @throws EncryptionException * if the unsealed data cannot be retrieved for any reason */ String unseal( String seal ) throws EncryptionException; - + /** * Verifies a seal (created with the seal method) and throws an exception * describing any of the various problems that could exist with a seal, such * as an invalid seal format, expired timestamp, or data mismatch. - * + * * @param seal * the seal to verify - * - * @return + * + * @return * true, if the seal is valid. False otherwise */ boolean verifySeal(String seal); - + /** * Gets an absolute timestamp representing an offset from the current time to be used by * other functions in the library. - * - * @param offset + * + * @param offset * the offset to add to the current time - * - * @return + * + * @return * the absolute timestamp */ long getRelativeTimeStamp( long offset ); - + /** * Gets a timestamp representing the current date and time to be used by * other functions in the library. - * - * @return + * + * @return * a timestamp representing the current time */ long getTimeStamp(); diff --git a/src/main/java/org/owasp/esapi/ExecuteResult.java b/src/main/java/org/owasp/esapi/ExecuteResult.java index 33bf0b13c..6887b80c1 100644 --- a/src/main/java/org/owasp/esapi/ExecuteResult.java +++ b/src/main/java/org/owasp/esapi/ExecuteResult.java @@ -25,7 +25,7 @@ * @since Aug 25, 2010 */ public class ExecuteResult { - + private final int exitValue; private final String output; private final String errors; @@ -66,7 +66,7 @@ public String getOutput() { public String getErrors() { return errors; } - + @Override public String toString() { return "ExecuteResult[exitValue="+exitValue+",output="+output+",errors="+errors+"]"; diff --git a/src/main/java/org/owasp/esapi/Executor.java b/src/main/java/org/owasp/esapi/Executor.java index 7ad5ba4df..122dcdb94 100644 --- a/src/main/java/org/owasp/esapi/Executor.java +++ b/src/main/java/org/owasp/esapi/Executor.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -23,18 +23,18 @@ /** * The Executor interface is used to run an OS command with reduced security risk. - * + * *

    Implementations should do as much as possible to minimize the risk of * injection into either the command or parameters. In addition, implementations * should timeout after a specified time period in order to help prevent denial - * of service attacks.

    - * + * of service attacks.

    + * *

    The class should perform logging and error handling as * well. Finally, implementation should handle errors and generate an * ExecutorException with all the necessary information.

    * *

    The reference implementation does all of the above.

    - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -43,7 +43,7 @@ public interface Executor { /** * Invokes the specified executable with default workdir and codec and not logging parameters. - * + * * @param executable * the command to execute * @param params diff --git a/src/main/java/org/owasp/esapi/HTTPUtilities.java b/src/main/java/org/owasp/esapi/HTTPUtilities.java index a4091eda7..faa950dcc 100644 --- a/src/main/java/org/owasp/esapi/HTTPUtilities.java +++ b/src/main/java/org/owasp/esapi/HTTPUtilities.java @@ -51,7 +51,7 @@ public interface HTTPUtilities * Calls addCookie with the *current* request. * * @param cookie The cookie to add - * + * * @see HTTPUtilities#setCurrentHTTP(HttpServletRequest, HttpServletResponse) */ void addCookie(Cookie cookie); @@ -230,7 +230,7 @@ public interface HTTPUtilities /** * Calls getCookie with the *current* response. - * + * * @param name The cookie to get * @return the requested cookie value * @throws ValidationException @@ -278,7 +278,7 @@ public interface HTTPUtilities * * @return List of new File objects from upload * @throws ValidationException if the file fails validation - * + * * @see HTTPUtilities#setCurrentHTTP(HttpServletRequest, HttpServletResponse) */ List getFileUploads() throws ValidationException; @@ -558,9 +558,9 @@ public interface HTTPUtilities /** * Calls setNoCacheHeaders with the *current* response. - * + * * ~DEPRECATED~ Per Kevin Wall, storing passwords with reversible encryption is contrary to *many* - * company's stated security policies. + * company's stated security policies. * * @see HTTPUtilities#setCurrentHTTP(HttpServletRequest, HttpServletResponse) */ @@ -568,11 +568,11 @@ public interface HTTPUtilities String setRememberToken(String password, int maxAge, String domain, String path); /** - * + * */ String setRememberToken(HttpServletRequest request, HttpServletResponse response, int maxAge, String domain, String path); - + /** * Set a cookie containing the current User's remember me token for automatic authentication. The use of remember me tokens * is generally not recommended, but this method will help do it as safely as possible. The user interface should strongly warn @@ -589,7 +589,7 @@ public interface HTTPUtilities * The username can be retrieved with: User username = ESAPI.authenticator().getCurrentUser(); * *~DEPRECATED~ Per Kevin Wall, storing passwords with reversible encryption is contrary to *many* - * company's stated security policies. + * company's stated security policies. * * @param request * @param password the user's password diff --git a/src/main/java/org/owasp/esapi/IntrusionDetector.java b/src/main/java/org/owasp/esapi/IntrusionDetector.java index 2a1388332..ccb2bc984 100644 --- a/src/main/java/org/owasp/esapi/IntrusionDetector.java +++ b/src/main/java/org/owasp/esapi/IntrusionDetector.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -25,22 +25,22 @@ *

    * The interface is currently designed to accept exceptions as well as custom events. Implementations can use this * stream of information to detect both normal and abnormal behavior. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 */ public interface IntrusionDetector { /** - * Adds the exception to the IntrusionDetector. This method should immediately log the exception so that developers throwing an + * Adds the exception to the IntrusionDetector. This method should immediately log the exception so that developers throwing an * IntrusionException do not have to remember to log every error. The implementation should store the exception somewhere for the current user * in order to check if the User has reached the threshold for any Enterprise Security Exceptions. The User object is the recommended location for storing * the current user's security exceptions. If the User has reached any security thresholds, the appropriate security action can be taken and logged. - * - * @param exception + * + * @param exception * the exception thrown - * - * @throws IntrusionException + * + * @throws IntrusionException * the intrusion exception */ void addException(Exception exception) throws IntrusionException; @@ -49,13 +49,13 @@ public interface IntrusionDetector { * Adds the event to the IntrusionDetector. This method should immediately log the event. The implementation should store the event somewhere for the current user * in order to check if the User has reached the threshold for any Enterprise Security Exceptions. The User object is the recommended location for storing * the current user's security event. If the User has reached any security thresholds, the appropriate security action can be taken and logged. - * - * @param eventName + * + * @param eventName * the event to add - * @param logMessage + * @param logMessage * the message to log with the event - * - * @throws IntrusionException + * + * @throws IntrusionException * the intrusion exception */ void addEvent(String eventName, String logMessage) throws IntrusionException; diff --git a/src/main/java/org/owasp/esapi/LogFactory.java b/src/main/java/org/owasp/esapi/LogFactory.java index edde286c2..7571ea460 100644 --- a/src/main/java/org/owasp/esapi/LogFactory.java +++ b/src/main/java/org/owasp/esapi/LogFactory.java @@ -1,15 +1,15 @@ /** * 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 Rogan DawesAspect Security * @created 2008 */ @@ -18,43 +18,43 @@ /** * The LogFactory interface is intended to allow substitution of various logging packages, while providing * a common interface to access them. - * - * In the reference implementation, JavaLogFactory.java implements this interface. JavaLogFactory.java also contains an - * inner class called JavaLogger which implements Logger.java and uses the Java logging package to log events. - * + * + * In the reference implementation, JavaLogFactory.java implements this interface. JavaLogFactory.java also contains an + * inner class called JavaLogger which implements Logger.java and uses the Java logging package to log events. + * * @see org.owasp.esapi.ESAPI - * + * * @author rdawes * */ public interface LogFactory { - + /** - * Gets the logger associated with the specified module name. The module name is used by the logger to log which - * module is generating the log events. The implementation of this method should return any preexisting Logger + * Gets the logger associated with the specified module name. The module name is used by the logger to log which + * module is generating the log events. The implementation of this method should return any preexisting Logger * associated with this module name, rather than creating a new Logger. *

    * The JavaLogFactory reference implementation meets these requirements. - * + * * @param moduleName * The name of the module requesting the logger. * @return * The Logger associated with this module. */ Logger getLogger(String moduleName); - + /** - * Gets the logger associated with the specified class. The class is used by the logger to log which - * class is generating the log events. The implementation of this method should return any preexisting Logger + * Gets the logger associated with the specified class. The class is used by the logger to log which + * class is generating the log events. The implementation of this method should return any preexisting Logger * associated with this class name, rather than creating a new Logger. *

    * The JavaLogFactory reference implementation meets these requirements. - * + * * @param clazz * The name of the class requesting the logger. * @return * The Logger associated with this class. */ Logger getLogger(Class clazz); - + } diff --git a/src/main/java/org/owasp/esapi/Logger.java b/src/main/java/org/owasp/esapi/Logger.java index 7c4ccef9e..288509b92 100644 --- a/src/main/java/org/owasp/esapi/Logger.java +++ b/src/main/java/org/owasp/esapi/Logger.java @@ -1,15 +1,15 @@ /** * 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-2019 - 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 */ @@ -45,22 +45,22 @@ *

  • EVENT_UNSPECIFIED
  • * *

    - * Your custom implementation can extend or change this list if desired. + * Your custom implementation can extend or change this list if desired. *

    - * This {@code Logger} allows callers to determine which logging levels are enabled, and to submit events + * This {@code Logger} allows callers to determine which logging levels are enabled, and to submit events * at different severity levels.
    *
    Implementors of this interface should: - * + * *

      - *
    1. Provide a mechanism for setting the logging level threshold that is currently enabled. This usually works by logging all + *
    2. Provide a mechanism for setting the logging level threshold that is currently enabled. This usually works by logging all * events at and above that severity level, and discarding all events below that level. * This is usually done via configuration, but can also be made accessible programmatically.
    3. - *
    4. Ensure that dangerous HTML characters are encoded before they are logged to defend against malicious injection into logs + *
    5. Ensure that dangerous HTML characters are encoded before they are logged to defend against malicious injection into logs * that might be viewed in an HTML based log viewer.
    6. *
    7. Encode any CRLF characters included in log data in order to prevent log injection attacks.
    8. - *
    9. Avoid logging the user's session ID. Rather, they should log something equivalent like a - * generated logging session ID, or a hashed value of the session ID so they can track session specific - * events without risking the exposure of a live session's ID.
    10. + *
    11. Avoid logging the user's session ID. Rather, they should log something equivalent like a + * generated logging session ID, or a hashed value of the session ID so they can track session specific + * events without risking the exposure of a live session's ID.
    12. *
    13. Record the following information with each event:
    14. *
        *
      1. Identity of the user that caused the event.
      2. @@ -72,13 +72,13 @@ *
      3. A date/time stamp.
      4. *
      *
    - * + * * Custom logger implementations might also: *
      - *
    1. Filter out any sensitive data specific to the current application or organization, such as credit cards, + *
    2. Filter out any sensitive data specific to the current application or organization, such as credit cards, * social security numbers, etc.
    3. *
    - * + * * There are both SLF4J and native Java Logging (i.e., {@code java.util.logging}, aka JUL) implementations * of the ESAPI logger with JUL being our default logger for our stock ESAPI.properties file that * is delivered along with ESAPI releases in a separate esapi-configuration jar available from the @@ -88,11 +88,11 @@ * The {@code org.owasp.esapi.logging.java.JavaLogger} class uses the {@code java.util.logging} package as * the basis for its logging implementation. Both provided implementations implement requirements #1 through #5 above. *

    - * Customization: It is expected that most organizations may wish to implement their own custom {@code Logger} class in + * Customization: It is expected that most organizations may wish to implement their own custom {@code Logger} class in * order to integrate ESAPI logging with their specific logging infrastructure. The ESAPI feference implementations * can serve as a useful starting point to intended to provide a simple functional example of an implementation, but * they are also largely usuable out-of-the-box with some additional minimal log configuration. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -100,7 +100,7 @@ public interface Logger { // All implied static final as this is an interface - + /** * A security type of log event that has succeeded. This is one of 6 predefined * ESAPI logging events. New events can be added. @@ -126,7 +126,7 @@ public interface Logger { * ESAPI logging events. New events can be added. */ EventType EVENT_SUCCESS = new EventType( "EVENT SUCCESS", true); - + /** * A non-security type of log event that has failed. This is one of 6 predefined * ESAPI logging events. New events can be added. @@ -142,22 +142,22 @@ public interface Logger { /** * Defines the type of log event that is being generated. The Logger interface defines 6 types of Log events: * SECURITY_SUCCESS, SECURITY_FAILURE, EVENT_SUCCESS, EVENT_FAILURE, EVENT_UNSPECIFIED. - * Your implementation can extend or change this list if desired. + * Your implementation can extend or change this list if desired. */ class EventType { - + private String type; private Boolean success = null; - + public EventType (String name, Boolean newSuccess) { this.type = name; this.success = newSuccess; } - + public Boolean isSuccess() { return success; } - + /** * Convert the {@code EventType} to a string. * @return The event type name. @@ -167,76 +167,76 @@ public String toString() { return this.type; } } - + /* - * The Logger interface defines 6 logging levels: FATAL, ERROR, WARNING, INFO, DEBUG, TRACE. It also + * The Logger interface defines 6 logging levels: FATAL, ERROR, WARNING, INFO, DEBUG, TRACE. It also * supports ALL, which logs all events, and OFF, which disables all logging. - * Your implementation can extend or change this list if desired. + * Your implementation can extend or change this list if desired. */ - + /** OFF indicates that no messages should be logged. This level is initialized to Integer.MAX_VALUE. */ int OFF = Integer.MAX_VALUE; /** FATAL indicates that only FATAL messages should be logged. This level is initialized to 1000. */ int FATAL = 1000; - /** ERROR indicates that ERROR messages and above should be logged. + /** ERROR indicates that ERROR messages and above should be logged. * This level is initialized to 800. */ int ERROR = 800; - /** WARNING indicates that WARNING messages and above should be logged. + /** WARNING indicates that WARNING messages and above should be logged. * This level is initialized to 600. */ int WARNING = 600; - /** INFO indicates that INFO messages and above should be logged. + /** INFO indicates that INFO messages and above should be logged. * This level is initialized to 400. */ int INFO = 400; - /** DEBUG indicates that DEBUG messages and above should be logged. + /** DEBUG indicates that DEBUG messages and above should be logged. * This level is initialized to 200. */ int DEBUG = 200; - /** TRACE indicates that TRACE messages and above should be logged. + /** TRACE indicates that TRACE messages and above should be logged. * This level is initialized to 100. */ int TRACE = 100; /** ALL indicates that all messages should be logged. This level is initialized to Integer.MIN_VALUE. */ int ALL = Integer.MIN_VALUE; - + /** - * Dynamically set the ESAPI logging severity level. All events of this level and higher will be logged from + * Dynamically set the ESAPI logging severity level. All events of this level and higher will be logged from * this point forward for all logs. All events below this level will be discarded. - * - * @param level The level to set the logging level to. + * + * @param level The level to set the logging level to. */ void setLevel(int level); - + /** Retrieve the current ESAPI logging level for this logger. - * + * * @return The current logging level. */ int getESAPILevel(); - + /** * Log a fatal event if 'fatal' level logging is enabled. - * - * @param type + * + * @param type * the type of event - * @param message + * @param message * the message to log */ void fatal(EventType type, String message); - + /** - * Log a fatal level security event if 'fatal' level logging is enabled + * Log a fatal level security event if 'fatal' level logging is enabled * and also record the stack trace associated with the event. - * - * @param type + * + * @param type * the type of event - * @param message + * @param message * the message to log - * @param throwable + * @param throwable * the exception to be logged */ void fatal(EventType type, String message, Throwable throwable); @@ -244,30 +244,30 @@ public String toString() { /** * Allows the caller to determine if messages logged at this level * will be discarded, to avoid performing expensive processing. - * + * * @return true if fatal level messages will be output to the log */ boolean isFatalEnabled(); /** * Log an error level security event if 'error' level logging is enabled. - * - * @param type - * the type of event - * @param message + * + * @param type + * the type of event + * @param message * the message to log */ void error(EventType type, String message); - + /** - * Log an error level security event if 'error' level logging is enabled + * Log an error level security event if 'error' level logging is enabled * and also record the stack trace associated with the event. - * - * @param type + * + * @param type * the type of event - * @param message + * @param message * the message to log - * @param throwable + * @param throwable * the exception to be logged */ void error(EventType type, String message, Throwable throwable); @@ -275,30 +275,30 @@ public String toString() { /** * Allows the caller to determine if messages logged at this level * will be discarded, to avoid performing expensive processing. - * + * * @return true if error level messages will be output to the log */ boolean isErrorEnabled(); /** * Log a warning level security event if 'warning' level logging is enabled. - * - * @param type - * the type of event - * @param message + * + * @param type + * the type of event + * @param message * the message to log */ void warning(EventType type, String message); - + /** - * Log a warning level security event if 'warning' level logging is enabled + * Log a warning level security event if 'warning' level logging is enabled * and also record the stack trace associated with the event. - * - * @param type - * the type of event - * @param message + * + * @param type + * the type of event + * @param message * the message to log - * @param throwable + * @param throwable * the exception to be logged */ void warning(EventType type, String message, Throwable throwable); @@ -306,30 +306,30 @@ public String toString() { /** * Allows the caller to determine if messages logged at this level * will be discarded, to avoid performing expensive processing. - * + * * @return true if warning level messages will be output to the log */ boolean isWarningEnabled(); /** * Log an info level security event if 'info' level logging is enabled. - * - * @param type - * the type of event - * @param message + * + * @param type + * the type of event + * @param message * the message to log */ void info(EventType type, String message); - + /** - * Log an info level security event if 'info' level logging is enabled + * Log an info level security event if 'info' level logging is enabled * and also record the stack trace associated with the event. - * - * @param type + * + * @param type * the type of event - * @param message + * @param message * the message to log - * @param throwable + * @param throwable * the exception to be logged */ void info(EventType type, String message, Throwable throwable); @@ -337,30 +337,30 @@ public String toString() { /** * Allows the caller to determine if messages logged at this level * will be discarded, to avoid performing expensive processing. - * + * * @return true if info level messages will be output to the log */ boolean isInfoEnabled(); /** * Log a debug level security event if 'debug' level logging is enabled. - * - * @param type + * + * @param type * the type of event - * @param message + * @param message * the message to log */ void debug(EventType type, String message); - + /** - * Log a debug level security event if 'debug' level logging is enabled + * Log a debug level security event if 'debug' level logging is enabled * and also record the stack trace associated with the event. - * - * @param type + * + * @param type * the type of event - * @param message + * @param message * the message to log - * @param throwable + * @param throwable * the exception to be logged */ void debug(EventType type, String message, Throwable throwable); @@ -368,30 +368,30 @@ public String toString() { /** * Allows the caller to determine if messages logged at this level * will be discarded, to avoid performing expensive processing. - * + * * @return true if debug level messages will be output to the log */ boolean isDebugEnabled(); /** * Log a trace level security event if 'trace' level logging is enabled. - * - * @param type + * + * @param type * the type of event - * @param message + * @param message * the message to log */ void trace(EventType type, String message); - + /** - * Log a trace level security event if 'trace' level logging is enabled + * Log a trace level security event if 'trace' level logging is enabled * and also record the stack trace associated with the event. - * - * @param type - * the type of event - * @param message + * + * @param type + * the type of event + * @param message * the message to log - * @param throwable + * @param throwable * the exception to be logged */ void trace(EventType type, String message, Throwable throwable); @@ -399,7 +399,7 @@ public String toString() { /** * Allows the caller to determine if messages logged at this level * will be discarded, to avoid performing expensive processing. - * + * * @return true if trace level messages will be output to the log */ boolean isTraceEnabled(); @@ -408,25 +408,25 @@ public String toString() { * Log an event regardless of what logging level is enabled. *
    * Note that logging will not occur if the underlying logging implementation has logging disabled. - * - * @param type + * + * @param type * the type of event - * @param message + * @param message * the message to log */ void always(EventType type, String message); - + /** * Log an event regardless of what logging level is enabled * and also record the stack trace associated with the event. *
    * Note that logging will not occur if the underlying logging implementation has logging disabled. - * - * @param type - * the type of event - * @param message + * + * @param type + * the type of event + * @param message * the message to log - * @param throwable + * @param throwable * the exception to be logged */ void always(EventType type, String message, Throwable throwable); diff --git a/src/main/java/org/owasp/esapi/PreparedString.java b/src/main/java/org/owasp/esapi/PreparedString.java index d0695e4a5..5102a324c 100644 --- a/src/main/java/org/owasp/esapi/PreparedString.java +++ b/src/main/java/org/owasp/esapi/PreparedString.java @@ -1,15 +1,15 @@ /** * 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-2019 - 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 2009 */ @@ -21,19 +21,19 @@ /** * A parameterized string that uses escaping to make untrusted data safe before combining it with * a command or query intended for use in an interpreter. - *

     
    + * 
      * PreparedString div = new PreparedString( "<a href=\"http:\\\\example.com?id=?\" onmouseover=\"alert('?')\">test</a>", new HTMLEntityCodec() );
      * div.setURL( 1, request.getParameter( "url" ), new PercentCodec() );
      * div.set( 2, request.getParameter( "message" ), new JavaScriptCodec() );
      * out.println( div.toString() );
    - * 
    + *
      * // escaping for SQL
      * PreparedString query = new PreparedString( "SELECT * FROM users WHERE name='?' AND password='?'", new OracleCodec() );
      * query.set( 1, request.getParameter( "name" ) );
      * query.set( 2, request.getParameter( "pass" ) );
      * stmt.execute( query.toString() );
      * 
    - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 */ @@ -45,7 +45,7 @@ public class PreparedString { private final static char[] IMMUNE = {}; /** - * Create a PreparedString with the supplied template and Codec. The template should use the + * Create a PreparedString with the supplied template and Codec. The template should use the * default parameter placeholder character (?) in the place where actual parameters are to be inserted. * The supplied Codec will be used to escape characters in calls to set, unless a specific Codec is * provided to override it. @@ -89,9 +89,9 @@ private void split( String str, char c ) { parts.add( str.substring(index) ); parameters = new String[pcount]; } - + /** - * Set the parameter at index with supplied value using the default Codec to escape. + * Set the parameter at index with supplied value using the default Codec to escape. * @param index * @param value */ @@ -102,9 +102,9 @@ public void set( int index, String value ) { String encoded = codec.encode( IMMUNE, value ); parameters[index-1] = encoded; } - + /** - * Set the parameter at index with supplied value using the supplied Codec to escape. + * Set the parameter at index with supplied value using the supplied Codec to escape. * @param index * @param value * @param codec @@ -116,7 +116,7 @@ public void set( int index, String value, Codec codec ) { String encoded = codec.encode( IMMUNE, value ); parameters[index-1] = encoded; } - + /** * Render the PreparedString by combining the template with properly escaped parameters. */ diff --git a/src/main/java/org/owasp/esapi/PropNames.java b/src/main/java/org/owasp/esapi/PropNames.java index 33a5eb4e1..59deb8991 100644 --- a/src/main/java/org/owasp/esapi/PropNames.java +++ b/src/main/java/org/owasp/esapi/PropNames.java @@ -67,7 +67,7 @@ public final class PropNames { public static final String CANONICALIZATION_CODECS = "Encoder.DefaultCodecList"; public static final String DISABLE_INTRUSION_DETECTION = "IntrusionDetector.Disable"; - + public static final String MASTER_KEY = "Encryptor.MasterKey"; public static final String MASTER_SALT = "Encryptor.MasterSalt"; public static final String KEY_LENGTH = "Encryptor.EncryptionKeyLength"; diff --git a/src/main/java/org/owasp/esapi/Randomizer.java b/src/main/java/org/owasp/esapi/Randomizer.java index 1d991b164..bef0c4a1b 100644 --- a/src/main/java/org/owasp/esapi/Randomizer.java +++ b/src/main/java/org/owasp/esapi/Randomizer.java @@ -92,7 +92,7 @@ public interface Randomizer { /** * Returns an unguessable random filename with the specified extension. This method could call - * getRandomString(length, charset) from this Class with the desired length and alphanumerics as the charset + * getRandomString(length, charset) from this Class with the desired length and alphanumerics as the charset * then merely append "." + extension. * * @param extension @@ -123,7 +123,7 @@ public interface Randomizer { /** * Generates a random GUID. This method could use a hash of random Strings, the current time, - * and any other random data available. The format is a well-defined sequence of 32 hex digits + * and any other random data available. The format is a well-defined sequence of 32 hex digits * grouped into chunks of 8-4-4-4-12. *

    * For more information including algorithms used to create UUIDs, diff --git a/src/main/java/org/owasp/esapi/SafeFile.java b/src/main/java/org/owasp/esapi/SafeFile.java index fba5a94e7..e048e9419 100644 --- a/src/main/java/org/owasp/esapi/SafeFile.java +++ b/src/main/java/org/owasp/esapi/SafeFile.java @@ -1,15 +1,15 @@ /** * 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) 2008 - 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 Arshan Dabirsiaghi Aspect Security * @created 2008 */ @@ -31,8 +31,8 @@ public class SafeFile extends File { private static final long serialVersionUID = 1L; - private static final Pattern PERCENTS_PAT = Pattern.compile("(%)([0-9a-fA-F])([0-9a-fA-F])"); - private static final Pattern FILE_BLACKLIST_PAT = Pattern.compile("([\\\\/:*?<>|^])"); + private static final Pattern PERCENTS_PAT = Pattern.compile("(%)([0-9a-fA-F])([0-9a-fA-F])"); + private static final Pattern FILE_BLACKLIST_PAT = Pattern.compile("([\\\\/:*?<>|^])"); private static final Pattern DIR_BLACKLIST_PAT = Pattern.compile("([*?<>|^])"); public SafeFile(String path) throws ValidationException { @@ -59,7 +59,7 @@ public SafeFile(URI uri) throws ValidationException { doFileCheck(this.getName()); } - + private void doDirCheck(String path) throws ValidationException { Matcher m1 = DIR_BLACKLIST_PAT.matcher( path ); if ( null != m1 && m1.find() ) { @@ -70,13 +70,13 @@ private void doDirCheck(String path) throws ValidationException { if (null != m2 && m2.find() ) { throw new ValidationException( "Invalid directory", "Directory path (" + path + ") contains encoded characters: " + m2.group() ); } - + int ch = containsUnprintableCharacters(path); if (ch != -1) { throw new ValidationException("Invalid directory", "Directory path (" + path + ") contains unprintable character: " + ch); } } - + private void doFileCheck(String path) throws ValidationException { Matcher m1 = FILE_BLACKLIST_PAT.matcher( path ); if ( m1.find() ) { @@ -87,7 +87,7 @@ private void doFileCheck(String path) throws ValidationException { if ( m2.find() ) { throw new ValidationException( "Invalid file", "File path (" + path + ") contains encoded characters: " + m2.group() ); } - + int ch = containsUnprintableCharacters(path); if (ch != -1) { throw new ValidationException("Invalid file", "File path (" + path + ") contains unprintable character: " + ch); diff --git a/src/main/java/org/owasp/esapi/SecurityConfiguration.java b/src/main/java/org/owasp/esapi/SecurityConfiguration.java index 11f6454d5..564206de0 100644 --- a/src/main/java/org/owasp/esapi/SecurityConfiguration.java +++ b/src/main/java/org/owasp/esapi/SecurityConfiguration.java @@ -1,15 +1,15 @@ /** * 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 Mike Fauzy Aspect Security * @author Jeff Williams Aspect Security * @created 2007 @@ -45,7 +45,7 @@ *

    * The ESAPI reference implementation (DefaultSecurityConfiguration.java) does * not encrypt its properties file. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -54,107 +54,107 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { /** * Gets the application name, used for logging - * + * * @return the name of the current application * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getApplicationName(); - + /** * Returns the fully qualified classname of the ESAPI Logging implementation. * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getLogImplementation(); - + /** * Returns the fully qualified classname of the ESAPI Authentication implementation. * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getAuthenticationImplementation(); - + /** * Returns the fully qualified classname of the ESAPI Encoder implementation. * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getEncoderImplementation(); - + /** * Returns the fully qualified classname of the ESAPI Access Control implementation. * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getAccessControlImplementation(); - + /** * Returns the fully qualified classname of the ESAPI Intrusion Detection implementation. * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getIntrusionDetectionImplementation(); - + /** * Returns the fully qualified classname of the ESAPI Randomizer implementation. * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getRandomizerImplementation(); - + /** * Returns the fully qualified classname of the ESAPI Encryption implementation. * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getEncryptionImplementation(); - + /** * Returns the fully qualified classname of the ESAPI Validation implementation. * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getValidationImplementation(); - + /** * Returns the validation pattern for a particular type * @param typeName * @return the validation pattern */ Pattern getValidationPattern( String typeName ); - + /** * Determines whether ESAPI will accept "lenient" dates when attempt * to parse dates. Controlled by ESAPI property * {@code Validator.AcceptLenientDates}, which defaults to {@code false} * if unset. - * + * * @return True if lenient dates are accepted; false otherwise. * @see java.text.DateFormat#setLenient(boolean) * @deprecated Use SecurityConfiguration.getBooleanProp("appropriate_esapi_prop_name") instead. */ @Deprecated boolean getLenientDatesAccepted(); - + /** * Returns the fully qualified classname of the ESAPI OS Execution implementation. * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getExecutorImplementation(); - + /** * Returns the fully qualified classname of the ESAPI HTTPUtilities implementation. * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getHTTPUtilitiesImplementation(); - + /** * Gets the master key. This password is used to encrypt/decrypt other files or types * of data that need to be protected by your application. - * + * * @return the current master key * @deprecated Use SecurityConfiguration.getByteArrayProp("appropriate_esapi_prop_name") instead. */ @@ -166,7 +166,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { * @return the upload directory */ File getUploadDirectory(); - + /** * Retrieves the temp directory to use when uploading files, as specified in ESAPI.properties. * @return the temp directory @@ -180,17 +180,17 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { * ciphers supporting multiple key sizes. (Note that there is also an Encryptor.MinEncryptionKeyLength, * which is the minimum key size (in bits) that ESAPI will support * for encryption. (There is no miminimum for decryption.) - * + * * @return the key length (in bits) * @deprecated Use SecurityConfiguration.getIntProp("appropriate_esapi_prop_name") instead. */ @Deprecated int getEncryptionKeyLength(); - + /** - * Gets the master salt that is used to salt stored password hashes and any other location + * Gets the master salt that is used to salt stored password hashes and any other location * where a salt is needed. - * + * * @return the current master salt * @deprecated Use SecurityConfiguration.getByteArrayProp("appropriate_esapi_prop_name") instead. */ @@ -199,21 +199,21 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { /** * Gets the allowed executables to run with the Executor. - * + * * @return a list of the current allowed file extensions */ List getAllowedExecutables(); /** * Gets the allowed file extensions for files that are uploaded to this application. - * + * * @return a list of the current allowed file extensions */ List getAllowedFileExtensions(); /** * Gets the maximum allowed file upload size. - * + * * @return the current allowed file upload size * @deprecated Use SecurityConfiguration.getIntProp("appropriate_esapi_prop_name") instead. */ @@ -222,7 +222,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { /** * Gets the name of the password parameter used during user authentication. - * + * * @return the name of the password parameter * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @@ -231,7 +231,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { /** * Gets the name of the username parameter used during user authentication. - * + * * @return the name of the username parameter * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @@ -243,7 +243,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { * mostly used for compatibility with ESAPI 1.4; ESAPI 2.0 prefers to * use "cipher transformation" since it supports multiple cipher modes * and padding schemes. - * + * * @return the current encryption algorithm * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @@ -267,7 +267,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { * actual block size. When requesting such a mode, you may optionally * specify the number of bits to be processed at a time. This generally must * be an integral multiple of 8-bits so that it can specify a whole number - * of octets. + * of octets. *

    * Examples are: *

    @@ -293,13 +293,13 @@ public interface SecurityConfiguration extends EsapiPropertyLoader {
          */
         @Deprecated
         String getCipherTransformation();
    -    
    +
         /**
          * Set the cipher transformation. This allows a different cipher transformation
          * to be used without changing the {@code ESAPI.properties} file. For instance
          * you may normally want to use AES/CBC/PKCS5Padding, but have some legacy
          * encryption where you have ciphertext that was encrypted using 3DES.
    -     * 
    +     *
          * @param cipherXform    The new cipher transformation. See
          *                         {@link #getCipherTransformation} for format. If
          *                         {@code null} is passed as the parameter, the cipher
    @@ -342,7 +342,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader {
          */
         @Deprecated
         String getPreferredJCEProvider();
    -    
    +
     // TODO - DISCUSS: Where should this web page (below) go? Maybe with the Javadoc? But where?
     //                   Think it makes more sense as part of the release notes, but OTOH, I
     //                   really don't want to rewrite this as a Wiki page either.
    @@ -379,7 +379,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader {
          */
         @Deprecated
         boolean overwritePlainText();
    -    
    +
         /**
          * Get a string indicating how to compute an Initialization Vector (IV).
          * Currently supported modes are "random" to generate a random IV or
    @@ -393,17 +393,17 @@ public interface SecurityConfiguration extends EsapiPropertyLoader {
          * since release 2.2.0.0). An ESAPI.properties value of {@code fixed} for the property
          * {@code Encryptor.ChooseIVMethod} will now result in a {@code ConfigurationException}
          * being thrown.
    -     * 
    +     *
          * @return A string specifying the IV type. Should be "random". Anything
          * else should fail with a {@code ConfigurationException} being thrown.
    -     * 
    +     *
          * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead.
          *             This method will be removed in a future release as it is now moot since
          *             it can only legitimately have the single value of "random".
          */
         @Deprecated
         String getIVType();
    -    
    +
         /**
          * Return a {@code List} of strings of combined cipher modes that support
          * both confidentiality and authenticity. These would be preferred
    @@ -415,7 +415,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader {
          * The list is taken from the comma-separated list of cipher modes specified
          * by the ESAPI property
          * {@code Encryptor.cipher_modes.combined_modes}.
    -     * 
    +     *
          * @return The parsed list of comma-separated cipher modes if the property
          * was specified in {@code ESAPI.properties}; otherwise the empty list is
          * returned.
    @@ -431,7 +431,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader {
          * The list is taken from the comma-separated list of cipher modes specified
          * by the ESAPI property
          * {@code Encryptor.cipher_modes.additional_allowed}.
    -     * 
    +     *
          * @return The parsed list of comma-separated cipher modes if the property
          * was specified in {@code ESAPI.properties}; otherwise the empty list is
          * returned.
    @@ -442,7 +442,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader {
     
         /**
          * Gets the hashing algorithm used by ESAPI to hash data.
    -     * 
    +     *
          * @return the current hashing algorithm
          * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead.
          */
    @@ -451,7 +451,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader {
     
         /**
          * Gets the hash iterations used by ESAPI to hash data.
    -     * 
    +     *
          * @return the current hashing algorithm
          * @deprecated Use SecurityConfiguration.getIntProp("appropriate_esapi_prop_name") instead.
          */
    @@ -461,22 +461,22 @@ public interface SecurityConfiguration extends EsapiPropertyLoader {
         /**
          * Retrieve the Pseudo Random Function (PRF) used by the ESAPI
          * Key Derivation Function (KDF).
    -     * 
    +     *
          * @return    The KDF PRF algorithm name.
          * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead.
          */
         @Deprecated
         String getKDFPseudoRandomFunction();
    -    
    +
         /**
          * Gets the character encoding scheme supported by this application. This is used to set the
          * character encoding scheme on requests and responses when setCharacterEncoding() is called
    -     * on SafeRequests and SafeResponses. This scheme is also used for encoding/decoding URLs 
    +     * on SafeRequests and SafeResponses. This scheme is also used for encoding/decoding URLs
          * and any other place where the current encoding scheme needs to be known.
          * 

    - * Note: This does not get the configured response content type. That is accessed by calling + * Note: This does not get the configured response content type. That is accessed by calling * getResponseContentType(). - * + * * @return the current character encoding scheme * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @@ -503,14 +503,14 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { /** * Returns the List of Codecs to use when canonicalizing data - * + * * @return the codec list */ List getDefaultCanonicalizationCodecs(); /** * Gets the digital signature algorithm used by ESAPI to generate and verify signatures. - * + * * @return the current digital signature algorithm * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @@ -519,16 +519,16 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { /** * Gets the digital signature key length used by ESAPI to generate and verify signatures. - * + * * @return the current digital signature key length * @deprecated Use SecurityConfiguration.getIntProp("appropriate_esapi_prop_name") instead. */ @Deprecated int getDigitalSignatureKeyLength(); - + /** * Gets the random number generation algorithm used to generate random numbers where needed. - * + * * @return the current random number generation algorithm * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @@ -536,9 +536,9 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { String getRandomAlgorithm(); /** - * Gets the number of login attempts allowed before the user's account is locked. If this + * Gets the number of login attempts allowed before the user's account is locked. If this * many failures are detected within the alloted time period, the user's account will be locked. - * + * * @return the number of failed login attempts that cause an account to be locked * @deprecated Use SecurityConfiguration.getIntProp("appropriate_esapi_prop_name") instead. */ @@ -546,10 +546,10 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { int getAllowedLoginAttempts(); /** - * Gets the maximum number of old password hashes that should be retained. These hashes can + * Gets the maximum number of old password hashes that should be retained. These hashes can * be used to ensure that the user doesn't reuse the specified number of previous passwords * when they change their password. - * + * * @return the number of old hashed passwords to retain * @deprecated Use SecurityConfiguration.getIntProp("appropriate_esapi_prop_name") instead. */ @@ -558,18 +558,18 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { /** * Allows for complete disabling of all intrusion detection mechanisms - * + * * @return true if intrusion detection should be disabled * @deprecated Use SecurityConfiguration.getBooleanProp("appropriate_esapi_prop_name") instead. */ @Deprecated boolean getDisableIntrusionDetection(); - + /** * Gets the intrusion detection quota for the specified event. - * + * * @param eventName the name of the event whose quota is desired - * + * * @return the Quota that has been configured for the specified type of event */ Threshold getQuota(String eventName); @@ -581,7 +581,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { * @return A {@code File} object representing the specified file name or null if not found. */ File getResourceFile( String filename ); - + /** * Returns true if session cookies are required to have HttpOnly flag set. * @deprecated Use SecurityConfiguration.getBooleanProp("appropriate_esapi_prop_name") instead. @@ -628,17 +628,17 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { /** * Sets the ESAPI resource directory. - * + * * @param dir The location of the resource directory. */ void setResourceDirectory(String dir); - + /** * Gets the content type for responses used when setSafeContentType() is called. *

    - * Note: This does not get the configured character encoding scheme. That is accessed by calling + * Note: This does not get the configured character encoding scheme. That is accessed by calling * getCharacterEncoding(). - * + * * @return The current content-type set for responses. * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @@ -646,60 +646,60 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { String getResponseContentType(); /** - * This method returns the configured name of the session identifier, + * This method returns the configured name of the session identifier, * likely "JSESSIONID" though this can be overridden. - * + * * @return The name of the session identifier, like "JSESSIONID" * @deprecated Use SecurityConfiguration.getStringProp("appropriate_esapi_prop_name") instead. */ @Deprecated String getHttpSessionIdName(); - + /** * Gets the length of the time to live window for remember me tokens (in milliseconds). - * + * * @return The time to live length for generated "remember me" tokens. */ // OPEN ISSUE: Can we replace w/ SecurityConfiguration.getIntProp("appropriate_esapi_prop_name") instead? long getRememberTokenDuration(); - + /** * Gets the idle timeout length for sessions (in milliseconds). This is the amount of time that a session * can live before it expires due to lack of activity. Applications or frameworks could provide a reauthenticate * function that enables a session to continue after reauthentication. - * + * * @return The session idle timeout length. * @deprecated Use SecurityConfiguration.getIntProp("appropriate_esapi_prop_name") instead. */ @Deprecated int getSessionIdleTimeoutLength(); - + /** * Gets the absolute timeout length for sessions (in milliseconds). This is the amount of time that a session - * can live before it expires regardless of the amount of user activity. Applications or frameworks could + * can live before it expires regardless of the amount of user activity. Applications or frameworks could * provide a reauthenticate function that enables a session to continue after reauthentication. - * + * * @return The session absolute timeout length. * @deprecated Use SecurityConfiguration.getIntProp("appropriate_esapi_prop_name") instead. */ @Deprecated int getSessionAbsoluteTimeoutLength(); - - + + /** * Returns whether HTML entity encoding should be applied to log entries. - * + * * @return True if log entries are to be HTML Entity encoded. False otherwise. * @deprecated Use SecurityConfiguration.getBooleanProp("appropriate_esapi_prop_name") instead. */ @Deprecated boolean getLogEncodingRequired(); - + /** * Returns whether ESAPI should log the application name. This might be clutter in some * single-server/single-app environments. - * + * * @return True if ESAPI should log the application name, False otherwise * @deprecated Use SecurityConfiguration.getBooleanProp("appropriate_esapi_prop_name") instead. */ @@ -709,7 +709,7 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { /** * Returns whether ESAPI should log the server IP. This might be clutter in some * single-server environments. - * + * * @return True if ESAPI should log the server IP and port, False otherwise * @deprecated Use SecurityConfiguration.getBooleanProp("appropriate_esapi_prop_name") instead. */ @@ -717,35 +717,35 @@ public interface SecurityConfiguration extends EsapiPropertyLoader { boolean getLogServerIP(); /** - * Models a simple threshold as a count and an interval, along with a set of actions to take if + * Models a simple threshold as a count and an interval, along with a set of actions to take if * the threshold is exceeded. These thresholds are used to define when the accumulation of a particular event * has met a set number within the specified time period. Once a threshold value has been met, various * actions can be taken at that point. */ class Threshold { - + /** The name of this threshold. */ public String name = null; - + /** The count at which this threshold is triggered. */ public int count = 0; - - /** + + /** * The time frame within which 'count' number of actions has to be detected in order to * trigger this threshold. */ public long interval = 0; - + /** - * The list of actions to take if the threshold is met. It is expected that this is a list of Strings, but - * your implementation could have this be a list of any type of 'actions' you wish to define. + * The list of actions to take if the threshold is met. It is expected that this is a list of Strings, but + * your implementation could have this be a list of any type of 'actions' you wish to define. */ public List actions = null; /** * Constructs a threshold that is composed of its name, its threshold count, the time window for * the threshold, and the actions to take if the threshold is triggered. - * + * * @param name The name of this threshold. * @param count The count at which this threshold is triggered. * @param interval The time frame within which 'count' number of actions has to be detected in order to diff --git a/src/main/java/org/owasp/esapi/StringUtilities.java b/src/main/java/org/owasp/esapi/StringUtilities.java index 19a29f7c9..55f8c55a3 100644 --- a/src/main/java/org/owasp/esapi/StringUtilities.java +++ b/src/main/java/org/owasp/esapi/StringUtilities.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -20,7 +20,7 @@ /** * String utilities used in various filters. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -31,9 +31,9 @@ public class StringUtilities { public static String replaceLinearWhiteSpace( String input ) { return p.matcher(input).replaceAll( " " ); } - + /** - * Removes all unprintable characters from a string + * Removes all unprintable characters from a string * and replaces with a space. * @param input * @return the stripped value @@ -51,16 +51,16 @@ public static String stripControls( String input ) { return sb.toString(); } - + /** * Union multiple character arrays. - * + * * @param list the char[]s to union * @return the union of the char[]s */ public static char[] union(char[]... list) { StringBuilder sb = new StringBuilder(); - + for (char[] characters : list) { for ( char c : characters ) { if ( !contains( sb, c ) ) diff --git a/src/main/java/org/owasp/esapi/User.java b/src/main/java/org/owasp/esapi/User.java index 8e46a97e2..fa30ca3ba 100644 --- a/src/main/java/org/owasp/esapi/User.java +++ b/src/main/java/org/owasp/esapi/User.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -34,7 +34,7 @@ * number of reasons, most commonly because they have failed login for too many times. Finally, the account can expire * after the expiration date has been reached. The User must be enabled, not expired, and unlocked in order to pass * authentication. - * + * * @author Jeff Williams at Aspect Security * @author Chris Schmidt (chrisisbeef .at. gmail.com) Digital Ritual Software * @since June 1, 2007 @@ -53,22 +53,22 @@ public interface User extends Principal, Serializable { /** * Adds a role to this user's account. - * - * @param role + * + * @param role * the role to add - * - * @throws AuthenticationException + * + * @throws AuthenticationException * the authentication exception */ void addRole(String role) throws AuthenticationException; /** * Adds a set of roles to this user's account. - * - * @param newRoles + * + * @param newRoles * the new roles to add - * - * @throws AuthenticationException + * + * @throws AuthenticationException * the authentication exception */ void addRoles(Set newRoles) throws AuthenticationException; @@ -76,17 +76,17 @@ public interface User extends Principal, Serializable { /** * Sets the user's password, performing a verification of the user's old password, the equality of the two new * passwords, and the strength of the new password. - * - * @param oldPassword + * + * @param oldPassword * the old password - * @param newPassword1 + * @param newPassword1 * the new password - * @param newPassword2 + * @param newPassword2 * the new password - used to verify that the new password was typed correctly - * - * @throws AuthenticationException - * if newPassword1 does not match newPassword2, if oldPassword does not match the stored old password, or if the new password does not meet complexity requirements - * @throws EncryptionException + * + * @throws AuthenticationException + * if newPassword1 does not match newPassword2, if oldPassword does not match the stored old password, or if the new password does not meet complexity requirements + * @throws EncryptionException */ void changePassword(String oldPassword, String newPassword1, String newPassword2) throws AuthenticationException, EncryptionException; @@ -102,21 +102,21 @@ public interface User extends Principal, Serializable { /** * Gets this user's account id number. - * + * * @return the account id */ long getAccountId(); - + /** * Gets this user's account name. - * + * * @return the account name */ String getAccountName(); /** * Gets the CSRF token for this user's current sessions. - * + * * @return the CSRF token */ String getCSRFToken(); @@ -133,7 +133,7 @@ public interface User extends Principal, Serializable { * intended to be used as a part of the account lockout feature, to help protect against brute force attacks. * However, the implementor should be aware that lockouts can be used to prevent access to an application by a * legitimate user, and should consider the risk of denial of service. - * + * * @return the number of failed login attempts since the last successful login */ int getFailedLoginCount(); @@ -141,7 +141,7 @@ public interface User extends Principal, Serializable { /** * Returns the last host address used by the user. This will be used in any log messages generated by the processing * of this request. - * + * * @return the last host address used by the user */ String getLastHostAddress(); @@ -149,10 +149,10 @@ public interface User extends Principal, Serializable { /** * Returns the date of the last failed login time for a user. This date should be used in a message to users after a * successful login, to notify them of potential attack activity on their account. - * + * * @return date of the last failed login - * - * @throws AuthenticationException + * + * @throws AuthenticationException * the authentication exception */ Date getLastFailedLoginTime() throws AuthenticationException; @@ -160,54 +160,54 @@ public interface User extends Principal, Serializable { /** * Returns the date of the last successful login time for a user. This date should be used in a message to users * after a successful login, to notify them of potential attack activity on their account. - * + * * @return date of the last successful login */ Date getLastLoginTime(); /** * Gets the date of user's last password change. - * + * * @return the date of last password change */ Date getLastPasswordChangeTime(); /** * Gets the roles assigned to a particular account. - * + * * @return an immutable set of roles */ Set getRoles(); /** * Gets the screen name (alias) for the current user. - * + * * @return the screen name */ String getScreenName(); /** * Adds a session for this User. - * + * * @param s * The session to associate with this user. */ void addSession( HttpSession s ); - + /** * Removes a session for this User. - * + * * @param s * The session to remove from being associated with this user. */ void removeSession( HttpSession s ); - + /** * Returns a Set containing the sessions associated with this User. * @return The Set of sessions for this User. */ Set getSessions(); - + /** * Increment failed login count. */ @@ -215,70 +215,70 @@ public interface User extends Principal, Serializable { /** * Checks if user is anonymous. - * + * * @return true, if user is anonymous */ boolean isAnonymous(); /** * Checks if this user's account is currently enabled. - * - * @return true, if account is enabled + * + * @return true, if account is enabled */ boolean isEnabled(); /** * Checks if this user's account is expired. - * + * * @return true, if account is expired */ boolean isExpired(); /** * Checks if this user's account is assigned a particular role. - * - * @param role + * + * @param role * the role for which to check - * + * * @return true, if role has been assigned to user */ boolean isInRole(String role); /** * Checks if this user's account is locked. - * + * * @return true, if account is locked */ boolean isLocked(); /** * Tests to see if the user is currently logged in. - * + * * @return true, if the user is logged in */ boolean isLoggedIn(); /** - * Tests to see if this user's session has exceeded the absolute time out based + * Tests to see if this user's session has exceeded the absolute time out based * on ESAPI's configuration settings. - * + * * @return true, if user's session has exceeded the absolute time out */ boolean isSessionAbsoluteTimeout(); /** - * Tests to see if the user's session has timed out from inactivity based + * Tests to see if the user's session has timed out from inactivity based * on ESAPI's configuration settings. - * - * A session may timeout prior to ESAPI's configuration setting due to - * the servlet container setting for session-timeout in web.xml. The - * following is an example of a web.xml session-timeout set for one hour. + * + * A session may timeout prior to ESAPI's configuration setting due to + * the servlet container setting for session-timeout in web.xml. The + * following is an example of a web.xml session-timeout set for one hour. * * - * 60 + * 60 * - * - * @return true, if user's session has timed out from inactivity based + * + * @return true, if user's session has timed out from inactivity based * on ESAPI configuration */ boolean isSessionTimeout(); @@ -290,10 +290,10 @@ public interface User extends Principal, Serializable { /** * Login with password. - * - * @param password + * + * @param password * the password - * @throws AuthenticationException + * @throws AuthenticationException * if login fails */ void loginWithPassword(String password) throws AuthenticationException; @@ -305,10 +305,10 @@ public interface User extends Principal, Serializable { /** * Removes a role from this user's account. - * - * @param role + * + * @param role * the role to remove - * @throws AuthenticationException + * @throws AuthenticationException * the authentication exception */ void removeRole(String role) throws AuthenticationException; @@ -318,42 +318,42 @@ public interface User extends Principal, Serializable { * forms. The application should verify that all requests contain the token, or they may have been generated by a * CSRF attack. It is generally best to perform the check in a centralized location, either a filter or controller. * See the verifyCSRFToken method. - * + * * @return the new CSRF token - * - * @throws AuthenticationException + * + * @throws AuthenticationException * the authentication exception */ String resetCSRFToken() throws AuthenticationException; /** * Sets this user's account name. - * + * * @param accountName the new account name */ void setAccountName(String accountName); /** * Sets the date and time when this user's account will expire. - * + * * @param expirationTime the new expiration time */ void setExpirationTime(Date expirationTime); /** * Sets the roles for this account. - * - * @param roles + * + * @param roles * the new roles - * - * @throws AuthenticationException + * + * @throws AuthenticationException * the authentication exception */ void setRoles(Set roles) throws AuthenticationException; /** * Sets the screen name (username alias) for this user. - * + * * @param screenName the new screen name */ void setScreenName(String screenName); @@ -367,40 +367,40 @@ public interface User extends Principal, Serializable { * Verify that the supplied password matches the password for this user. This method * is typically used for "reauthentication" for the most sensitive functions, such * as transactions, changing email address, and changing other account information. - * - * @param password + * + * @param password * the password that the user entered - * + * * @return true, if the password passed in matches the account's password - * - * @throws EncryptionException + * + * @throws EncryptionException */ boolean verifyPassword(String password) throws EncryptionException; /** * Set the time of the last failed login for this user. - * + * * @param lastFailedLoginTime the date and time when the user just failed to login correctly. */ void setLastFailedLoginTime(Date lastFailedLoginTime); - + /** * Set the last remote host address used by this user. - * + * * @param remoteHost The address of the user's current source host. */ void setLastHostAddress(String remoteHost) throws AuthenticationHostException; - + /** * Set the time of the last successful login for this user. - * + * * @param lastLoginTime the date and time when the user just successfully logged in. */ void setLastLoginTime(Date lastLoginTime); - + /** * Set the time of the last password change for this user. - * + * * @param lastPasswordChangeTime the date and time when the user just successfully changed his/her password. */ void setLastPasswordChangeTime(Date lastPasswordChangeTime); @@ -410,7 +410,7 @@ public interface User extends Principal, Serializable { * IntrusionDetector. */ HashMap getEventMap(); - + /** * The ANONYMOUS user is used to represent an unidentified user. Since there is @@ -424,7 +424,7 @@ public interface User extends Principal, Serializable { private String csrfToken = ""; private Set sessions = new HashSet(); private Locale locale = null; - + /** * {@inheritDoc} */ @@ -478,13 +478,13 @@ public String getAccountName() { /** * Alias method that is equivalent to getAccountName() - * + * * @return the name of the current user's account */ public String getName() { return getAccountName(); } - + /** * {@inheritDoc} */ @@ -680,7 +680,7 @@ public void setAccountName(String accountName) { public void setExpirationTime(Date expirationTime) { throw new RuntimeException("Invalid operation for the anonymous user"); } - + /** * {@inheritDoc} */ @@ -715,7 +715,7 @@ public boolean verifyPassword(String password) throws EncryptionException { public void setLastFailedLoginTime(Date lastFailedLoginTime) { throw new RuntimeException("Invalid operation for the anonymous user"); } - + /** * {@inheritDoc} */ @@ -729,14 +729,14 @@ public void setLastLoginTime(Date lastLoginTime) { public void setLastHostAddress(String remoteHost) { throw new RuntimeException("Invalid operation for the anonymous user"); } - + /** * {@inheritDoc} */ public void setLastPasswordChangeTime(Date lastPasswordChangeTime) { throw new RuntimeException("Invalid operation for the anonymous user"); } - + /** * {@inheritDoc} */ diff --git a/src/main/java/org/owasp/esapi/ValidationErrorList.java b/src/main/java/org/owasp/esapi/ValidationErrorList.java index 0837f0d32..a56ae1eec 100644 --- a/src/main/java/org/owasp/esapi/ValidationErrorList.java +++ b/src/main/java/org/owasp/esapi/ValidationErrorList.java @@ -1,17 +1,17 @@ /** * 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; @@ -23,13 +23,13 @@ import org.owasp.esapi.errors.ValidationException; /** - * The ValidationErrorList class defines a well-formed collection of - * ValidationExceptions so that groups of validation functions can be + * The ValidationErrorList class defines a well-formed collection of + * ValidationExceptions so that groups of validation functions can be * called in a non-blocking fashion. *

    - * To use the ValidationErrorList to execute groups of validation + * To use the ValidationErrorList to execute groups of validation * attempts, your controller code would look something like: - * + * *

      * ValidationErrorList() errorList = new ValidationErrorList();.
      * String name  = getValidInput("Name", form.getName(), "SomeESAPIRegExName1", 255, false, errorList);
    @@ -38,12 +38,12 @@
      * Integer sortOrder = getValidInteger("Sort Order", form.getSortOrder(), -100000, +100000, false, errorList);
      * request.setAttribute( "ERROR_LIST", errorList );
      * 
    - * + * * The at your view layer you would be able to retrieve all * of your error messages via a helper function like: - * + * *
    - * public static ValidationErrorList getErrors() {          
    + * public static ValidationErrorList getErrors() {
      *     HttpServletRequest request = ESAPI.httpUtilities().getCurrentRequest();
      *     ValidationErrorList errors = new ValidationErrorList();
      *     if (request.getAttribute(Constants.ERROR_LIST) != null) {
    @@ -52,9 +52,9 @@
      *        return errors;
      * }
      * 
    - * + * * You can list all errors like: - * + * *
      * <%
      *      for (Object vo : errorList.errors()) {
    @@ -65,13 +65,13 @@
      *     }
      * %>
      * 
    - * + * * And even check if a specific UI component is in error via calls like: - * + * *
      * ValidationException e = errorList.getError("Name");
      * 
    - * + * * @author Jim Manico (jim@manico.net) Manico.net * @since August 15, 2008 */ @@ -84,9 +84,9 @@ public class ValidationErrorList { /** * Adds a new error to list with a unique named context. - * No action taken if either element is null. + * No action taken if either element is null. * Existing contexts will be overwritten. - * + * * @param context Unique named context for this {@code ValidationErrorList}. * @param vex A {@code ValidationException}. */ @@ -99,7 +99,7 @@ public void addError(String context, ValidationException vex) { /** * Returns list of ValidationException, or empty list of no errors exist. - * + * * @return List */ public List errors() { @@ -108,27 +108,27 @@ public List errors() { /** * Retrieves ValidationException for given context if one exists. - * + * * @param context unique name for each error * @return ValidationException or null for given context */ public ValidationException getError(String context) { - if (context == null) return null; + if (context == null) return null; return errorList.get(context); } /** * Returns true if no error are present. - * + * * @return boolean */ public boolean isEmpty() { return errorList.isEmpty(); } - + /** * Returns the numbers of errors present. - * + * * @return boolean */ public int size() { diff --git a/src/main/java/org/owasp/esapi/ValidationRule.java b/src/main/java/org/owasp/esapi/ValidationRule.java index 985bb169c..3f9c3d42f 100644 --- a/src/main/java/org/owasp/esapi/ValidationRule.java +++ b/src/main/java/org/owasp/esapi/ValidationRule.java @@ -8,7 +8,7 @@ public interface ValidationRule { /** * Parse the input, throw exceptions if validation fails - * + * * @param context * for logging * @param input @@ -33,7 +33,7 @@ Object getValid(String context, String input) * Whether or not a valid valid can be null. {@code getValid} will throw an * Exception and {#code getSafe} will return the default value if flag is set to * true - * + * * @param flag * whether or not null values are valid/safe */ @@ -56,7 +56,7 @@ Object getValid(String context, String input) void setEncoder(Encoder encoder); /** - * Check if the input is valid, throw an Exception otherwise + * Check if the input is valid, throw an Exception otherwise */ void assertValid(String context, String input) throws ValidationException; @@ -72,7 +72,7 @@ Object getValid(String context, String input, * finally return a default value. */ Object getSafe(String context, String input); - + /** * @return true if the input passes validation */ @@ -82,7 +82,7 @@ Object getValid(String context, String input, * String the input of all chars contained in the list */ String whitelist(String input, char[] list); - + /** * String the input of all chars contained in the list */ diff --git a/src/main/java/org/owasp/esapi/Validator.java b/src/main/java/org/owasp/esapi/Validator.java index 0312266aa..df7d035ad 100644 --- a/src/main/java/org/owasp/esapi/Validator.java +++ b/src/main/java/org/owasp/esapi/Validator.java @@ -63,7 +63,7 @@ public interface Validator { *

    * Calls {@link #getValidInput(String, String, String, int, boolean, boolean)} with {@code canonicalize=true} * and returns true if no exceptions are thrown. - * + * * @throws IntrusionException Input likely indicates an attack. */ boolean isValidInput(String context, String input, String type, int maxLength, boolean allowNull) throws IntrusionException; @@ -615,7 +615,7 @@ public interface Validator { * and input that is clearly an attack will generate a descriptive IntrusionException. * * @param context - * A descriptive name of the parameter that you are validating (e.g., LoginPage_UsernameField). + * A descriptive name of the parameter that you are validating (e.g., LoginPage_UsernameField). * This value is used by any logging or error handling that is done with respect to the value passed in. * @param input * The actual input data to validate. @@ -1037,10 +1037,10 @@ public interface Validator { /** * Parses and ensures that the URI in question is a valid RFC-3986 URI. This simplifies - * the kind of regex required for subsequent validation to mitigate regex-based DoS attacks. - * + * the kind of regex required for subsequent validation to mitigate regex-based DoS attacks. + * * @see RFC-3986. - * + * * @param context * A descriptive name of the parameter that you are validating (e.g., LoginPage_UsernameField). * This value is used by any logging or error handling that is done with respect to the value passed in. @@ -1056,11 +1056,11 @@ public interface Validator { /** * Will return a {@code URI} object that will represent a fully parsed and legal URI - * as specified in RFC-3986. - * + * as specified in RFC-3986. + * * @param input String - * @return URI object representing a parsed URI, or {@code null} if the URI was non-compliant in some way. + * @return URI object representing a parsed URI, or {@code null} if the URI was non-compliant in some way. */ URI getRfcCompliantURI(String input); - + } diff --git a/src/main/java/org/owasp/esapi/codecs/AbstractCharacterCodec.java b/src/main/java/org/owasp/esapi/codecs/AbstractCharacterCodec.java index 4b366f5cf..8595cb6e1 100644 --- a/src/main/java/org/owasp/esapi/codecs/AbstractCharacterCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/AbstractCharacterCodec.java @@ -1,18 +1,18 @@ /** * 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) 2017 - 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 Matt Seil (mseil .at. owasp.org) * @created 2017 - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @created 2007 @@ -21,9 +21,9 @@ package org.owasp.esapi.codecs; /** - * - * This abstract Impl is broken off from the original {@code Codec} class and - * provides the {@code Character} parsing logic that has been with ESAPI from the beginning. + * + * This abstract Impl is broken off from the original {@code Codec} class and + * provides the {@code Character} parsing logic that has been with ESAPI from the beginning. * */ public abstract class AbstractCharacterCodec extends AbstractCodec { diff --git a/src/main/java/org/owasp/esapi/codecs/AbstractCodec.java b/src/main/java/org/owasp/esapi/codecs/AbstractCodec.java index 969bf791c..dccc3f491 100644 --- a/src/main/java/org/owasp/esapi/codecs/AbstractCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/AbstractCodec.java @@ -1,15 +1,15 @@ /** * 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) 2017 - 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 Matt Seil (mseil .at. owasp.org) * @created 2017 */ @@ -26,7 +26,7 @@ * Be sure to see the several WARNINGs associated with the detailed * method descriptions. You will not find that in the "Method Summary" section * of the javadoc because that only shows the intial sentence. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @param @@ -58,11 +58,11 @@ public AbstractCodec() { /** * {@inheritDoc} *

    - * WARNING!! {@code Character} based {@code Codec}s will silently transform code points that are not - * legal UTF code points into garbage data as they will cast them to {@code char}s. + * WARNING!! {@code Character} based {@code Codec}s will silently transform code points that are not + * legal UTF code points into garbage data as they will cast them to {@code char}s. * Also, if you are implementing an {@code Integer} based codec, these will be silently discarded * based on the return from {@code Character.isValidCodePoint( int )}. This is the preferred - * behavior moving forward. + * behavior moving forward. */ @Override public String encode(char[] immune, String input) { @@ -73,7 +73,7 @@ public String encode(char[] immune, String input) { //We can then safely cast this to char and maintain legacy behavior. sb.append(encodeCharacter(immune, new Character((char) point))); } else { - sb.append(encodeCharacter(immune, point)); + sb.append(encodeCharacter(immune, point)); } offset += Character.charCount(point); } @@ -83,7 +83,7 @@ public String encode(char[] immune, String input) { /** * {@inheritDoc} *

    - * WARNING!!!! Passing a standard {@code char} rather than {@code Character} to this method will resolve to the + * WARNING!!!! Passing a standard {@code char} rather than {@code Character} to this method will resolve to the * {@link #encodeCharacter( char[], char )} method, which will throw an {@code IllegalArgumentException} instead. * YOU HAVE BEEN WARNED!!!! */ @@ -91,13 +91,13 @@ public String encode(char[] immune, String input) { public String encodeCharacter( char[] immune, Character c ) { return ""+c; } - + /** * To prevent accidental footgun usage and calling * {@link #encodeCharacter( char[], int)} when called with {@code char} and * {@code char} is first silently converted to {@code int} and then the - * unexpected method is called. + * unexpected method is called. * * @throws IllegalArgumentException to indicate that you called the incorrect method. */ @@ -105,7 +105,7 @@ public String encodeCharacter(char[] immune, char c) { throw new IllegalArgumentException("You tried to call encodeCharacter() with a char. Nope. " + "Use 'encodeCharacter( char[] immune, Character c)' instead!"); } - + /* (non-Javadoc) * @see org.owasp.esapi.codecs.Codec#encodeCharacter(char[], int) */ @@ -136,7 +136,7 @@ public String getHexForNonAlphanumeric(char c) { return hex[c]; return toHex(c); } - + /** * {@inheritDoc} */ @@ -155,7 +155,7 @@ public String toOctal(char c) { public String toHex(char c) { return Integer.toHexString(c); } - + public String toHex(int c) { return Integer.toHexString(c); } diff --git a/src/main/java/org/owasp/esapi/codecs/AbstractIntegerCodec.java b/src/main/java/org/owasp/esapi/codecs/AbstractIntegerCodec.java index cb9a61ff2..385b19e05 100644 --- a/src/main/java/org/owasp/esapi/codecs/AbstractIntegerCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/AbstractIntegerCodec.java @@ -1,18 +1,18 @@ /** * 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) 2017 - 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 Matt Seil (mseil .at. owasp.org) * @created 2017 - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @created 2007 @@ -24,9 +24,9 @@ * data by focusing on {@code int} as opposed to {@code Character}. Because non-BMP code * points cannot be represented by a {@code char}, this class remedies that by parsing string * data as codePoints as opposed to a stream of {@code char}s. - * + * * @author Matt Seil (mseil .at. owasp.org) - * @since 2017 -- Adapted from Jeff Williams' original {@code Codec} class. + * @since 2017 -- Adapted from Jeff Williams' original {@code Codec} class. */ public class AbstractIntegerCodec extends AbstractCodec { diff --git a/src/main/java/org/owasp/esapi/codecs/AbstractPushbackSequence.java b/src/main/java/org/owasp/esapi/codecs/AbstractPushbackSequence.java index dfe640fbc..f90e07dbb 100644 --- a/src/main/java/org/owasp/esapi/codecs/AbstractPushbackSequence.java +++ b/src/main/java/org/owasp/esapi/codecs/AbstractPushbackSequence.java @@ -1,18 +1,18 @@ /** * 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) 2017 - 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 Matt Seil (mseil .at. owasp.org) * @created 2017 - * + * */ package org.owasp.esapi.codecs; @@ -21,9 +21,9 @@ * This Abstract class provides the generic logic for using a {@link PushbackSequence} * in regards to iterating strings. The final Impl is intended for the user to supply * a type T such that the pushback interface can be utilized for sequences - * of type T. Presently this generic class is limited by the fact that - * input is a String. - * + * of type T. Presently this generic class is limited by the fact that + * input is a String. + * * @author Matt Seil * * @param diff --git a/src/main/java/org/owasp/esapi/codecs/CSSCodec.java b/src/main/java/org/owasp/esapi/codecs/CSSCodec.java index 548ce3a5e..9ffb60f32 100644 --- a/src/main/java/org/owasp/esapi/codecs/CSSCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/CSSCodec.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -21,7 +21,7 @@ /** * Implementation of the Codec interface for backslash encoding used in CSS. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -33,16 +33,16 @@ public class CSSCodec extends AbstractCharacterCodec //rgb (###,###,###) OR rgb(###%,###%,###%) //([rR][gG][bB])\s*\(\s*\d{1,3}\s*(\%)?\s*,\s*\d{1,3}\s*(\%)?\s*,\s*\d{1,3}\s*(\%)?\s*\) private static final String RGB_TRPLT = "([rR][gG][bB])\\s*\\(\\s*\\d{1,3}\\s*(\\%)?\\s*,\\s*\\d{1,3}\\s*(\\%)?\\s*,\\s*\\d{1,3}\\s*(\\%)?\\s*\\)"; - private static final Pattern RGB_TRPLT_PATTERN = Pattern.compile(RGB_TRPLT); - + private static final Pattern RGB_TRPLT_PATTERN = Pattern.compile(RGB_TRPLT); + @Override public String encode(char[] immune, String input) { EncodingPatternPreservation tripletCheck = new EncodingPatternPreservation(RGB_TRPLT_PATTERN); - + String inputChk = tripletCheck.captureAndReplaceMatches(input); - + String result = super.encode(immune, inputChk); - + return tripletCheck.restoreOriginalContent(result); } /** @@ -57,21 +57,21 @@ public String encodeCharacter(char[] immune, Character c) { if ( containsCharacter(c, immune ) ) { return ""+c; } - + // check for alphanumeric characters String hex = super.getHexForNonAlphanumeric(c); if ( hex == null ) { return ""+c; } - + // return the hex and end in whitespace to terminate return "\\" + hex + " "; } - + /** * {@inheritDoc} - * + * * Returns the decoded version of the character starting at index, * or null if no decoding is possible. */ @@ -185,7 +185,7 @@ public Character decodeCharacter(PushbackSequence input) { // parse the hex digit and create a character int i = Integer.parseInt(sb.toString(), 16); - + if (Character.isValidCodePoint(i)) return (char)i; return REPLACEMENT; diff --git a/src/main/java/org/owasp/esapi/codecs/Codec.java b/src/main/java/org/owasp/esapi/codecs/Codec.java index f1c6bceab..52c49c1e2 100644 --- a/src/main/java/org/owasp/esapi/codecs/Codec.java +++ b/src/main/java/org/owasp/esapi/codecs/Codec.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -22,19 +22,19 @@ * and canonicalization. The design of these codecs allows for character-by-character decoding, which is * necessary to detect double-encoding and the use of multiple encoding schemes, both of which are techniques * used by attackers to bypass validation and bury encoded attacks in data. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 - * - * @author Matt Seil (mseil .at. owasp.org) + * + * @author Matt Seil (mseil .at. owasp.org) * @since June 1, 2017 * @see org.owasp.esapi.Encoder */ public interface Codec { /** * Encode a String so that it can be safely used in a specific context. - * + * * @param immune * @param input * the String to encode @@ -44,8 +44,8 @@ public interface Codec { /** * Default implementation that should be overridden in specific codecs. - * - * @param immune + * + * @param immune * array of chars to NOT encode. Use with caution. * @param c * the Character to encode @@ -53,10 +53,10 @@ public interface Codec { * the encoded Character */ public String encodeCharacter( char[] immune, Character c ); - + /** * Default codepoint implementation that should be overridden in specific codecs. - * + * * @param immune * @param codePoint * the integer to encode @@ -67,7 +67,7 @@ public interface Codec { /** * Decode a String that was encoded using the encode method in this Class - * + * * @param input * the String to decode * @return @@ -77,11 +77,11 @@ public interface Codec { /** * Returns the decoded version of the next character from the input string and advances the - * current character in the {@code PushbackSequence}. If the current character is not encoded, this + * current character in the {@code PushbackSequence}. If the current character is not encoded, this * method MUST reset the {@code PushbackString}. - * + * * @param input the Character to decode - * + * * @return the decoded Character */ public T decodeCharacter( PushbackSequence input ); @@ -92,7 +92,7 @@ public interface Codec { * @return return null if alphanumeric or the character code in hex. */ public String getHexForNonAlphanumeric(char c); - + /** * Lookup the hex value of any character that is not alphanumeric. * @param c The character to lookup. @@ -113,7 +113,7 @@ public interface Codec { * @return the hexadecimal representation. */ public String toHex(char c); - + /** * Convert the {@code int} parameter to its hexadecimal representation. * @param c the character for which to return the new representation. @@ -123,7 +123,7 @@ public interface Codec { /** * Utility to search a char[] for a specific char. - * + * * @param c * @param array * @return True if the supplied array contains the specified character. False otherwise. diff --git a/src/main/java/org/owasp/esapi/codecs/DB2Codec.java b/src/main/java/org/owasp/esapi/codecs/DB2Codec.java index 33d0e4a59..8df61bc34 100644 --- a/src/main/java/org/owasp/esapi/codecs/DB2Codec.java +++ b/src/main/java/org/owasp/esapi/codecs/DB2Codec.java @@ -15,7 +15,7 @@ /** * Implementation of the Codec interface for DB2 strings. This function will only protect you from SQLi in limited situations. - * + * * @author Sivasankar Tanakala (stanakal@TRS.NYC.NY.US) * @since October 26, 2010 * @see org.owasp.esapi.Encoder diff --git a/src/main/java/org/owasp/esapi/codecs/HTMLEntityCodec.java b/src/main/java/org/owasp/esapi/codecs/HTMLEntityCodec.java index 0340edbac..df65b813a 100644 --- a/src/main/java/org/owasp/esapi/codecs/HTMLEntityCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/HTMLEntityCodec.java @@ -1,18 +1,18 @@ /** * 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) 2017 - 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 Matt Seil (mseil .at. owasp.org) - * @created 2017 - * + * @created 2017 + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @created 2007 @@ -26,13 +26,13 @@ /** * Implementation of the Codec interface for HTML entity encoding. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 - * - * @author Matt Seil (mseil .at. owasp.org) (mseil .at. owasp.org) - * + * + * @author Matt Seil (mseil .at. owasp.org) (mseil .at. owasp.org) + * * @see org.owasp.esapi.Encoder */ public class HTMLEntityCodec extends AbstractIntegerCodec @@ -52,11 +52,11 @@ public HTMLEntityCodec() { /** * Given an array of {@code char}, scan the input {@code String} and encode unsafe - * codePoints, except for codePoints passed into the {@code char} array. + * codePoints, except for codePoints passed into the {@code char} array. *

    - * WARNING: This method will silently discard any code point per the - * call to {@code Character.isValidCodePoint( int )} method. - * + * WARNING: This method will silently discard any code point per the + * call to {@code Character.isValidCodePoint( int )} method. + * * {@inheritDoc} */ @Override @@ -65,16 +65,16 @@ public String encode(char[] immune, String input) { for(int offset = 0; offset < input.length(); ){ final int point = input.codePointAt(offset); if(Character.isValidCodePoint(point)){ - sb.append(encodeCharacter(immune, point)); + sb.append(encodeCharacter(immune, point)); } offset += Character.charCount(point); } return sb.toString(); } - + /** * {@inheritDoc} - * + * * Encodes a codePoint for safe use in an HTML entity field. * @param immune */ @@ -82,43 +82,43 @@ public String encode(char[] immune, String input) { public String encodeCharacter( char[] immune, int codePoint ) { // check for immune characters - // Cast the codePoint to a char because we want to limit immunity to the BMP field only. + // Cast the codePoint to a char because we want to limit immunity to the BMP field only. if ( containsCharacter( (char) codePoint, immune ) && Character.isValidCodePoint(codePoint)) { return new StringBuilder().appendCodePoint(codePoint).toString(); } - + // check for alphanumeric characters String hex = super.getHexForNonAlphanumeric(codePoint); if ( hex == null && Character.isValidCodePoint(codePoint)) { return new StringBuilder().appendCodePoint(codePoint).toString(); } // check for illegal characters - if ( ( codePoint <= 0x1f - && codePoint != '\t' - && codePoint != '\n' - && codePoint != '\r' ) + if ( ( codePoint <= 0x1f + && codePoint != '\t' + && codePoint != '\n' + && codePoint != '\r' ) || ( codePoint >= 0x7f && codePoint <= 0x9f ) ) { hex = REPLACEMENT_HEX; // Let's entity encode this instead of returning it codePoint = REPLACEMENT_CHAR; } - + // check if there's a defined entity String entityName = characterToEntityMap.get(codePoint); if (entityName != null) { return "&" + entityName + ";"; } - + // return the hex entity as suggested in the spec return "&#x" + hex + ";"; } - + /** * {@inheritDoc} - * + * * Returns the decoded version of the character starting at index, or * null if no decoding is possible. - * + * * Formats all are legal both with and without semi-colon, upper/lower case: * &#dddd; * &#xhhhh; @@ -131,20 +131,20 @@ public Integer decodeCharacter( PushbackSequence input ) { input.reset(); return null; } - + // if this is not an encoded character, return null if (first != '&' ) { input.reset(); return null; } - + // test for numeric encodings Integer second = input.next(); if ( second == null ) { input.reset(); return null; } - + if (second == '#' ) { // handle numbers Integer c = getNumericEntity( input ); @@ -158,13 +158,13 @@ public Integer decodeCharacter( PushbackSequence input ) { input.reset(); return null; } - + /** * getNumericEntry checks input to see if it is a numeric entity - * + * * @param input * The input to test for being a numeric entity - * + * * @return * null if input is null, the character of input after decoding */ @@ -181,28 +181,28 @@ private Integer getNumericEntity( PushbackSequence input ) { /** * Parse a decimal number, such as those from JavaScript's String.fromCharCode(value) - * + * * @param input * decimal encoded string, such as 65 * @return - * character representation of this decimal value, e.g. A + * character representation of this decimal value, e.g. A * @throws NumberFormatException */ private Integer parseNumber( PushbackSequence input ) { StringBuilder sb = new StringBuilder(); while( input.hasNext() ) { Integer c = input.peek(); - + // if character is a digit then add it on and keep going if ( Character.isDigit( c ) && Character.isValidCodePoint(c) ) { sb.appendCodePoint( c ); input.next(); - + // if character is a semi-colon, eat it and quit } else if (c == ';' ) { input.next(); break; - + // otherwise just quit } else { break; @@ -218,10 +218,10 @@ private Integer parseNumber( PushbackSequence input ) { } return null; } - + /** * Parse a hex encoded entity - * + * * @param input * Hex encoded input (such as 437ae;) * @return @@ -232,18 +232,18 @@ private Integer parseHex( PushbackSequence input ) { StringBuilder sb = new StringBuilder(); while( input.hasNext() ) { Integer c = input.peek(); - + // if character is a hex digit then add it on and keep going //This statement implicitly tests for Character.isValidCodePoint(int) if ( "0123456789ABCDEFabcdef".indexOf(c) != -1 ) { sb.appendCodePoint( c ); input.next(); - + // if character is a semi-colon, eat it and quit } else if (c == ';' ) { input.next(); break; - + // otherwise just quit } else { break; @@ -259,12 +259,12 @@ private Integer parseHex( PushbackSequence input ) { } return null; } - + /** - * + * * Returns the decoded version of the character starting at index, or * null if no decoding is possible. - * + * * Formats all are legal both with and without semi-colon, upper/lower case: * &aa; * &aaa; @@ -282,7 +282,7 @@ private Integer getNamedEntity( PushbackSequence input ) { StringBuilder possible = new StringBuilder(); Entry entry; int len; - + // kludge around PushbackString.... len = Math.min(input.remainder().length(), entityToCharacterTrie.getMaxKeyLength()); for(int i=0;i Map> newNodeMap(Map> prev return new HashMap>(prev); } - /** + /** * Set the value for the key terminated at this node. * @param value The value for this key. */ @@ -225,7 +225,7 @@ T get(CharSequence key, int pos) return null; return nextNode.get(key,pos+1); } - + /** * Recursively lookup the longest key match. * @param key The key being looked up. @@ -507,7 +507,7 @@ public void putAll(Map map) public Set keySet() { Set keys = new HashSet(size); - + if(root == null) return keys; return root.keySet(new StringBuilder(), keys); diff --git a/src/main/java/org/owasp/esapi/codecs/Hex.java b/src/main/java/org/owasp/esapi/codecs/Hex.java index 63b96e932..5ca0b6890 100644 --- a/src/main/java/org/owasp/esapi/codecs/Hex.java +++ b/src/main/java/org/owasp/esapi/codecs/Hex.java @@ -1,6 +1,6 @@ /* * 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. @@ -13,7 +13,7 @@ public class Hex { /** Output byte representation as hexadecimal representation. - * + * * @param b Bytes to encode to hexadecimal representation. * @param leading0x If true, return with leading "0x". * @return Hexadecimal representation of specified bytes. @@ -37,7 +37,7 @@ public static String toHex(byte[] b, boolean leading0x) { /** * Output byte representation as hexadecimal representation. * Alias for toHex() method. - * + * * @param b Bytes to encode to hexadecimal representation. * @param leading0x If true, return with leading "0x". * @return Hexadecimal representation of specified bytes. @@ -53,7 +53,7 @@ public static String encode(byte[] b, boolean leading0x) { * in dealing with things like keys, initialization vectors, etc. For * example, the string "0x0000face" is going to return a byte array * whose length is 4, not 2. - * + * * @param hexStr Hexadecimal-encoded string, with or without leading "0x". * @return The equivalent byte array. */ @@ -74,9 +74,9 @@ public static byte[] fromHex(String hexStr) { /** Decode hexadecimal-encoded string and return raw byte array. * Alias for fromHex() method. - * + * * @param hexStr Hexadecimal-encoded string, with or without leading "0x". - * @return The equivalent byte array. + * @return The equivalent byte array. */ public static byte[] decode(String hexStr) { return fromHex(hexStr); diff --git a/src/main/java/org/owasp/esapi/codecs/JavaScriptCodec.java b/src/main/java/org/owasp/esapi/codecs/JavaScriptCodec.java index 4e7172e67..39f2d6406 100644 --- a/src/main/java/org/owasp/esapi/codecs/JavaScriptCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/JavaScriptCodec.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -18,7 +18,7 @@ /** * Implementation of the Codec interface for backslash encoding in JavaScript. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -29,7 +29,7 @@ public class JavaScriptCodec extends AbstractCharacterCodec { /** * {@inheritDoc} - * + * * Returns backslash encoded numeric format. Does not use backslash character escapes * such as, \" or \' as these may cause parsing problems. For example, if a javascript * attribute, such as onmouseover, contains a \" that will close the entire attribute and @@ -43,13 +43,13 @@ public String encodeCharacter( char[] immune, Character c ) { if ( containsCharacter(c, immune ) ) { return ""+c; } - + // check for alphanumeric characters String hex = super.getHexForNonAlphanumeric(c); if ( hex == null ) { return ""+c; } - + // Do not use these shortcuts as they can be used to break out of a context // if ( ch == 0x00 ) return "\\0"; // if ( ch == 0x08 ) return "\\b"; @@ -74,10 +74,10 @@ public String encodeCharacter( char[] immune, Character c ) { return "\\u" + pad + temp.toUpperCase(); } - + /** * {@inheritDoc} - * + * * Returns the decoded version of the character starting at index, or * null if no decoding is possible. *

    @@ -96,7 +96,7 @@ public Character decodeCharacter( PushbackSequence input ) { input.reset(); return null; } - + // if this is not an encoded character, return null if (first != '\\' ) { input.reset(); @@ -108,7 +108,7 @@ public Character decodeCharacter( PushbackSequence input ) { input.reset(); return null; } - + // \0 collides with the octal decoder and is non-standard // if ( second.charValue() == '0' ) { // return Character.valueOf( (char)0x00 ); @@ -130,7 +130,7 @@ public Character decodeCharacter( PushbackSequence input ) { return 0x27; } else if (second == '\\' ) { return 0x5c; - + // look for \\xXX format } else if ( Character.toLowerCase( second.charValue() ) == 'x' ) { // Search for exactly 2 hex digits following @@ -154,7 +154,7 @@ public Character decodeCharacter( PushbackSequence input ) { input.reset(); return null; } - + // look for \\uXXXX format } else if ( Character.toLowerCase( second.charValue() ) == 'u') { // Search for exactly 4 hex digits following @@ -178,13 +178,13 @@ public Character decodeCharacter( PushbackSequence input ) { input.reset(); return null; } - + // look for one, two, or three octal digits } else if ( PushbackString.isOctalDigit(second) ) { StringBuilder sb = new StringBuilder(); // get digit 1 sb.append(second); - + // get digit 2 if present Character c2 = input.next(); if ( !PushbackString.isOctalDigit(c2) ) { @@ -211,7 +211,7 @@ public Character decodeCharacter( PushbackSequence input ) { return null; } } - + // ignore the backslash and return the character input.reset(); return null; diff --git a/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java b/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java index 1789efd2b..ce66ba256 100644 --- a/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -20,14 +20,14 @@ import java.util.Map; /** - * + * * This class is DEPRECATED. It did not correctly handle encoding of non-BMP * unicode code points. This class is provided solely for any fatal bugs * not accounted for in the new version and will be removed entirely in - * a future release. - * + * a future release. + * * Implementation of the Codec interface for HTML entity encoding. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -35,7 +35,7 @@ */ @Deprecated public class LegacyHTMLEntityCodec extends AbstractCharacterCodec { - + private static final char REPLACEMENT_CHAR = '\ufffd'; private static final String REPLACEMENT_HEX = "fffd"; private static final String REPLACEMENT_STR = "" + REPLACEMENT_CHAR; @@ -44,7 +44,7 @@ public class LegacyHTMLEntityCodec extends AbstractCharacterCodec { /** * {@inheritDoc} - * + * * Encodes a Character for safe use in an HTML entity field. * @param immune */ @@ -54,34 +54,34 @@ public String encodeCharacter( char[] immune, Character c ) { if ( containsCharacter(c, immune ) ) { return ""+c; } - + // check for alphanumeric characters String hex = super.getHexForNonAlphanumeric(c); if ( hex == null ) { return ""+c; } - + // check for illegal characters if ( ( c <= 0x1f && c != '\t' && c != '\n' && c != '\r' ) || ( c >= 0x7f && c <= 0x9f ) ) { hex = REPLACEMENT_HEX; // Let's entity encode this instead of returning it c = REPLACEMENT_CHAR; } - + // check if there's a defined entity String entityName = characterToEntityMap.get(c); if (entityName != null) { return "&" + entityName + ";"; } - + // return the hex entity as suggested in the spec return "&#x" + hex + ";"; } - + /** * Returns the decoded version of the character starting at index, or * null if no decoding is possible. - * + * * Formats all are legal both with and without semi-colon, upper/lower case: * &#dddd; * &#xhhhh; @@ -94,20 +94,20 @@ public Character decodeCharacter( PushbackString input ) { input.reset(); return null; } - + // if this is not an encoded character, return null if (first != '&' ) { input.reset(); return null; } - + // test for numeric encodings Character second = input.next(); if ( second == null ) { input.reset(); return null; } - + if (second == '#' ) { // handle numbers Character c = getNumericEntity( input ); @@ -121,13 +121,13 @@ public Character decodeCharacter( PushbackString input ) { input.reset(); return null; } - + /** * getNumericEntry checks input to see if it is a numeric entity - * + * * @param input * The input to test for being a numeric entity - * + * * @return * null if input is null, the character of input after decoding */ @@ -144,28 +144,28 @@ private Character getNumericEntity( PushbackString input ) { /** * Parse a decimal number, such as those from JavaScript's String.fromCharCode(value) - * + * * @param input * decimal encoded string, such as 65 * @return - * character representation of this decimal value, e.g. A + * character representation of this decimal value, e.g. A * @throws NumberFormatException */ private Character parseNumber( PushbackString input ) { StringBuilder sb = new StringBuilder(); while( input.hasNext() ) { Character c = input.peek(); - + // if character is a digit then add it on and keep going if ( Character.isDigit( c.charValue() ) ) { sb.append( c ); input.next(); - + // if character is a semi-colon, eat it and quit } else if (c == ';' ) { input.next(); break; - + // otherwise just quit } else { break; @@ -181,10 +181,10 @@ private Character parseNumber( PushbackString input ) { } return null; } - + /** * Parse a hex encoded entity - * + * * @param input * Hex encoded input (such as 437ae;) * @return @@ -195,17 +195,17 @@ private Character parseHex( PushbackString input ) { StringBuilder sb = new StringBuilder(); while( input.hasNext() ) { Character c = input.peek(); - + // if character is a hex digit then add it on and keep going if ( "0123456789ABCDEFabcdef".indexOf(c) != -1 ) { sb.append( c ); input.next(); - + // if character is a semi-colon, eat it and quit } else if (c == ';' ) { input.next(); break; - + // otherwise just quit } else { break; @@ -221,12 +221,12 @@ private Character parseHex( PushbackString input ) { } return null; } - + /** - * + * * Returns the decoded version of the character starting at index, or * null if no decoding is possible. - * + * * Formats all are legal both with and without semi-colon, upper/lower case: * &aa; * &aaa; @@ -244,7 +244,7 @@ private Character getNamedEntity( PushbackString input ) { StringBuilder possible = new StringBuilder(); Map.Entry entry; int len; - + // kludge around PushbackString.... len = Math.min(input.remainder().length(), entityToCharacterTrie.getMaxKeyLength()); for(int i=0;ihttp://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 */ @@ -27,7 +27,7 @@ * Simply encode all ' (single tick) characters with '' (two single ticks) *
    *

  • Standard - * + * *
      *   NUL (0x00) --> \0  [This is a zero, not the letter O]
      *   BS  (0x08) --> \b
    @@ -39,20 +39,20 @@
      *   %   (0x25) --> \%
      *   '   (0x27) --> \'
      *   \   (0x5c) --> \\
    - *   _   (0x5f) --> \_ 
    + *   _   (0x5f) --> \_
      *   
    * all other non-alphanumeric characters with ASCII values less than 256 --> \c * where 'c' is the original non-alphanumeric character. *
    - * + * *
  • - * + * * - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) * Aspect Security * @since June 1, 2007 - * + * * MySQL 8.0 String Literals * OWASP * SQL_Injection_Prevention_Cheat_Sheet#MySQL_Escaping @@ -85,22 +85,22 @@ static Mode findByKey(int key) { /** Target MySQL Server is running in Standard MySQL (Default) mode. */ public static final int MYSQL_MODE = 0; - + /** * Target MySQL Server is running in ANSI_QUOTES Mode - * + * * @see * https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_ansi_quotes */ public static final int ANSI_MODE = 1; - + //private int mode = 0; private Mode mode; - + /** * Instantiate the MySQL codec - * + * * @param mode * Mode has to be one of {MYSQL_MODE|ANSI_MODE} to allow correct encoding * @deprecated @@ -125,35 +125,35 @@ public MySQLCodec( Mode mode ) { */ public String encodeCharacter( char[] immune, Character c ) { char ch = c.charValue(); - + // check for immune characters if ( containsCharacter( ch, immune ) ) { return ""+ch; } - + // check for alphanumeric characters String hex = super.getHexForNonAlphanumeric( ch ); if ( hex == null ) { return ""+ch; } - - + + switch( mode ) { case ANSI: return encodeCharacterANSI( c ); case STANDARD: return encodeCharacterMySQL( c ); default: return null; } } - + /** - * encodeCharacterANSI encodes for ANSI SQL. - * + * encodeCharacterANSI encodes for ANSI SQL. + * * Apostrophe is encoded * * Bug ###: In ANSI Mode Strings can also be passed in using the quotation. In ANSI_QUOTES mode a quotation * is considered to be an identifier, thus cannot be used at all in a value and will be dropped completely. - * - * @param c + * + * @param c * character to encode * @return * String encoded to standards of MySQL running in ANSI mode @@ -161,13 +161,13 @@ public String encodeCharacter( char[] immune, Character c ) { private String encodeCharacterANSI( Character c ) { if ( c == '\'' ) return "\'\'"; - + return ""+c; } /** * Encode a character suitable for MySQL - * + * * @param c * Character to encode * @return @@ -188,13 +188,13 @@ private String encodeCharacterMySQL( Character c ) { if ( ch == 0x5f ) return "\\_"; return "\\" + c; } - + /** * {@inheritDoc} - * + * * Returns the decoded version of the character starting at index, or * null if no decoding is possible. - * + * * Formats all are legal (case sensitive) * In ANSI_MODE '' decodes to ' * In MYSQL_MODE \x decodes to x (or a small list of specials) @@ -209,7 +209,7 @@ public Character decodeCharacter( PushbackSequence input ) { /** * decodeCharacterANSI decodes the next character from ANSI SQL escaping - * + * * @param input * A PushBackString containing characters you'd like decoded * @return @@ -222,7 +222,7 @@ private Character decodeCharacterANSI( PushbackSequence input ) { input.reset(); return null; } - + // if this is not an encoded character, return null if ( first.charValue() != '\'' ) { input.reset(); @@ -234,7 +234,7 @@ private Character decodeCharacterANSI( PushbackSequence input ) { input.reset(); return null; } - + // if this is not an encoded character, return null if ( second.charValue() != '\'' ) { input.reset(); @@ -245,7 +245,7 @@ private Character decodeCharacterANSI( PushbackSequence input ) { /** * decodeCharacterMySQL decodes all the potential escaped characters that MySQL is prepared to escape - * + * * @param input * A string you'd like to be decoded * @return @@ -258,7 +258,7 @@ private Character decodeCharacterMySQL( PushbackSequence input ) { input.reset(); return null; } - + // if this is not an encoded character, return null if ( first.charValue() != '\\' ) { input.reset(); @@ -270,7 +270,7 @@ private Character decodeCharacterMySQL( PushbackSequence input ) { input.reset(); return null; } - + if ( second.charValue() == '0' ) { return Character.valueOf( (char)0x00 ); } else if ( second.charValue() == 'b' ) { diff --git a/src/main/java/org/owasp/esapi/codecs/OracleCodec.java b/src/main/java/org/owasp/esapi/codecs/OracleCodec.java index 5a5db7d67..eb91a07ce 100644 --- a/src/main/java/org/owasp/esapi/codecs/OracleCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/OracleCodec.java @@ -20,11 +20,11 @@ /** * Implementation of the Codec interface for Oracle strings. This function will only protect you from SQLi in the case of user data * bring placed within an Oracle quoted string such as: - * + * * select * from table where user_name=' USERDATA '; - * + * * @see how-to-escape-single-quotes-in-strings - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @author Jim Manico (jim@manico.net) Manico.net * @since June 1, 2007 @@ -35,7 +35,7 @@ public class OracleCodec extends AbstractCharacterCodec { /** * {@inheritDoc} - * + * * Encodes ' to '' * * Encodes ' to '' @@ -47,7 +47,7 @@ public String encodeCharacter( char[] immune, Character c ) { return "\'\'"; return ""+c; } - + /** @@ -78,7 +78,7 @@ public Character decodeCharacter( PushbackSequence input ) { input.reset(); return null; } - + // if this is not an encoded character, return null if ( second.charValue() != '\'' ) { input.reset(); diff --git a/src/main/java/org/owasp/esapi/codecs/PercentCodec.java b/src/main/java/org/owasp/esapi/codecs/PercentCodec.java index 38a1ea8f4..5775055bb 100644 --- a/src/main/java/org/owasp/esapi/codecs/PercentCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/PercentCodec.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -22,7 +22,7 @@ /** * Implementation of the Codec interface for percent encoding (aka URL encoding). - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -74,7 +74,7 @@ private static byte[] toUtf8Bytes(String str) * @param b The byte to hexify * @return sb with the hex characters appended. */ - // rfc3986 2.1: For consistency, URI producers + // rfc3986 2.1: For consistency, URI producers // should use uppercase hexadecimal digits for all percent- // encodings. private static StringBuilder appendTwoUpperHex(StringBuilder sb, int b) @@ -121,10 +121,10 @@ public String encodeCharacter( char[] immune, Character c ) /** * {@inheritDoc} - * + * * Formats all are legal both upper/lower case: * %hh; - * + * * @param input * encoded character using percent characters (such as URL encoding) */ diff --git a/src/main/java/org/owasp/esapi/codecs/PushBackSequenceImpl.java b/src/main/java/org/owasp/esapi/codecs/PushBackSequenceImpl.java index 7b858badd..9f0c5223c 100644 --- a/src/main/java/org/owasp/esapi/codecs/PushBackSequenceImpl.java +++ b/src/main/java/org/owasp/esapi/codecs/PushBackSequenceImpl.java @@ -4,7 +4,7 @@ /** * The pushback string is used by Codecs to allow them to push decoded characters back onto a string * for further decoding. This is necessary to detect double-encoding. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -18,7 +18,7 @@ public class PushBackSequenceImpl extends AbstractPushbackSequence{ public PushBackSequenceImpl( String input ) { super(input); } - + /** * * @return The next value in this Sequence, as an Integer. @@ -36,7 +36,7 @@ public Integer next() { index += Character.charCount(point); return point; } - + /** * * @return The next value in this Sequence, as an Integer if it is a hex digit. Null otherwise. @@ -77,7 +77,7 @@ public static boolean isHexDigit( Integer c ) { */ public static boolean isOctalDigit( Integer c ) { if ( c == null ) return false; - Integer ch = Integer.valueOf(c); + Integer ch = Integer.valueOf(c); return ch >= '0' && ch <= '7'; } @@ -89,10 +89,10 @@ public Integer peek() { if ( pushback != null ) return pushback; if ( input == null ) return null; if ( input.length() == 0 ) return null; - if ( index >= input.length() ) return null; + if ( index >= input.length() ) return null; return input.codePointAt(index); } - + /** * Test to see if the next codePoint is a particular value without affecting the current index. * @param c @@ -102,10 +102,10 @@ public boolean peek( Integer c ) { if ( pushback != null && pushback.intValue() == c ) return true; if ( input == null ) return false; if ( input.length() == 0 ) return false; - if ( index >= input.length() ) return false; + if ( index >= input.length() ) return false; return input.codePointAt(index) == c; - } - + } + /** * {@inheritDoc} */ @@ -121,7 +121,7 @@ public void reset() { pushback = temp; index = mark; } - + /** * {@inheritDoc} */ diff --git a/src/main/java/org/owasp/esapi/codecs/PushbackSequence.java b/src/main/java/org/owasp/esapi/codecs/PushbackSequence.java index dfdc61e12..d2edcb652 100644 --- a/src/main/java/org/owasp/esapi/codecs/PushbackSequence.java +++ b/src/main/java/org/owasp/esapi/codecs/PushbackSequence.java @@ -1,18 +1,18 @@ /** * 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) 2017 - 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 Matt Seil (mseil .at. owasp.org) * @created 2017 - * + * */ package org.owasp.esapi.codecs; @@ -79,8 +79,8 @@ public interface PushbackSequence { void reset(); /** - * Not at all sure what this method is intended to do. There - * is a line in HTMLEntityCodec that said calling this method + * Not at all sure what this method is intended to do. There + * is a line in HTMLEntityCodec that said calling this method * is a "kludge around PushbackString..." * @return Return the remaining portion of the sequence, with any pushback appended to the front (if any). */ diff --git a/src/main/java/org/owasp/esapi/codecs/PushbackString.java b/src/main/java/org/owasp/esapi/codecs/PushbackString.java index 96bdec5ab..b25cc1f20 100644 --- a/src/main/java/org/owasp/esapi/codecs/PushbackString.java +++ b/src/main/java/org/owasp/esapi/codecs/PushbackString.java @@ -1,18 +1,18 @@ /** * 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) 2017 - 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 Matt Seil (mseil .at. owasp.org) * @updated 2017 - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @created 2007 @@ -23,7 +23,7 @@ * The pushback string is used by Codecs to allow them to push decoded * characters back onto a string for further decoding. This is necessary to * detect double-encoding. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) * Aspect Security * @since June 1, 2007 @@ -40,7 +40,7 @@ public PushbackString(String input) { /* * (non-Javadoc) - * + * * @see org.owasp.esapi.codecs.PushbackSequence#index() */ public int index() { @@ -49,7 +49,7 @@ public int index() { /* * (non-Javadoc) - * + * * @see org.owasp.esapi.codecs.PushbackSequence#hasNext() */ public boolean hasNext() { @@ -70,7 +70,7 @@ public boolean hasNext() { /* * (non-Javadoc) - * + * * @see org.owasp.esapi.codecs.PushbackSequence#next() */ public Character next() { @@ -93,7 +93,7 @@ public Character next() { /* * (non-Javadoc) - * + * * @see org.owasp.esapi.codecs.PushbackSequence#nextHex() */ public Character nextHex() { @@ -109,7 +109,7 @@ public Character nextHex() { /* * (non-Javadoc) - * + * * @see org.owasp.esapi.codecs.PushbackSequence#nextOctal() */ public Character nextOctal() { @@ -126,7 +126,7 @@ public Character nextOctal() { /** * Returns true if the parameter character is a hexidecimal digit 0 through * 9, a through f, or A through F. - * + * * @param c * @return true if it is a hexidecimal digit, false otherwise. */ @@ -140,7 +140,7 @@ public static boolean isHexDigit(Character c) { /** * Returns true if the parameter character is an octal digit 0 through 7. - * + * * @param c * @return true if it is an octal digit, false otherwise. */ @@ -154,7 +154,7 @@ public static boolean isOctalDigit(Character c) { /* * (non-Javadoc) - * + * * @see org.owasp.esapi.codecs.PushbackSequence#peek() */ public Character peek() { @@ -175,7 +175,7 @@ public Character peek() { /* * (non-Javadoc) - * + * * @see org.owasp.esapi.codecs.PushbackSequence#peek(char) */ public boolean peek(Character c) { diff --git a/src/main/java/org/owasp/esapi/codecs/UnixCodec.java b/src/main/java/org/owasp/esapi/codecs/UnixCodec.java index 0cd4f635c..aa513b94e 100644 --- a/src/main/java/org/owasp/esapi/codecs/UnixCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/UnixCodec.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -18,7 +18,7 @@ /** * Implementation of the {@code Codec} interface for '\' encoding from Unix command shell (bash lineage, not csh lineage). - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -28,7 +28,7 @@ public class UnixCodec extends AbstractCharacterCodec { /** * {@inheritDoc} - * + * * @return the backslash-encoded character * * @param immune Array of characters that should not be encoded. Use with caution! All @@ -37,22 +37,22 @@ public class UnixCodec extends AbstractCharacterCodec { */ public String encodeCharacter( char[] immune, Character c ) { char ch = c.charValue(); - + // check for immune characters if ( containsCharacter( ch, immune ) ) { return ""+ch; } - + // check for alphanumeric characters String hex = super.getHexForNonAlphanumeric( ch ); if ( hex == null ) { return ""+ch; } - + return "\\" + c; } - - + + /** * {@inheritDoc} * @@ -61,7 +61,7 @@ public String encodeCharacter( char[] immune, Character c ) { *
          *   \x - all special characters
          * 
    - * + * * @return the decoded version of the character starting at index, or * null if no decoding is possible. */ @@ -72,7 +72,7 @@ public Character decodeCharacter( PushbackSequence input ) { input.reset(); return null; } - + // if this is not an encoded character, return null if ( first.charValue() != '\\' ) { input.reset(); diff --git a/src/main/java/org/owasp/esapi/codecs/VBScriptCodec.java b/src/main/java/org/owasp/esapi/codecs/VBScriptCodec.java index ba9694786..5f768ec4f 100644 --- a/src/main/java/org/owasp/esapi/codecs/VBScriptCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/VBScriptCodec.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -20,7 +20,7 @@ /** * Implementation of the Codec interface for 'quote' encoding from VBScript. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -30,7 +30,7 @@ public class VBScriptCodec extends AbstractCharacterCodec { /** * Encode a String so that it can be safely used in a specific context. - * + * * @param immune * @param input * the String to encode @@ -42,7 +42,7 @@ public String encode(char[] immune, String input) { boolean inquotes = false; for ( int i=0; i 0 ) sb.append( "&" ); @@ -50,7 +50,7 @@ public String encode(char[] immune, String input) { sb.append( c ); inquotes = true; encoding = false; - + // handle characters that need encoding } else { if ( inquotes && i < input.length() ) sb.append( "\"" ); @@ -71,27 +71,27 @@ public String encode(char[] immune, String input) { */ public String encodeCharacter( char[] immune, Character c ) { char ch = c.charValue(); - + // check for immune characters if ( containsCharacter( ch, immune ) ) { return ""+ch; } - + // check for alphanumeric characters String hex = super.getHexForNonAlphanumeric( ch ); if ( hex == null ) { return ""+ch; } - + return "chrw(" + (int)c.charValue() + ")"; } - - - + + + /** * Returns the decoded version of the character starting at index, or * null if no decoding is possible. - * + * * Formats all are legal both upper/lower case: * "x - all special characters * " + chr(x) + " - not supported yet @@ -103,7 +103,7 @@ public Character decodeCharacter( PushbackSequence input ) { input.reset(); return null; } - + // if this is not an encoded character, return null if ( first.charValue() != '\"' ) { input.reset(); diff --git a/src/main/java/org/owasp/esapi/codecs/WindowsCodec.java b/src/main/java/org/owasp/esapi/codecs/WindowsCodec.java index fbb19a784..d3338b1be 100644 --- a/src/main/java/org/owasp/esapi/codecs/WindowsCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/WindowsCodec.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -18,7 +18,7 @@ /** * Implementation of the Codec interface for '^' encoding from Windows command shell. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -26,35 +26,35 @@ */ public class WindowsCodec extends AbstractCharacterCodec { - + /** * {@inheritDoc} - * + * * Returns Windows shell encoded character (which is ^) * * @param immune */ public String encodeCharacter( char[] immune, Character c ) { char ch = c.charValue(); - + // check for immune characters if ( containsCharacter( ch, immune ) ) { return ""+ch; } - + // check for alphanumeric characters String hex = super.getHexForNonAlphanumeric( ch ); if ( hex == null ) { return ""+ch; } - + return "^" + c; } - + /** * {@inheritDoc} - * + * * Returns the decoded version of the character starting at index, or * null if no decoding is possible. *

    @@ -68,7 +68,7 @@ public Character decodeCharacter( PushbackSequence input ) { input.reset(); return null; } - + // if this is not an encoded character, return null if ( first.charValue() != '^' ) { input.reset(); diff --git a/src/main/java/org/owasp/esapi/codecs/XMLEntityCodec.java b/src/main/java/org/owasp/esapi/codecs/XMLEntityCodec.java index 3ead807e3..c28734387 100644 --- a/src/main/java/org/owasp/esapi/codecs/XMLEntityCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/XMLEntityCodec.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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. - * + * */ package org.owasp.esapi.codecs; @@ -60,7 +60,7 @@ public class XMLEntityCodec extends AbstractCharacterCodec /** * {@inheritDoc} - * + * * Encodes a Character using XML entities as necessary. * * @param immune characters that should not be encoded as entities @@ -80,10 +80,10 @@ public String encodeCharacter(char[] immune, Character c) /** * {@inheritDoc} - * + * * Returns the decoded version of the character starting at index, or * null if no decoding is possible. - * + * * Legal formats: *

      *
    • &#dddd;
    • @@ -261,7 +261,7 @@ private static Character parseHex(PushbackSequence input) } /** - * + * * Converts the rest of a named entity to a character. * null if no decoding is possible. * @param input The input to read from. It is assumed that input diff --git a/src/main/java/org/owasp/esapi/codecs/package.html b/src/main/java/org/owasp/esapi/codecs/package.html index 0951a73f2..0726d78ef 100644 --- a/src/main/java/org/owasp/esapi/codecs/package.html +++ b/src/main/java/org/owasp/esapi/codecs/package.html @@ -10,7 +10,7 @@ before validation, many attacks can be detected and handled. By using the codecs to encode untrusted data before sending it to an interpreter, a wide variety of 'injection' attacks can be stopped. However, -this package does not currently address issues related to converting between byte-streams and +this package does not currently address issues related to converting between byte-streams and internal character representations, such as overlong UTF-8 issues. Those are left to the platform. The codecs cover protocol encodings such as HTML entity encoding and percent encoding, but also common product escaping schemes, such as Unix, Windows, MySQL, and Oracle. diff --git a/src/main/java/org/owasp/esapi/codecs/ref/EncodingPatternPreservation.java b/src/main/java/org/owasp/esapi/codecs/ref/EncodingPatternPreservation.java index 54487cadc..309485428 100644 --- a/src/main/java/org/owasp/esapi/codecs/ref/EncodingPatternPreservation.java +++ b/src/main/java/org/owasp/esapi/codecs/ref/EncodingPatternPreservation.java @@ -29,7 +29,7 @@ public class EncodingPatternPreservation { /** * Constructor. - * + * * @param pattern Pattern identifying content being replaced. */ public EncodingPatternPreservation(Pattern pattern) { @@ -39,11 +39,11 @@ public EncodingPatternPreservation(Pattern pattern) { /** * Replaces each matching instance of this instance's Pattern with an * identifiable replacement marker.
      - * + * *
      * After the encoding process is complete, use * {@link #restoreOriginalContent(String)} to re-insert the original data. - * + * * @param input String to adjust * @return The adjusted String */ @@ -62,7 +62,7 @@ public String captureAndReplaceMatches(String input) { if (replaceContent != null) { replacedContentList.add(replaceContent); inputCpy = inputCpy.replaceFirst(noEncodeContent.pattern(), replacementMarker); - } + } } return inputCpy; @@ -71,7 +71,7 @@ public String captureAndReplaceMatches(String input) { /** * Replaces each instance of the {@link #replacementMarker} with the original * content, as captured by {@link #captureAndReplaceMatches(String)} - * + * * @param input String to restore. * @return String reference with all values replaced. */ @@ -88,7 +88,7 @@ public String restoreOriginalContent(String input) { /** * Allows the marker used as a replacement to be altered. - * + * * @param marker String replacment to use for regex matches. */ public void setReplacementMarker(String marker) { diff --git a/src/main/java/org/owasp/esapi/configuration/EsapiPropertyLoaderFactory.java b/src/main/java/org/owasp/esapi/configuration/EsapiPropertyLoaderFactory.java index 4f814e06a..f32330852 100644 --- a/src/main/java/org/owasp/esapi/configuration/EsapiPropertyLoaderFactory.java +++ b/src/main/java/org/owasp/esapi/configuration/EsapiPropertyLoaderFactory.java @@ -55,5 +55,5 @@ public static AbstractPrioritizedPropertyLoader createPropertyLoader(EsapiConfig "supported"); } } - + } diff --git a/src/main/java/org/owasp/esapi/configuration/StandardEsapiPropertyLoader.java b/src/main/java/org/owasp/esapi/configuration/StandardEsapiPropertyLoader.java index 565235a84..fe50e02d7 100644 --- a/src/main/java/org/owasp/esapi/configuration/StandardEsapiPropertyLoader.java +++ b/src/main/java/org/owasp/esapi/configuration/StandardEsapiPropertyLoader.java @@ -83,7 +83,7 @@ public String getStringProp(String propertyName) throws ConfigurationException { } /** - * Methods loads configuration from .properties file. + * Methods loads configuration from .properties file. * @param file */ protected void loadPropertiesFromFile(File file) { diff --git a/src/main/java/org/owasp/esapi/configuration/XmlEsapiPropertyLoader.java b/src/main/java/org/owasp/esapi/configuration/XmlEsapiPropertyLoader.java index 45ef77f9c..3b3dc8ebc 100644 --- a/src/main/java/org/owasp/esapi/configuration/XmlEsapiPropertyLoader.java +++ b/src/main/java/org/owasp/esapi/configuration/XmlEsapiPropertyLoader.java @@ -99,7 +99,7 @@ public String getStringProp(String propertyName) throws ConfigurationException { } /** - * Methods loads configuration from .xml file. + * Methods loads configuration from .xml file. * @param file * @throws ConfigurationException if there is a problem loading the specified configuration file. */ diff --git a/src/main/java/org/owasp/esapi/configuration/consts/EsapiConfiguration.java b/src/main/java/org/owasp/esapi/configuration/consts/EsapiConfiguration.java index 7428123e1..e5e330569 100644 --- a/src/main/java/org/owasp/esapi/configuration/consts/EsapiConfiguration.java +++ b/src/main/java/org/owasp/esapi/configuration/consts/EsapiConfiguration.java @@ -1,7 +1,7 @@ package org.owasp.esapi.configuration.consts; /** - * Enum used for initialization of esapi configuration files. + * Enum used for initialization of esapi configuration files. * * @since 2.2 */ @@ -11,7 +11,7 @@ public enum EsapiConfiguration { DEVTEAM_ESAPI_CFG("org.owasp.esapi.devteam", 2); /** - * Key of system property pointing to path esapi to configuration file. + * Key of system property pointing to path esapi to configuration file. */ String configName; diff --git a/src/main/java/org/owasp/esapi/crypto/CipherSpec.java b/src/main/java/org/owasp/esapi/crypto/CipherSpec.java index 7a8e530e8..10b89b4d2 100644 --- a/src/main/java/org/owasp/esapi/crypto/CipherSpec.java +++ b/src/main/java/org/owasp/esapi/crypto/CipherSpec.java @@ -1,6 +1,6 @@ /* * 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. @@ -33,21 +33,21 @@ * by application developers, but rather only by those either extending ESAPI * or in the ESAPI reference implementation. Use directly by application * code is not recommended or supported. - * + * * @author kevin.w.wall@gmail.com * @since 2.0 */ public final class CipherSpec implements Serializable { private static final long serialVersionUID = 20090822; // version, in YYYYMMDD format - + private String cipher_xform_ = ESAPI.securityConfiguration().getCipherTransformation(); private int keySize_ = ESAPI.securityConfiguration().getEncryptionKeyLength(); // In bits private int blockSize_ = 16; // In bytes! I.e., 128 bits!!! private byte[] iv_ = null; private boolean blockSizeExplicitlySet = false; // Used for check in setIV(). - + // Cipher transformation component. Format is ALG/MODE/PADDING private enum CipherTransformationComponent { ALG, MODE, PADDING } @@ -64,7 +64,7 @@ public CipherSpec(String cipherXform, int keySize, int blockSize, final byte[] i setBlockSize(blockSize); setIV(iv); } - + /** * CTOR that sets everything but IV. * @param cipherXform The cipher transformation @@ -80,13 +80,13 @@ public CipherSpec(String cipherXform, int keySize, int blockSize) { setKeySize(keySize); setBlockSize(blockSize); } - + /** CTOR that sets everything but block size and IV. */ public CipherSpec(String cipherXform, int keySize) { setCipherTransformation(cipherXform); setKeySize(keySize); } - + /** CTOR that sets everything except block size. */ public CipherSpec(String cipherXform, int keySize, final byte[] iv) { setCipherTransformation(cipherXform); @@ -105,18 +105,18 @@ public CipherSpec(final Cipher cipher) { setIV(cipher.getIV()); } } - + /** CTOR that sets everything. */ public CipherSpec(final Cipher cipher, int keySize) { this(cipher); setKeySize(keySize); } - + /* CTOR that sets only the IV and uses defaults for everything else. */ public CipherSpec(final byte[] iv) { setIV(iv); } - + /** * Default CTOR. Creates a cipher specification for 128-bit cipher * transformation of "AES/CBC/PKCS5Padding" and a {@code null} IV. @@ -186,7 +186,7 @@ private CipherSpec setCipherTransformation(String cipherXform, boolean fromCiphe this.cipher_xform_ = cipherXform; return this; } - + /** * Get the cipher transformation. * @return The cipher transformation {@code String}. @@ -246,7 +246,7 @@ public int getBlockSize() { public String getCipherAlgorithm() { return getFromCipherXform(CipherTransformationComponent.ALG); } - + /** * Retrieve the cipher mode. * @return The cipher mode. @@ -254,7 +254,7 @@ public String getCipherAlgorithm() { public String getCipherMode() { return getFromCipherXform(CipherTransformationComponent.MODE); } - + /** * Retrieve the cipher padding scheme. * @return The padding scheme is returned. @@ -262,7 +262,7 @@ public String getCipherMode() { public String getPaddingScheme() { return getFromCipherXform(CipherTransformationComponent.PADDING); } - + /** * Retrieve the initialization vector (IV). * @return The IV as a byte array. @@ -270,7 +270,7 @@ public String getPaddingScheme() { public byte[] getIV() { return iv_; } - + /** * Set the initialization vector (IV). * @param iv The byte array to set as the IV. A copy of the IV is saved. @@ -282,7 +282,7 @@ public CipherSpec setIV(final byte[] iv) { if ( ! ( requiresIV() && (iv != null && iv.length != 0) ) ) { throw new IllegalArgumentException("Required IV cannot be null or 0 length."); } - + // Don't store a reference, but make a copy! When an IV is provided, it generally should // be the same length as the block size of the cipher. if ( iv != null ) { // Allow null IV for ECB mode. @@ -307,9 +307,9 @@ public CipherSpec setIV(final byte[] iv) { * @return True if the cipher mode requires an IV, otherwise false. * */ public boolean requiresIV() { - + String cm = getCipherMode(); - + // Add any other cipher modes supported by JCE but not requiring IV. // ECB is the only one I'm aware of that doesn't. Mode is not case // sensitive. @@ -318,7 +318,7 @@ public boolean requiresIV() { } return true; } - + /** * Override {@code Object.toString()} to provide something more useful. * @return A meaningful string describing this object. @@ -338,7 +338,7 @@ public String toString() { sb.append("; IV length = ").append( ivLen ).append(" bytes."); return sb.toString(); } - + /** * {@inheritDoc} */ @@ -399,10 +399,10 @@ public int hashCode() { */ protected boolean canEqual(Object other) { return (other instanceof CipherSpec); - } - + } + /** - * Split the current cipher transformation and return the requested part. + * Split the current cipher transformation and return the requested part. * @param component The component of the cipher transformation to return. * @return The cipher algorithm, cipher mode, or padding, as requested. */ @@ -411,7 +411,7 @@ private String getFromCipherXform(CipherTransformationComponent component) { String[] parts = getCipherTransformation().split("/"); // Assertion should also be okay here as these conditions are checked // elsewhere and this method is private. - assert parts.length == 3 : "Invalid cipher transformation: " + getCipherTransformation(); + assert parts.length == 3 : "Invalid cipher transformation: " + getCipherTransformation(); return parts[part]; } } diff --git a/src/main/java/org/owasp/esapi/crypto/CipherText.java b/src/main/java/org/owasp/esapi/crypto/CipherText.java index 5f1a1e161..e0b549da3 100644 --- a/src/main/java/org/owasp/esapi/crypto/CipherText.java +++ b/src/main/java/org/owasp/esapi/crypto/CipherText.java @@ -1,6 +1,6 @@ /* * 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. @@ -71,9 +71,9 @@ public final class CipherText implements Serializable { public static final int cipherTextVersion = 20130830; // Format: YYYYMMDD, max is 99991231. // Required by Serializable classes. private static final long serialVersionUID = cipherTextVersion; // Format: YYYYMMDD - + private static final Logger logger = ESAPI.getLogger("CipherText"); - + private CipherSpec cipherSpec_ = null; private byte[] raw_ciphertext_ = null; private byte[] separate_mac_ = null; @@ -94,7 +94,7 @@ private enum CipherTextFlags { CipherTextFlags.PADDING, CipherTextFlags.KEYSIZE, CipherTextFlags.BLOCKSIZE, CipherTextFlags.CIPHERTEXT, CipherTextFlags.INITVECTOR); - + // These are all the pieces we collect when passed a CipherSpec object. private final EnumSet fromCipherSpec = EnumSet.of(CipherTextFlags.ALGNAME, CipherTextFlags.CIPHERMODE, @@ -103,7 +103,7 @@ private enum CipherTextFlags { // How much we've collected so far. We start out with having collected nothing. private EnumSet progress = EnumSet.noneOf(CipherTextFlags.class); - + // Check if versions of KeyDerivationFunction, CipherText, and // CipherTextSerializer are all the same. { @@ -118,7 +118,7 @@ private enum CipherTextFlags { } /////////////////////////// C O N S T R U C T O R S ///////////////////////// - + /** * Default CTOR. Takes all the defaults from the ESAPI.properties, or * default values from initial values from this class (when appropriate) @@ -128,12 +128,12 @@ public CipherText() { cipherSpec_ = new CipherSpec(); // Uses default for everything but IV. received(fromCipherSpec); } - + /** * Construct from a {@code CipherSpec} object. Still needs to have * {@link #setCiphertext(byte[])} or {@link #setIVandCiphertext(byte[], byte[])} * called to be usable. - * + * * @param cipherSpec The cipher specification to use. */ public CipherText(final CipherSpec cipherSpec) { @@ -143,10 +143,10 @@ public CipherText(final CipherSpec cipherSpec) { received(CipherTextFlags.INITVECTOR); } } - + /** * Construct from a {@code CipherSpec} object and the raw ciphertext. - * + * * @param cipherSpec The cipher specification to use. * @param cipherText The raw ciphertext bytes to use. * @throws EncryptionException Thrown if {@code cipherText} is null or @@ -162,7 +162,7 @@ public CipherText(final CipherSpec cipherSpec, byte[] cipherText) received(CipherTextFlags.INITVECTOR); } } - + /** Create a {@code CipherText} object from what is supposed to be a * portable serialized byte array, given in network byte order, that * represents a valid, previously serialized {@code CipherText} object @@ -194,39 +194,39 @@ public static CipherText fromPortableSerializedBytes(byte[] bytes) * The cipher transformation name is usually sufficient to be passed to * {@link javax.crypto.Cipher#getInstance(String)} to create a * Cipher object to decrypt the ciphertext. - * + * * @return The cipher transformation name used to encrypt the plaintext * resulting in this ciphertext. */ public String getCipherTransformation() { return cipherSpec_.getCipherTransformation(); } - + /** * Obtain the name of the cipher algorithm used for encrypting the * plaintext. - * + * * @return The name as the cryptographic algorithm used to perform the * encryption resulting in this ciphertext. */ public String getCipherAlgorithm() { return cipherSpec_.getCipherAlgorithm(); } - + /** * Retrieve the key size used with the cipher algorithm that was used to * encrypt data to produce this ciphertext. - * + * * @return The key size in bits. We work in bits because that's the crypto way! */ public int getKeySize() { return cipherSpec_.getKeySize(); } - + /** * Retrieve the block size (in bytes!) of the cipher used for encryption. * (Note: If an IV is used, this will also be the IV length.) - * + * * @return The block size in bytes. (Bits, bytes! It's confusing I know. Blame * the cryptographers; we've just following * convention.) @@ -234,10 +234,10 @@ public int getKeySize() { public int getBlockSize() { return cipherSpec_.getBlockSize(); } - + /** * Get the name of the cipher mode used to encrypt some plaintext. - * + * * @return The name of the cipher mode used to encrypt the plaintext * resulting in this ciphertext. E.g., "CBC" for "cipher block * chaining", "ECB" for "electronic code book", etc. @@ -245,10 +245,10 @@ public int getBlockSize() { public String getCipherMode() { return cipherSpec_.getCipherMode(); } - + /** * Get the name of the padding scheme used to encrypt some plaintext. - * + * * @return The name of the padding scheme used to encrypt the plaintext * resulting in this ciphertext. Example: "PKCS5Padding". If no * padding was used "None" is returned. @@ -256,11 +256,11 @@ public String getCipherMode() { public String getPaddingScheme() { return cipherSpec_.getPaddingScheme(); } - + /** * Return the initialization vector (IV) used to encrypt the plaintext * if applicable. - * + * * @return The IV is returned if the cipher mode used to encrypt the * plaintext was not "ECB". ECB mode does not use an IV so in * that case, null is returned. @@ -273,8 +273,8 @@ public byte[] getIV() { return null; } } - - /** + + /** * Return true if the cipher mode used requires an IV. Usually this will * be true unless ECB mode (which should be avoided whenever possible) is * used. @@ -282,11 +282,11 @@ public byte[] getIV() { public boolean requiresIV() { return cipherSpec_.requiresIV(); } - + /** * Get the raw ciphertext byte array resulting from encrypting some * plaintext. - * + * * @return A copy of the raw ciphertext as a byte array. */ public byte[] getRawCipherText() { @@ -299,11 +299,11 @@ public byte[] getRawCipherText() { return null; } } - + /** * Get number of bytes in raw ciphertext. Zero is returned if ciphertext has not * yet been stored. - * + * * @return The number of bytes of raw ciphertext; 0 if no raw ciphertext has been stored. */ public int getRawCipherTextByteLength() { @@ -330,7 +330,7 @@ public int getRawCipherTextByteLength() { public String getBase64EncodedRawCipherText() { return ESAPI.encoder().encodeForBase64(getRawCipherText(),false); } - + /** * Return the ciphertext as a base64-encoded String. If an * IV was used, the IV if first prepended to the raw ciphertext before @@ -382,7 +382,7 @@ public String getEncodedIVCipherText() { * implementation of {@code Encryptor} always computes it and includes it. * The recipient of the ciphertext can then choose whether or not to validate * it. - * + * * @param authKey The secret key that is used for proving authenticity of * the IV and ciphertext. This key should be derived from * the {@code SecretKey} passed to the @@ -424,7 +424,7 @@ public void computeAndStoreMAC(SecretKey authKey) { } // If 'result' is null, we already logged this in computeMAC(). } - + /** * Same as {@link #computeAndStoreMAC(SecretKey)} but this is only used by * {@code CipherTextSerializeer}. (Has package level access.) @@ -437,14 +437,14 @@ void storeSeparateMAC(byte[] macValue) { assert macComputed() : "MAC failed to compute correctly!"; } } - + /** * Validate the message authentication code (MAC) associated with the ciphertext. * This is mostly meant to ensure that an attacker has not replaced the IV * or raw ciphertext with something arbitrary. Note however that it will * not detect the case where an attacker simply substitutes one * valid ciphertext with another ciphertext. - * + * * @param authKey The secret key that is used for proving authenticity of * the IV and ciphertext. This key should be derived from * the {@code SecretKey} passed to the @@ -490,14 +490,14 @@ public boolean validateMAC(SecretKey authKey) { return false; // Deprecated decrypt() method removed, so now return false. } } - + /** * Return this {@code CipherText} object as a portable (i.e., network byte * ordered) serialized byte array. Note this is not the same as * returning a serialized object using Java serialization. Instead this * is a representation that all ESAPI implementations will use to pass * ciphertext between different programming language implementations. - * + * * @return A network byte-ordered serialized representation of this object. * @throws EncryptionException */ // DISCUSS: This method name sucks too. Suggestions??? @@ -509,7 +509,7 @@ public byte[] asPortableSerializedByteArray() throws EncryptionException { "all mandatory information has been collected"; throw new EncryptionException("Can't serialize incomplete ciphertext info", msg); } - + // If we are supposed to be using a (separate) MAC, also make sure // that it has been computed/stored. boolean requiresMAC = ESAPI.securityConfiguration().useMACforCipherText(); @@ -522,11 +522,11 @@ public byte[] asPortableSerializedByteArray() throws EncryptionException { throw new EncryptionException("Can't serialize ciphertext info: Data integrity issue.", msg); } - + // OK, everything ready, so give it a shot. return new CipherTextSerializer(this).asSerializedByteArray(); } - + ///// Setters ///// /** * Set the raw ciphertext. @@ -555,7 +555,7 @@ public void setCiphertext(byte[] ciphertext) throw new EncryptionException("MAC already set; cannot store new raw ciphertext", logMsg); } } - + /** * Set the IV and raw ciphertext. * @param iv The initialization vector. @@ -599,7 +599,7 @@ public void setIVandCiphertext(byte[] iv, byte[] ciphertext) throw new EncryptionException("Validation of decryption failed.", logMsg); } } - + public int getKDFVersion() { return kdfVersion_; } @@ -608,7 +608,7 @@ public void setKDFVersion(int vers) { CryptoHelper.isValidKDFVersion(vers, false, true); kdfVersion_ = vers; } - + public KeyDerivationFunction.PRF_ALGORITHMS getKDF_PRF() { return KeyDerivationFunction.convertIntToPRF(kdfPrfSelection_); } @@ -616,19 +616,19 @@ public KeyDerivationFunction.PRF_ALGORITHMS getKDF_PRF() { int kdfPRFAsInt() { return kdfPrfSelection_; } - + public void setKDF_PRF(int prfSelection) { if ( prfSelection < 0 || prfSelection > 15 ) { throw new IllegalArgumentException("kdfPrf == " + prfSelection + " must be between 0 and 15, inclusive."); } kdfPrfSelection_ = prfSelection; } - + /** Get stored time stamp representing when data was encrypted. */ public long getEncryptionTimestamp() { return encryption_timestamp_; } - + /** * Set the encryption timestamp to the current system time as determined by * {@code System.currentTimeMillis()}, but only if it has not been previously @@ -647,12 +647,12 @@ private void setEncryptionTimestamp() { } encryption_timestamp_ = System.currentTimeMillis(); } - + /** * Set the encryption timestamp to the time stamp specified by the parameter. *

      * This method is intended for use only by {@code CipherTextSerializer}. - * + * * @param timestamp The time in milliseconds since epoch time (midnight, * January 1, 1970 GMT). */ // Package level access. ESAPI jar should be sealed and signed. @@ -666,7 +666,7 @@ void setEncryptionTimestamp(long timestamp) { } encryption_timestamp_ = timestamp; } - + /** Return the separately calculated Message Authentication Code (MAC) that * is computed via the {@code computeAndStoreMAC(SecretKey authKey)} method. * @return The copy of the computed MAC, or {@code null} if one is not used. @@ -677,9 +677,9 @@ public byte[] getSeparateMAC() { } byte[] copy = new byte[ separate_mac_.length ]; System.arraycopy(separate_mac_, 0, copy, 0, separate_mac_.length); - return copy; + return copy; } - + /** * More useful {@code toString()} method. */ @@ -782,7 +782,7 @@ protected boolean canEqual(Object other) { } //////////////////////////////////// P R I V A T E ///////////////////////////////////////// - + /** * Compute a MAC, but do not store it. May set the nonce value as a * side-effect. The MAC is calculated as: @@ -801,7 +801,7 @@ protected boolean canEqual(Object other) { * @param authKey The {@code SecretKey} used with the computed HMAC-SHA1 * to ensure authenticity. * @return The value for the MAC. - */ + */ private byte[] computeMAC(SecretKey authKey) { // These assertions are okay and leaving them as assertions rather than // changing the to conditional statements that throw should be all right @@ -840,7 +840,7 @@ private byte[] computeMAC(SecretKey authKey) { return null; } } - + /** * Return true if the MAC has already been computed (i.e., not null). */ @@ -859,7 +859,7 @@ private boolean collectedAll() { EnumSet initVector = EnumSet.of(CipherTextFlags.INITVECTOR); ctFlags = EnumSet.complementOf(initVector); } - boolean result = progress.containsAll(ctFlags); + boolean result = progress.containsAll(ctFlags); return result; } @@ -878,7 +878,7 @@ private boolean isCollected(CipherTextFlags flag) { private void received(CipherTextFlags flag) { progress.add(flag); } - + /** * Add all the flags from the specified set to that we've collected so far. * @param ctSet A {@code EnumSet} containing all the flags diff --git a/src/main/java/org/owasp/esapi/crypto/CipherTextSerializer.java b/src/main/java/org/owasp/esapi/crypto/CipherTextSerializer.java index 547068c11..c5daa7d85 100644 --- a/src/main/java/org/owasp/esapi/crypto/CipherTextSerializer.java +++ b/src/main/java/org/owasp/esapi/crypto/CipherTextSerializer.java @@ -27,7 +27,7 @@ * supports. (Perhaps wishful thinking that other ESAPI implementations such as * ESAPI for .NET, ESAPI for C, ESAPI for C++, etc. will all support a single, common * serialization technique so they could exchange encrypted data.) - * + * * @author kevin.w.wall@gmail.com * @since 2.0 * @@ -44,9 +44,9 @@ public class CipherTextSerializer { private static final long serialVersionUID = cipherTextSerializerVersion; private static final Logger logger = ESAPI.getLogger("CipherTextSerializer"); - + private CipherText cipherText_ = null; - + // Check if versions of KeyDerivationFunction, CipherText, and // CipherTextSerializer are all the same. { @@ -59,14 +59,14 @@ public class CipherTextSerializer { throw new ExceptionInInitializerError("Versions of CipherTextSerializer and KeyDerivationFunction are not compatible."); } } - + public CipherTextSerializer(CipherText cipherTextObj) { if ( cipherTextObj == null ) { throw new IllegalArgumentException("CipherText object must not be null."); } cipherText_ = cipherTextObj; } - + /** * Given byte array in network byte order (i.e., big-endian order), convert * it so that a {@code CipherText} can be constructed from it. @@ -116,7 +116,7 @@ public byte[] asSerializedByteArray() { throw new IllegalArgumentException("MAC length too large. Max is " + Short.MAX_VALUE + " bytes"); } short macLen = (short) mac.length; - + byte[] serializedObj = computeSerialization(kdfInfo, timestamp, cipherXform, @@ -129,10 +129,10 @@ public byte[] asSerializedByteArray() { macLen, mac ); - + return serializedObj; } - + /** * Return the actual {@code CipherText} object. * @return The {@code CipherText} object that we are serializing. @@ -143,7 +143,7 @@ public CipherText asCipherText() { } return cipherText_; } - + /** * Take all the individual elements that make of the serialized ciphertext * format and put them in order and return them as a byte array. @@ -204,7 +204,7 @@ private byte[] computeSerialization(int kdfInfo, long timestamp, if ( macLen > 0 ) baos.write(mac, 0, mac.length); return baos.toByteArray(); } - + // All strings are written as UTF-8 encoded byte streams with the // length prepended before it as a short. The prepended length is // more for the benefit of languages like C so they can pre-allocate @@ -230,7 +230,7 @@ private void writeString(ByteArrayOutputStream baos, String str) { "converting string to UTF8 encoding. Results suspect. Corrupt rt.jar????"); } } - + private String readString(ByteArrayInputStream bais, short sz) throws NullPointerException, IOException { @@ -242,7 +242,7 @@ private String readString(ByteArrayInputStream bais, short sz) } return new String(bytes, "UTF8"); } - + private void writeShort(ByteArrayOutputStream baos, short s) { byte[] shortAsByteArray = ByteConversionUtil.fromShort(s); if ( shortAsByteArray.length != 2 ) { @@ -250,7 +250,7 @@ private void writeShort(ByteArrayOutputStream baos, short s) { } baos.write(shortAsByteArray, 0, 2); } - + private short readShort(ByteArrayInputStream bais) throws NullPointerException, IndexOutOfBoundsException { @@ -261,12 +261,12 @@ private short readShort(ByteArrayInputStream bais) } return ByteConversionUtil.toShort(shortAsByteArray); } - + private void writeInt(ByteArrayOutputStream baos, int i) { byte[] intAsByteArray = ByteConversionUtil.fromInt(i); baos.write(intAsByteArray, 0, 4); } - + private int readInt(ByteArrayInputStream bais) throws NullPointerException, IndexOutOfBoundsException { @@ -277,7 +277,7 @@ private int readInt(ByteArrayInputStream bais) } return ByteConversionUtil.toInt(intAsByteArray); } - + private void writeLong(ByteArrayOutputStream baos, long l) { byte[] longAsByteArray = ByteConversionUtil.fromLong(l); if ( longAsByteArray.length != 8 ) { @@ -285,7 +285,7 @@ private void writeLong(ByteArrayOutputStream baos, long l) { } baos.write(longAsByteArray, 0, 8); } - + private long readLong(ByteArrayInputStream bais) throws NullPointerException, IndexOutOfBoundsException { @@ -296,7 +296,7 @@ private long readLong(ByteArrayInputStream bais) } return ByteConversionUtil.toLong(longAsByteArray); } - + /** Convert the serialized ciphertext byte array to a {@code CipherText} * object. * @param cipherTextSerializedBytes The serialized ciphertext as a byte array. @@ -337,11 +337,11 @@ private CipherText convertToCipherText(byte[] cipherTextSerializedBytes) throw new EncryptionException("Version info from serialized ciphertext not in valid range.", "Likely tampering with KDF version on serialized ciphertext." + logMsg); } - + debug("convertToCipherText: kdfPrf = " + kdfPrf + ", kdfVers = " + kdfVers); if ( ! versionIsCompatible( kdfVers) ) { throw new EncryptionException("This version of ESAPI is not compatible with the version of ESAPI that encrypted your data.", - "KDF version " + kdfVers + " from serialized ciphertext not compatibile with current KDF version of " + + "KDF version " + kdfVers + " from serialized ciphertext not compatibile with current KDF version of " + KeyDerivationFunction.kdfVersion); } long timestamp = readLong(bais); @@ -424,12 +424,12 @@ private CipherText convertToCipherText(byte[] cipherTextSerializedBytes) * the serialized ciphertext. In particular, we assume that if we have a * newer version of KDF than we can support it as we assume that we have * built in backward compatibility. - * + * * At this point (ESAPI 2.1.0, KDF version 20130830), all we need to check * if the version is either the current version or the previous version as * both versions work the same. This checking may get more complicated in * the future. - * + * * @param readKdfVers The version information extracted from the serialized * ciphertext. */ @@ -437,7 +437,7 @@ private static boolean versionIsCompatible(int readKdfVers) { if ( readKdfVers <= 0 ) { throw new IllegalArgumentException("Extracted KDF version is <= 0. Must be integer >= 1."); } - + switch ( readKdfVers ) { case KeyDerivationFunction.originalVersion: // First version return true; diff --git a/src/main/java/org/owasp/esapi/crypto/CryptoDiscoverer.java b/src/main/java/org/owasp/esapi/crypto/CryptoDiscoverer.java index 8f89c7e95..53ab1c7c0 100644 --- a/src/main/java/org/owasp/esapi/crypto/CryptoDiscoverer.java +++ b/src/main/java/org/owasp/esapi/crypto/CryptoDiscoverer.java @@ -23,7 +23,7 @@ public class CryptoDiscoverer { private static String EOL = System.getProperty("line.separator", "\n"); - + public static void main(String... args) { String provider = ".*"; String algorithm = ".*"; diff --git a/src/main/java/org/owasp/esapi/crypto/CryptoHelper.java b/src/main/java/org/owasp/esapi/crypto/CryptoHelper.java index 805c3565c..922fbf33d 100644 --- a/src/main/java/org/owasp/esapi/crypto/CryptoHelper.java +++ b/src/main/java/org/owasp/esapi/crypto/CryptoHelper.java @@ -1,6 +1,6 @@ /* * 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. @@ -31,12 +31,12 @@ * All the cryptographic operations use the default cryptographic properties; * e.g., default cipher transformation, default key size, default IV type (where * applicable), etc. - * + * * @author kevin.w.wall@gmail.com * @since 2.0 */ public class CryptoHelper { - + private static final Logger logger = ESAPI.getLogger("CryptoHelper"); // TODO: Also consider supplying implementation of RFC 2898 / PKCS#5 PBKDF2 @@ -101,7 +101,7 @@ public static SecretKey generateSecretKey(String alg, int keySize) * It is used by ESAPI's reference crypto implementation class {@code JavaEncryptor} * and might be useful for someone implementing their own replacement class, but * generally it is not something that is useful to application client code. - * + * * @param keyDerivationKey A key used as an input to a key derivation function * to derive other keys. This is the key that generally * is created using some key generation mechanism such as @@ -218,7 +218,7 @@ public static boolean isAllowedCipherMode(String cipherMode) ESAPI.securityConfiguration().getAdditionalAllowedCipherModes(); return extraCipherModes.contains( cipherMode ); } - + /** * Check to see if a Message Authentication Code (MAC) is required * for a given {@code CipherText} object and the current ESAPI.property @@ -247,7 +247,7 @@ public static boolean isMACRequired(CipherText ct) { // additional computing time. return ( !preferredCipherMode && wantsMAC ); } - + /** * If a Message Authentication Code (MAC) is required for the specified * {@code CipherText} object, then attempt to validate the MAC that @@ -257,7 +257,7 @@ public static boolean isMACRequired(CipherText ct) { * @param sk The {@code SecretKey} used to derived a key to check * the authenticity via the MAC. * @param ct The {@code CipherText} that we are checking for a - * valid MAC. + * valid MAC. * * @return True is returned if a MAC is required and it is valid as * verified using a key derived from the specified @@ -282,7 +282,7 @@ public static boolean isCipherTextMACvalid(SecretKey sk, CipherText ct) } return true; } - + /** * Overwrite a byte array with a specified byte. This is frequently done * to a plaintext byte array so the sensitive data is not lying around @@ -294,7 +294,7 @@ public static void overwrite(byte[] bytes, byte x) { Arrays.fill(bytes, x); } - + /** * Overwrite a byte array with the byte containing '*'. That is, call *

      @@ -306,11 +306,11 @@ public static void overwrite(byte[] bytes)
           {
               overwrite(bytes, (byte)'*');
           }
      -    
      +
           // These provide for a bit more type safety when copying bytes around.
           /**
            * Same as {@code System.arraycopy(src, 0, dest, 0, length)}.
      -     * 
      +     *
            * @param      src      the source array.
            * @param      dest     the destination array.
            * @param      length   the number of array elements to be copied.
      @@ -323,7 +323,7 @@ public static void copyByteArray(final byte[] src, byte[] dest, int length)
           {
               System.arraycopy(src, 0, dest, 0, length);
           }
      -    
      +
           /**
            * Same as {@code copyByteArray(src, dest, src.length)}.
            * @param      src      the source array.
      @@ -337,12 +337,12 @@ public static void copyByteArray(final byte[] src, byte[] dest)
           {
               copyByteArray(src, dest, src.length);
           }
      -    
      +
           /**
            * A "safe" array comparison that is not vulnerable to side-channel
            * "timing attacks". All comparisons of non-null, equal length bytes should
            * take same amount of time. We use this for cryptographic comparisons.
      -     * 
      +     *
            * @param b1   A byte array to compare.
            * @param b2   A second byte array to compare.
            * @return     {@code true} if both byte arrays are null or if both byte
      @@ -363,7 +363,7 @@ public static boolean arrayCompare(byte[] b1, byte[] b2) {
               }
               return java.security.MessageDigest.isEqual(b1, b2);
           }
      -  
      +
           /**
            * Is this particular KDF version number one that is sane? For that, we
            * just make sure it is inbounds of the valid range which is:
      @@ -385,7 +385,7 @@ public static boolean isValidKDFVersion(int kdfVers, boolean restrictToCurrent,
                       throws IllegalArgumentException
           {
               boolean ret = true;
      -        
      +
               if ( kdfVers < KeyDerivationFunction.originalVersion || kdfVers > 99991231 ) {
                   ret = false;
               } else if ( restrictToCurrent ) {
      @@ -396,14 +396,14 @@ public static boolean isValidKDFVersion(int kdfVers, boolean restrictToCurrent,
               } else {                    // False, so throw or not.
                   logger.warning(Logger.SECURITY_FAILURE, "Possible data tampering. Encountered invalid KDF version #. " +
                                  ( throwIfError ? "Throwing IllegalArgumentException" : "" ));
      -            if ( throwIfError ) {    
      +            if ( throwIfError ) {
                       throw new IllegalArgumentException("Version (" + kdfVers + ") invalid. " +
                           "Must be date in format of YYYYMMDD between " + KeyDerivationFunction.originalVersion + "and 99991231.");
                   }
               }
               return false;
           }
      -    
      +
           /**
            * Prevent public, no-argument CTOR from being auto-generated. Public CTOR
            * is not needed as all methods are static.
      diff --git a/src/main/java/org/owasp/esapi/crypto/CryptoToken.java b/src/main/java/org/owasp/esapi/crypto/CryptoToken.java
      index b8dc983d8..c12ee10dc 100644
      --- a/src/main/java/org/owasp/esapi/crypto/CryptoToken.java
      +++ b/src/main/java/org/owasp/esapi/crypto/CryptoToken.java
      @@ -1,15 +1,15 @@
       /**
        * 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 © 2010 - 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.
      - * 
      + *
        * @created 2010
        */
       package org.owasp.esapi.crypto;
      @@ -79,7 +79,7 @@
        * is, the value is not checked, so beware! When rendering these values, output
        * encoding may be required to prevent XSS. Use ESAPI's {@code Encoder} for that.
        * 

      - * This entire semicolon-separated string is then encrypted via one of the + * This entire semicolon-separated string is then encrypted via one of the * {@code Encryptor.encrypt()} methods and then base64-encoded, serialized * IV + ciphertext + MAC representation as determined by * {@code CipherTextasPortableSerializedByteArray()} is used as the @@ -100,17 +100,17 @@ public class CryptoToken { /** Represents an anonymous user. */ public static final String ANONYMOUS_USER = ""; - + // Default expiration time private static final long DEFAULT_EXP_TIME = 5 * 60 * 1000; // 5 min == 300 milliseconds private static final String DELIM = ";"; // field delimiter private static final char DELIM_CHAR = ';'; // field delim as a char private static final char QUOTE_CHAR = '\\'; // char used to quote delimiters, '=' and itself. - + // OPEN ISSUE: Should we make these 2 regex's properties in ESAPI.properties??? private static final String ATTR_NAME_REGEX = "[A-Za-z0-9_.-]+"; // One or more alphanumeric, underscore, periods, or hyphens. private static final String USERNAME_REGEX = "[a-z][a-z0-9_.@-]*"; - + private static Logger logger = ESAPI.getLogger("CryptoToken"); private String username = ANONYMOUS_USER; // Default user name if not set. Always lower case. @@ -121,10 +121,10 @@ public class CryptoToken { private transient SecretKey secretKey = null; private Pattern attrNameRegex = Pattern.compile(ATTR_NAME_REGEX); private Pattern userNameRegex = Pattern.compile(USERNAME_REGEX); - + /** * Create a cryptographic token using default secret key from the - * ESAPI.properties property Encryptor.MasterKey. + * ESAPI.properties property Encryptor.MasterKey. */ public CryptoToken() { secretKey = getDefaultSecretKey( @@ -137,7 +137,7 @@ public CryptoToken() { // Create using specified SecretKey /** * Create a cryptographic token using specified {@code SecretKey}. - * + * * @param skey The specified {@code SecretKey} to use to encrypt the token. */ public CryptoToken(SecretKey skey) { @@ -149,7 +149,7 @@ public CryptoToken(SecretKey skey) { expirationTime = now + DEFAULT_EXP_TIME; } - /** + /** * Create using previously encrypted token encrypted with default secret * key from ESAPI.properties. * @param token A previously encrypted token returned by one of the @@ -180,10 +180,10 @@ public CryptoToken(String token) throws EncryptionException { } } - /** + /** * Create cryptographic token using previously encrypted token that was * encrypted with specified secret key. - * + * * @param token A previously encrypted token returned by one of the * {@code getToken()} or {@code updateToken()} methods. * @throws EncryptionException Thrown if they are any problems while decrypting @@ -227,7 +227,7 @@ public CryptoToken(SecretKey skey, String token) throws EncryptionException { public String getUserAccountName() { return ( (username != null) ? username : ANONYMOUS_USER ); } - + /** * Set the user account name associated with this cryptographic token * object. The user account name is converted to lower case. @@ -243,10 +243,10 @@ public void setUserAccountName(String userAccountName) throws ValidationExceptio if ( userAccountName == null ) { throw new IllegalArgumentException("User account name may not be null."); } - + // Converting to lower case first allows a simpler regex. String userAcct = userAccountName.toLowerCase(); - + // Check to make sure that attribute name is valid as per our regex. Matcher userNameChecker = userNameRegex.matcher(userAcct); if ( userNameChecker.matches() ) { @@ -265,7 +265,7 @@ public void setUserAccountName(String userAccountName) throws ValidationExceptio public boolean isExpired() { return System.currentTimeMillis() > expirationTime; } - + /** * Set expiration time to expire in 'interval' seconds (NOT milliseconds). * @param intervalSecs Number of seconds in the future from current date/time @@ -274,7 +274,7 @@ public boolean isExpired() { public void setExpiration(int intervalSecs) throws IllegalArgumentException { int intervalMillis = intervalSecs * 1000; // Need to convert secs to millisec. - + // Don't want to use assertion here, because if they are disabled, // this would result in setting the expiration time prior to the // current time, hence it would already be expired. @@ -288,7 +288,7 @@ public void setExpiration(int intervalSecs) throws IllegalArgumentException preAdd(now, intervalMillis); expirationTime = now + intervalMillis; } - + /** * Set expiration time for a specific date/time. * @param expirationDate The date/time at which the token will fail. Must @@ -304,10 +304,10 @@ public void setExpiration(Date expirationDate) throws IllegalArgumentException long expTime = expirationDate.getTime(); if ( expTime <= curTime ) { throw new IllegalArgumentException("Expiration date must be after current date/time."); - } + } expirationTime = expTime; } - + /** * Return the expiration time in milliseconds since epoch time (midnight, * January 1, 1970 UTC). @@ -320,7 +320,7 @@ public long getExpiration() { assert expirationTime > 0L : "Programming error: Expiration time <= 0"; return expirationTime; } - + /** * Return the expiration time as a {@code Date}. * @return The {@code Date} object representing the expiration time. @@ -344,7 +344,7 @@ public void setAttribute(String name, String value) throws ValidationException { } if ( value == null ) { throw new ValidationException("Null attribute VALUE encountered for attr name " + name, - "Attribute VALUE may not be null; attr name: " + name); + "Attribute VALUE may not be null; attr name: " + name); } // NOTE: OTOH, it *is* VALID if the _value_ is empty! Null values cause too much trouble // to make it worth the effort of getting it to work consistently. @@ -359,12 +359,12 @@ public void setAttribute(String name, String value) throws ValidationException { ATTR_NAME_REGEX); } } - + /** * Add the specified collection of attributes to the current attributes. * If there are duplicate attributes specified, they will replace any * existing ones. - * + * * @param attrs Name/value pairs of attributes to add or replace the existing * attributes. Map must be non-null, but may be empty. * @throws ValidationException Thrown if one of the keys in the specified @@ -387,7 +387,7 @@ public void addAttributes(final Map attrs) throws ValidationExce } return; } - + /** * Retrieve the attribute with the specified name. * @param name The attribute name. @@ -397,13 +397,13 @@ public void addAttributes(final Map attrs) throws ValidationExce public String getAttribute(String name) { return attributes.get(name); } - + /** * Retrieve a {@code Map} that is a clone of all the attributes. A copy * is returned so that the attributes in {@code CrytpToken} are unaffected * by alterations made the returned {@code Map}. (Otherwise, multi-threaded code * could get trick. - * + * * @return A {@code Map} of all the attributes. * @see #getAttribute(String) */ @@ -412,7 +412,7 @@ public Map getAttributes() { // Unfortunately, this requires a cast, which requires us to supress warnings. return (Map) attributes.clone(); } - + /** * Removes all the attributes (if any) associated with this token. Note * that this does not clear / reset the user account name or expiration time. @@ -440,7 +440,7 @@ public void clearAttributes() { * SecretKey aliceSecretKey = ... // Shared with Alice * SecretKey bobSecretKey = ...; // Shared with Carol * CryptoToken cryptoToken = new CryptoToken(aliceSecretKey, tokenFromAlice); - * + * * // Re-encrypt for Carol using my (Bob's) key... * String tokenForCarol = cryptoToken.getToken(bobSecretKey); * // send tokenForCarol to Carol ... @@ -466,12 +466,12 @@ public void clearAttributes() { public String getToken(SecretKey skey) throws EncryptionException { return createEncryptedToken(skey); } - + /** * Update the (current) expiration time by adding the specified number of * seconds to it and then re-encrypting with the current {@code SecretKey} * that was used to construct this object. - * + * * @param additionalSecs The additional number of seconds to add to the * current expiration time. This number must be * >= 0 or otherwise an {@code IllegalArgumentException} @@ -493,7 +493,7 @@ public String updateToken(int additionalSecs) throws EncryptionException, Valida if ( additionalSecs < 0) { throw new IllegalArgumentException("additionalSecs argument must be >= 0."); } - + // Avoid integer overflow. This could happen if one first calls // setExpiration(Date) with a date far into the future. We want // to avoid overflows as they might lead to security vulnerabilities. @@ -503,14 +503,14 @@ public String updateToken(int additionalSecs) throws EncryptionException, Valida // 'long'. Could convert to Date first, and use // setExpiration(Date) but that hardly seems worth the trouble. expirationTime = curExpTime + (additionalSecs * 1000); - + if ( isExpired() ) { // Too bad there is no ProcrastinationException ;-) expirationTime = curExpTime; // Restore the original value (which still may // be expired. throw new ValidationException("Token timed out.", "Cryptographic token not increased to sufficient value to prevent timeout."); - + } // Don't change anything else (user acct name, attributes, skey, etc.) return getToken(); @@ -519,14 +519,14 @@ public String updateToken(int additionalSecs) throws EncryptionException, Valida /** * Return the new encrypted token as a base64-encoded string, encrypted with * the specified {@code SecretKey} with which this object was constructed. - * + * * @return The newly encrypted token. * @see #getToken(SecretKey) */ public String getToken() throws EncryptionException { return createEncryptedToken(secretKey); } - + // Create the actual encrypted token based on the specified SecretKey. // This method will ensure that the decrypted token always ends with an // unquoted delimiter. @@ -537,7 +537,7 @@ private String createEncryptedToken(SecretKey skey) throws EncryptionException { // If so, then updateToken() should also be revisited. sb.append( getExpiration() ).append( DELIM ); sb.append( getQuotedAttributes() ); - + Encryptor encryptor = ESAPI.encryptor(); CipherText ct = encryptor.encrypt(skey, new PlainText( sb.toString() ) ); String b64 = @@ -545,7 +545,7 @@ private String createEncryptedToken(SecretKey skey) throws EncryptionException { false); return b64; } - + // Return a string of all the attributes, properly quoted. This is used in // creating the encrypted token. Note that this method ensures that the // quoted attribute string always ends with an (quoted) delimiter. @@ -563,7 +563,7 @@ private String getQuotedAttributes() { } return sb.toString(); } - + // Do NOT define a toString() method as there may be sensitive // information contained in the attribute names. If we absolutely // need this, then only return the username and expiration time, and @@ -572,8 +572,8 @@ private String getQuotedAttributes() { /* * public String toString() { return null; } */ - - + + // Quote any special characters in value. private static String quoteAttributeValue(String value) { if ( value == null ) { @@ -592,7 +592,7 @@ private static String quoteAttributeValue(String value) { } return sb.toString(); } - + // Parse the possibly quoted value and return the unquoted value. private static String parseQuotedValue(String quotedValue) { StringBuilder sb = new StringBuilder(); @@ -608,7 +608,7 @@ private static String parseQuotedValue(String quotedValue) { } return sb.toString(); } - + /* * Decrypt the encrypted token and parse it into the individual components. * The string should always end with a semicolon (;) even when there are @@ -682,9 +682,9 @@ private void decryptToken(SecretKey skey, String b64token) throws EncryptionExce fields.add( record ); fieldNo++; prevPos = curPos; - } + } } - + Object[] objArray = fields.toArray(); if ( fieldNo != objArray.length ) { String exm = "Programming error???: Mismatch of delimited field count."; @@ -698,7 +698,7 @@ private void decryptToken(SecretKey skey, String b64token) throws EncryptionExce username = ((String)(objArray[0])).toLowerCase(); String expTime = (String)objArray[1]; expirationTime = Long.parseLong(expTime); - + for( int i = 2; i < objArray.length; i++ ) { String nvpair = (String)objArray[i]; int equalsAt = nvpair.indexOf("="); @@ -726,7 +726,7 @@ private void decryptToken(SecretKey skey, String b64token) throws EncryptionExce } return; } - + private SecretKey getDefaultSecretKey(String encryptAlgorithm) { if ( encryptAlgorithm == null ) { throw new IllegalArgumentException("Encryption algorithm cannot be null"); @@ -745,7 +745,7 @@ private SecretKey getDefaultSecretKey(String encryptAlgorithm) { // decryption. return new SecretKeySpec(skey, encryptAlgorithm ); } - + // Check precondition to see if addition of two operands will result in // arithmetic overflow. Note that the operands are of two different // integral types. I.e., check to see if: diff --git a/src/main/java/org/owasp/esapi/crypto/KeyDerivationFunction.java b/src/main/java/org/owasp/esapi/crypto/KeyDerivationFunction.java index 51032eec7..02f925bfb 100644 --- a/src/main/java/org/owasp/esapi/crypto/KeyDerivationFunction.java +++ b/src/main/java/org/owasp/esapi/crypto/KeyDerivationFunction.java @@ -1,6 +1,6 @@ /* * 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. @@ -60,7 +60,7 @@ public class KeyDerivationFunction { public static final int originalVersion = 20110203; // First version. Do not change. EVER! public static final int kdfVersion = 20130830; // Current version. Format: YYYYMMDD, max is 99991231. private static final long serialVersionUID = kdfVersion; // Format: YYYYMMDD - + // Pseudo-random function algorithms suitable for NIST KDF in counter mode. // Note that HmacMD5 is intentionally omitted here!!! public enum PRF_ALGORITHMS { @@ -81,17 +81,17 @@ public enum PRF_ALGORITHMS { // Reserved for future use -- values 8 through 15 // Most likely these might be some other strong contenders that // were are based on HMACs from the NIST SHA-3 finalists. - + private final byte value; // Value stored in serialized encrypted data to represent PRF private final short bits; private final String algName; - + PRF_ALGORITHMS(int value, int bits, String algName) { this.value = (byte) value; this.bits = (short) bits; this.algName = algName; } - + public byte getValue() { return value; } public short getBits() { return bits; } public String getAlgName() { return algName; } @@ -115,7 +115,7 @@ public enum PRF_ALGORITHMS { throw new ExceptionInInitializerError("Versions of CipherTextSerializer and KeyDerivationFunction are not compatible."); } } - + /** * Construct a {@code KeyDerivationFunction}. * @param prfAlg Specifies a supported algorithm. @@ -128,7 +128,7 @@ public KeyDerivationFunction(KeyDerivationFunction.PRF_ALGORITHMS prfAlg) { * Construct a {@code KeyDerivationFunction} based on the * ESAPI.property property, {@code Encryptor.KDF.PRF}. */ - public KeyDerivationFunction() { + public KeyDerivationFunction() { String prfName = ESAPI.securityConfiguration().getKDFPseudoRandomFunction(); if ( ! KeyDerivationFunction.isValidPRF(prfName) ) { throw new ConfigurationException("Algorithm name " + prfName + @@ -144,12 +144,12 @@ public KeyDerivationFunction() { * @return The PRF algorithm name. */ public String getPRFAlgName() { - return prfAlg_; + return prfAlg_; } - + /** * Package level method for use by {@code CipherText} class to get default - * + * */ static int getDefaultPRFSelection() { String prfName = ESAPI.securityConfiguration().getKDFPseudoRandomFunction(); @@ -161,7 +161,7 @@ static int getDefaultPRFSelection() { throw new ConfigurationException("Algorithm name " + prfName + " not a valid algorithm name for property " + KDF_PRF_ALG); } - + /** * Set version so backward compatibility can be supported. Used to set the * version to some previous version so that previously encrypted data can @@ -184,8 +184,8 @@ public void setVersion(int version) throws IllegalArgumentException { public int getVersion() { return version_; } - - + + // TODO: IMPORTANT NOTE: In a future release (hopefully starting in 2.3), // we will be using the 'context' to mix in some additional things. At a // minimum, we will be using the KDF version (version_) so that downgrade version @@ -195,7 +195,7 @@ public int getVersion() { * Set the 'context' as specified by NIST Special Publication 800-108. NIST * defines 'context' as "A binary string containing the information related * to the derived keying material. It may include identities of parties who - * are deriving and/or using the derived keying material and, optionally, a + * are deriving and/or using the derived keying material and, optionally, a * once known by the parties who derive the keys." NIST SP 800-108 seems to * imply that while 'context' is recommended, that it is optional. In section * 7.6 of NIST 800-108, NIST uses "SHOULD" rather than "MUST": @@ -215,7 +215,7 @@ public int getVersion() { * 'context' data is not specified at all. Therefore, ESAPI 2.0's * reference implementation, {@code JavaEncryptor}, chooses not to use * 'context' at all. - * + * * @param context Optional binary string containing information related to * the derived keying material. By default (if this method * is never called), the empty string is used. May have any @@ -227,7 +227,7 @@ public void setContext(String context) { } context_ = context; } - + /** * Return the optional 'context' that typically contains information * related to the keying material, such as the identities of the message @@ -255,7 +255,7 @@ public String getContext() { * It is used by ESAPI's reference crypto implementation class {@code JavaEncryptor} * and might be useful for someone implementing their own replacement class, but * generally it is not something that is useful to application client code. - * + * * @param keyDerivationKey A key used as an input to a key derivation function * to derive other keys. This is the key that generally * is created using some key generation mechanism such as @@ -275,7 +275,7 @@ public String getContext() { * be set to anything other than {@code null} or an empty string when called outside * of ESAPI's {@code JavaEncryptor} reference implementation (but you must consistent). * @return The derived {@code SecretKey} to be used according - * to the specified purpose. + * to the specified purpose. * @throws NoSuchAlgorithmException The {@code keyDerivationKey} has an unsupported * encryption algorithm or no current JCE provider supports requested * Hmac algorithrm used for the PRF for key generation. @@ -356,7 +356,7 @@ public SecretKey computeDerivedKey(SecretKey keyDerivationKey, int keySize, Stri throw new EncryptionException("Encryption failure (internal encoding error: UTF-8)", "UTF-8 encoding is NOT supported as a standard byte encoding: " + e.getMessage(), e); } - + // Note that keyDerivationKey is going to be some SecretKey like an AES or // DESede key, but not an HmacSHA1 key. That means it is not likely // going to be 20 bytes but something different. Experiments show @@ -379,7 +379,7 @@ public SecretKey computeDerivedKey(SecretKey keyDerivationKey, int keySize, Stri sk.getAlgorithm(), ex); throw ex; } - + // Repeatedly call of PRF Hmac until we've collected enough bits // for the derived key. The first time through, we calculate the HmacSHA1 // on the "purpose" string, but subsequent calculations are performed @@ -408,14 +408,14 @@ public SecretKey computeDerivedKey(SecretKey keyDerivationKey, int keySize, Stri // document (Section 7.6) implies that Context is to be an // optional field (based on NIST's use of the word SHOULD // rather than MUST) - // + // mac.update( ByteConversionUtil.fromInt( ctr++ ) ); mac.update(label); mac.update((byte) '\0'); mac.update(context); // This is problematic for us. See Jeff Walton's // analysis of ESAPI 2.0's KDF for details. // Maybe for 2.1, we'll see; 2.0 too close to GA. - + // According to the Javadoc for Mac.doFinal(byte[]), // "A call to this method resets this Mac object to the state it was // in when previously initialized via a call to init(Key) or @@ -424,7 +424,7 @@ public SecretKey computeDerivedKey(SecretKey keyDerivationKey, int keySize, Stri // desired, via new calls to update and doFinal." Therefore, we do // not do an explicit reset(). tmpKey = mac.doFinal( ByteConversionUtil.fromInt( keySize ) ); - + if ( tmpKey.length >= keySize ) { len = keySize; } else { @@ -435,7 +435,7 @@ public SecretKey computeDerivedKey(SecretKey keyDerivationKey, int keySize, Stri totalCopied += tmpKey.length; destPos += len; } while( totalCopied < keySize ); - + // Don't leave remnants of the partial key in memory. (Note: we could // not do this if tmpKey were declared in the do-while loop. // Of course, in reality, trying to stomp these bits out is probably not @@ -451,7 +451,7 @@ public SecretKey computeDerivedKey(SecretKey keyDerivationKey, int keySize, Stri tmpKey[i] = '\0'; } tmpKey = null; // Make it immediately eligible for GC. - + // Convert it back into a SecretKey of the appropriate type. return new SecretKeySpec(derivedKey, keyDerivationKey.getAlgorithm()); } @@ -479,16 +479,16 @@ public static PRF_ALGORITHMS convertNameToPRF(String prfAlgName) { throw new IllegalArgumentException("Algorithm name " + prfAlgName + " not a valid PRF algorithm name for the ESAPI KDF."); } - + public static PRF_ALGORITHMS convertIntToPRF(int selection) { for (PRF_ALGORITHMS prf : PRF_ALGORITHMS.values()) { if ( prf.getValue() == selection ) { return prf; } } - throw new IllegalArgumentException("No KDF PRF algorithm found for value name " + selection); + throw new IllegalArgumentException("No KDF PRF algorithm found for value name " + selection); } - + /** * Calculate the size of a key. The key size is given in bits, but we * can only allocate them by octets (i.e., bytes), so make sure we diff --git a/src/main/java/org/owasp/esapi/crypto/PlainText.java b/src/main/java/org/owasp/esapi/crypto/PlainText.java index 5f504cba1..60fda894c 100644 --- a/src/main/java/org/owasp/esapi/crypto/PlainText.java +++ b/src/main/java/org/owasp/esapi/crypto/PlainText.java @@ -31,9 +31,9 @@ public final class PlainText implements Serializable { private static final long serialVersionUID = 20090921; private static Logger logger = ESAPI.getLogger("PlainText"); - + private byte[] rawBytes = null; - + /** * Construct a {@code PlainText} object from a {@code String}. * @param str The {@code String} that is converted to a UTF-8 encoded @@ -68,7 +68,7 @@ public PlainText(byte[] b) { rawBytes = new byte[ b.length ]; System.arraycopy(b, 0, rawBytes, 0, b.length); } - + /** * Convert the {@code PlainText} object to a UTF-8 encoded {@code String}. * @return A {@code String} representing the {@code PlainText} object. @@ -82,7 +82,7 @@ public String toString() { throw new RuntimeException("Can't find UTF-8 byte-encoding!", e); } } - + /** * Convert the {@code PlainText} object to a byte array. * @return A byte array representing the {@code PlainText} object. @@ -92,7 +92,7 @@ public byte[] asBytes() { System.arraycopy(rawBytes, 0, bytes, 0, rawBytes.length); return bytes; } - + /** * {@inheritDoc} */ @@ -109,7 +109,7 @@ public byte[] asBytes() { } return result; } - + /** * Same as {@code this.toString().hashCode()}. * @return {@code this.toString().hashCode()}. @@ -117,20 +117,20 @@ public byte[] asBytes() { @Override public int hashCode() { return this.toString().hashCode(); } - + /** * Return the length of the UTF-8 encoded byte array representing this * object. Note that if this object was constructed with the constructor * {@code PlainText(String str)}, then this length might not necessarily * agree with {@code str.length()}. - * + * * @return The length of the UTF-8 encoded byte array representing this * object. */ public int length() { return rawBytes.length; } - + // DISCUSS: Should we set 'rawBytes' to null??? Won't make it eligible for // GC unless this PlainText object is set to null which can't do // from here. If we set it to null, most methods will cause @@ -143,7 +143,7 @@ public void overwrite() { CryptoHelper.overwrite( rawBytes ); // rawBytes = null; // See above comment re: discussion. } - + /** * Needed for correct definition of equals for general classes. * (Technically not needed for 'final' classes though like this class diff --git a/src/main/java/org/owasp/esapi/crypto/SecurityProviderLoader.java b/src/main/java/org/owasp/esapi/crypto/SecurityProviderLoader.java index cd4efd34e..a5cbd708c 100644 --- a/src/main/java/org/owasp/esapi/crypto/SecurityProviderLoader.java +++ b/src/main/java/org/owasp/esapi/crypto/SecurityProviderLoader.java @@ -8,7 +8,7 @@ import org.owasp.esapi.ESAPI; import org.owasp.esapi.Logger; -/** +/** * This class provides a generic static method that loads a * {@code java.security.Provider} either by some generic name * (i.e., {@code Provider.getName()}) or by a fully-qualified class name. @@ -43,14 +43,14 @@ public class SecurityProviderLoader { // with Sun-based JREs. As of JDK 1.3 and later, it is part of the // standard JRE install. jceProviders.put("SunJCE", "com.sun.crypto.provider.SunJCE"); - + // IBMJCE is default for WebSphere and is used by IBM JDKs. They // also have IBMJCEFIPS, but not sure if this is *always* provided // with WebSphere or just an add-on, hence not including it. IBMJCEFIPS // is a FIPS 140-2 compliant JCE provider from IBM. jceProviders.put("IBMJCE", "com.ibm.crypto.provider.IBMJCE"); // jceProviders.put("IBMJCEFIPS", "com.ibm.crypto.fips.provider.IBMJCEFIPS"); - + // GnuCrypto is JCE provider for GNU Compiler for Java (GCJ) jceProviders.put("GnuCrypto", "gnu.crypto.jce.GnuCrypto"); @@ -79,9 +79,9 @@ public class SecurityProviderLoader { jceProviders.put("ABA", "au.net.aba.crypto.provider.ABAProvider"); } - /** + /** * This methods adds a provider to the {@code SecurityManager} - * either by some generic name or by the class name. + * either by some generic name or by the class name. *

      * The following generic JCE provider names are built-in: *

        @@ -245,7 +245,7 @@ public static int insertProviderAt(String algProvider, int pos) "; exception msg: " + ex.toString()); } } - + /** * Load the preferred JCE provider for ESAPI based on the ESAPI.properties * property {@code Encryptor.PreferredJCEProvider}. If this property is null diff --git a/src/main/java/org/owasp/esapi/errors/AccessControlException.java b/src/main/java/org/owasp/esapi/errors/AccessControlException.java index 197f12d96..fbc537f3d 100644 --- a/src/main/java/org/owasp/esapi/errors/AccessControlException.java +++ b/src/main/java/org/owasp/esapi/errors/AccessControlException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -18,7 +18,7 @@ /** * An AccessControlException should be thrown when a user attempts to access a * resource that they are not authorized for. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class AccessControlException extends EnterpriseSecurityException { @@ -45,7 +45,7 @@ public AccessControlException(String userMessage, String logMessage) { /** * Instantiates a new access control exception. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged * @param cause the root cause diff --git a/src/main/java/org/owasp/esapi/errors/AuthenticationAccountsException.java b/src/main/java/org/owasp/esapi/errors/AuthenticationAccountsException.java index d59fa6911..a08b02c88 100644 --- a/src/main/java/org/owasp/esapi/errors/AuthenticationAccountsException.java +++ b/src/main/java/org/owasp/esapi/errors/AuthenticationAccountsException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -19,7 +19,7 @@ * An AuthenticationException should be thrown when anything goes wrong during * login or logout. They are also appropriate for any problems related to * identity management. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class AuthenticationAccountsException extends AuthenticationException { @@ -36,10 +36,10 @@ protected AuthenticationAccountsException() { /** * Creates a new instance of {@code AuthenticationAccountsException}. - * + * * @param userMessage the message displayed to the user - * @param logMessage the message logged - * + * @param logMessage the message logged + * */ public AuthenticationAccountsException(String userMessage, String logMessage) { super(userMessage, logMessage); @@ -47,7 +47,7 @@ public AuthenticationAccountsException(String userMessage, String logMessage) { /** * Instantiates a new authentication exception. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged * @param cause the root cause diff --git a/src/main/java/org/owasp/esapi/errors/AuthenticationCredentialsException.java b/src/main/java/org/owasp/esapi/errors/AuthenticationCredentialsException.java index c50019cf5..ad3d8df6b 100644 --- a/src/main/java/org/owasp/esapi/errors/AuthenticationCredentialsException.java +++ b/src/main/java/org/owasp/esapi/errors/AuthenticationCredentialsException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -19,7 +19,7 @@ * An AuthenticationException should be thrown when anything goes wrong during * login or logout. They are also appropriate for any problems related to * identity management. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class AuthenticationCredentialsException extends AuthenticationException { @@ -36,7 +36,7 @@ protected AuthenticationCredentialsException() { /** * Creates a new instance of {@code AuthenticationCredentialsException}. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged */ @@ -46,7 +46,7 @@ public AuthenticationCredentialsException(String userMessage, String logMessage) /** * Instantiates a new authentication exception. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged * @param cause the root cause diff --git a/src/main/java/org/owasp/esapi/errors/AuthenticationException.java b/src/main/java/org/owasp/esapi/errors/AuthenticationException.java index 0f350bad9..55abbc370 100644 --- a/src/main/java/org/owasp/esapi/errors/AuthenticationException.java +++ b/src/main/java/org/owasp/esapi/errors/AuthenticationException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -19,7 +19,7 @@ * An AuthenticationException should be thrown when anything goes wrong during * login or logout. They are also appropriate for any problems related to * identity management. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class AuthenticationException extends EnterpriseSecurityException { @@ -36,7 +36,7 @@ protected AuthenticationException() { /** * Creates a new instance of {@code AuthenticationException}. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged */ @@ -46,7 +46,7 @@ public AuthenticationException(String userMessage, String logMessage) { /** * Instantiates a new authentication exception. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged * @param cause the root cause diff --git a/src/main/java/org/owasp/esapi/errors/AuthenticationHostException.java b/src/main/java/org/owasp/esapi/errors/AuthenticationHostException.java index 1e5fe2577..4010d79b1 100644 --- a/src/main/java/org/owasp/esapi/errors/AuthenticationHostException.java +++ b/src/main/java/org/owasp/esapi/errors/AuthenticationHostException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -18,7 +18,7 @@ /** * An AuthenticationHostException should be thrown when there is a problem with * the host involved with authentication, particularly if the host changes unexpectedly. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class AuthenticationHostException extends AuthenticationException { @@ -35,7 +35,7 @@ protected AuthenticationHostException() { /** * Creates a new instance of AuthenticationHostException. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged */ @@ -45,7 +45,7 @@ public AuthenticationHostException(String userMessage, String logMessage) { /** * Instantiates a new authentication exception. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged * @param cause the cause diff --git a/src/main/java/org/owasp/esapi/errors/AuthenticationLoginException.java b/src/main/java/org/owasp/esapi/errors/AuthenticationLoginException.java index 3d63400fb..0f7a3d855 100644 --- a/src/main/java/org/owasp/esapi/errors/AuthenticationLoginException.java +++ b/src/main/java/org/owasp/esapi/errors/AuthenticationLoginException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -19,7 +19,7 @@ * An AuthenticationException should be thrown when anything goes wrong during * login or logout. They are also appropriate for any problems related to * identity management. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class AuthenticationLoginException extends AuthenticationException { @@ -36,7 +36,7 @@ protected AuthenticationLoginException() { /** * Creates a new instance of EnterpriseSecurityException. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged */ @@ -46,7 +46,7 @@ public AuthenticationLoginException(String userMessage, String logMessage) { /** * Instantiates a new authentication exception. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged * @param cause the cause diff --git a/src/main/java/org/owasp/esapi/errors/AvailabilityException.java b/src/main/java/org/owasp/esapi/errors/AvailabilityException.java index 7c7a17e02..98099155d 100644 --- a/src/main/java/org/owasp/esapi/errors/AvailabilityException.java +++ b/src/main/java/org/owasp/esapi/errors/AvailabilityException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -19,7 +19,7 @@ * An AvailabilityException should be thrown when the availability of a limited * resource is in jeopardy. For example, if a database connection pool runs out * of connections, an availability exception should be thrown. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class AvailabilityException extends EnterpriseSecurityException { @@ -36,7 +36,7 @@ protected AvailabilityException() { /** * Creates a new instance of AvailabilityException. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged */ @@ -46,7 +46,7 @@ public AvailabilityException(String userMessage, String logMessage) { /** * Instantiates a new AvailabilityException. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged * @param cause the cause diff --git a/src/main/java/org/owasp/esapi/errors/CertificateException.java b/src/main/java/org/owasp/esapi/errors/CertificateException.java index ee98f2dc1..561d41179 100644 --- a/src/main/java/org/owasp/esapi/errors/CertificateException.java +++ b/src/main/java/org/owasp/esapi/errors/CertificateException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -18,7 +18,7 @@ /** * A CertificateException should be thrown for any problems that arise during * processing of digital certificates. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class CertificateException extends EnterpriseSecurityException { @@ -35,7 +35,7 @@ protected CertificateException() { /** * Creates a new instance of CertificateException. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged */ @@ -45,7 +45,7 @@ public CertificateException(String userMessage, String logMessage) { /** * Instantiates a new CertificateException. - * + * * @param userMessage the message displayed to the user * @param logMessage the message logged * @param cause the cause diff --git a/src/main/java/org/owasp/esapi/errors/ConfigurationException.java b/src/main/java/org/owasp/esapi/errors/ConfigurationException.java index c6173f418..17d6a6b3e 100644 --- a/src/main/java/org/owasp/esapi/errors/ConfigurationException.java +++ b/src/main/java/org/owasp/esapi/errors/ConfigurationException.java @@ -23,11 +23,11 @@ public ConfigurationException(Exception e) { public ConfigurationException(String s) { super(s); } - + public ConfigurationException(String s, Throwable cause) { super(s, cause); } - + public ConfigurationException(Throwable cause) { super(cause); } diff --git a/src/main/java/org/owasp/esapi/errors/EncodingException.java b/src/main/java/org/owasp/esapi/errors/EncodingException.java index 9c53d0d1c..cee3abf2b 100644 --- a/src/main/java/org/owasp/esapi/errors/EncodingException.java +++ b/src/main/java/org/owasp/esapi/errors/EncodingException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -18,7 +18,7 @@ /** * An EncodingException should be thrown for any problems that occur when * encoding or decoding data. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class EncodingException extends EnterpriseSecurityException { @@ -35,7 +35,7 @@ protected EncodingException() { /** * Creates a new instance of EncodingException. - * + * * @param userMessage * the message displayed to the user * @param logMessage @@ -47,7 +47,7 @@ public EncodingException(String userMessage, String logMessage) { /** * Instantiates a new EncodingException. - * + * * @param userMessage * the message displayed to the user * @param logMessage diff --git a/src/main/java/org/owasp/esapi/errors/EncryptionException.java b/src/main/java/org/owasp/esapi/errors/EncryptionException.java index 8a70fe70d..895d34eb7 100644 --- a/src/main/java/org/owasp/esapi/errors/EncryptionException.java +++ b/src/main/java/org/owasp/esapi/errors/EncryptionException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -18,7 +18,7 @@ /** * An EncryptionException should be thrown for any problems related to * encryption, hashing, or digital signatures. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class EncryptionException extends EnterpriseSecurityException { @@ -35,7 +35,7 @@ protected EncryptionException() { /** * Creates a new instance of EncryptionException. - * + * * @param userMessage * the message displayed to the user * @param logMessage @@ -47,7 +47,7 @@ public EncryptionException(String userMessage, String logMessage) { /** * Instantiates a new EncryptionException. - * + * * @param userMessage * the message displayed to the user * @param logMessage diff --git a/src/main/java/org/owasp/esapi/errors/EncryptionRuntimeException.java b/src/main/java/org/owasp/esapi/errors/EncryptionRuntimeException.java index 1b46d383f..cdc484324 100644 --- a/src/main/java/org/owasp/esapi/errors/EncryptionRuntimeException.java +++ b/src/main/java/org/owasp/esapi/errors/EncryptionRuntimeException.java @@ -1,12 +1,12 @@ /** * 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) 2010 - 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. * @@ -18,7 +18,7 @@ /** * An EncryptionRuntimeException should be thrown for any problems related to * encryption, hashing, or digital signatures. - * + * * @author August Detlefsen (augustd at codemagi dot com) * CodeMagi, Inc. * @since October 8, 2010 @@ -37,7 +37,7 @@ protected EncryptionRuntimeException() { /** * Creates a new instance of EncryptionException. - * + * * @param userMessage * the message displayed to the user * @param logMessage @@ -49,7 +49,7 @@ public EncryptionRuntimeException(String userMessage, String logMessage) { /** * Instantiates a new EncryptionException. - * + * * @param userMessage * the message displayed to the user * @param logMessage diff --git a/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityException.java b/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityException.java index 4e05d0cf7..6b150bb42 100644 --- a/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityException.java +++ b/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -90,8 +90,8 @@ protected EnterpriseSecurityException(String userMessage, Throwable cause) * It should be noted that messages that are intended to be displayed to the user should be safe for display. In * other words, don't pass in unsanitized data here. Also could hold true for the logging message depending on the * context of the exception. - * - * @param userMessage + * + * @param userMessage * the message displayed to the user * @param logMessage * the message logged @@ -106,7 +106,7 @@ public EnterpriseSecurityException(String userMessage, String logMessage) { /** * Creates a new instance of EnterpriseSecurityException that includes a root cause Throwable. - * + * * It should be noted that messages that are intended to be displayed to the user should be safe for display. In * other words, don't pass in unsanitized data here. Also could hold true for the logging message depending on the * context of the exception. @@ -124,13 +124,13 @@ public EnterpriseSecurityException(String userMessage, String logMessage, Throwa ESAPI.intrusionDetector().addException(this); } } - + /** * Returns message meant for display to users * * Note that if you are unsure of what set this message, it would probably * be a good idea to encode this message before displaying it to the end user. - * + * * @return a String containing a message that is safe to display to users */ public String getUserMessage() { @@ -141,7 +141,7 @@ public String getUserMessage() { * Returns a message that is safe to display in logs, but may contain * sensitive information and therefore probably should not be displayed to * users. - * + * * @return a String containing a message that is safe to display in logs, * but probably not to users as it may contain sensitive information. */ diff --git a/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityRuntimeException.java b/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityRuntimeException.java index 8097bcdf0..3b511c321 100644 --- a/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityRuntimeException.java +++ b/src/main/java/org/owasp/esapi/errors/EnterpriseSecurityRuntimeException.java @@ -1,12 +1,12 @@ /** * 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) 2010 - 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. * @@ -32,7 +32,7 @@ * used extensively throughout ESAPI implementations and the result is a fairly complete set of security log records. * ALL EnterpriseSecurityRuntimeExceptions are also sent to the IntrusionDetector for use in detecting anomalous patterns of * application usage. - * + * * @author August Detlefsen (augustd at codemagi dot com) * CodeMagi, Inc. * @since October 8, 2010 @@ -91,8 +91,8 @@ protected EnterpriseSecurityRuntimeException(String userMessage, * It should be noted that messages that are intended to be displayed to the user should be safe for display. In * other words, don't pass in unsanitized data here. Also could hold true for the logging message depending on the * context of the exception. - * - * @param userMessage + * + * @param userMessage * the message displayed to the user * @param logMessage * the message logged @@ -107,7 +107,7 @@ public EnterpriseSecurityRuntimeException(String userMessage, String logMessage) /** * Creates a new instance of EnterpriseSecurityException that includes a root cause Throwable. - * + * * It should be noted that messages that are intended to be displayed to the user should be safe for display. In * other words, don't pass in unsanitized data here. Also could hold true for the logging message depending on the * context of the exception. @@ -125,13 +125,13 @@ public EnterpriseSecurityRuntimeException(String userMessage, String logMessage, ESAPI.intrusionDetector().addException(this); } } - + /** * Returns message meant for display to users * * Note that if you are unsure of what set this message, it would probably * be a good idea to encode this message before displaying it to the end user. - * + * * @return a String containing a message that is safe to display to users */ public String getUserMessage() { @@ -142,7 +142,7 @@ public String getUserMessage() { * Returns a message that is safe to display in logs, but may contain * sensitive information and therefore probably should not be displayed to * users. - * + * * @return a String containing a message that is safe to display in logs, * but probably not to users as it may contain sensitive information. */ diff --git a/src/main/java/org/owasp/esapi/errors/ExecutorException.java b/src/main/java/org/owasp/esapi/errors/ExecutorException.java index 5676e1eb9..9adda9296 100644 --- a/src/main/java/org/owasp/esapi/errors/ExecutorException.java +++ b/src/main/java/org/owasp/esapi/errors/ExecutorException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -18,7 +18,7 @@ /** * An ExecutorException should be thrown for any problems that arise during the * execution of a system executable. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class ExecutorException extends EnterpriseSecurityException { @@ -35,7 +35,7 @@ protected ExecutorException() { /** * Creates a new instance of ExecutorException. - * + * * @param userMessage * the message to display to users * @param logMessage @@ -47,7 +47,7 @@ public ExecutorException(String userMessage, String logMessage) { /** * Instantiates a new ExecutorException. - * + * * @param userMessage * the message to display to users * @param logMessage diff --git a/src/main/java/org/owasp/esapi/errors/IntegrityException.java b/src/main/java/org/owasp/esapi/errors/IntegrityException.java index 07fad5adc..92a546a2a 100644 --- a/src/main/java/org/owasp/esapi/errors/IntegrityException.java +++ b/src/main/java/org/owasp/esapi/errors/IntegrityException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -19,7 +19,7 @@ * An IntegrityException should be thrown when a problem with the integrity of data * has been detected. For example, if a financial account cannot be reconciled after * a transaction has been performed, an integrity exception should be thrown. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class IntegrityException extends EnterpriseSecurityException { @@ -36,7 +36,7 @@ protected IntegrityException() { /** * Creates a new instance of IntegrityException. - * + * * @param userMessage * the message to display to users * @param logMessage @@ -48,7 +48,7 @@ public IntegrityException(String userMessage, String logMessage) { /** * Instantiates a new IntegrityException. - * + * * @param userMessage * the message to display to users * @param logMessage diff --git a/src/main/java/org/owasp/esapi/errors/IntrusionException.java b/src/main/java/org/owasp/esapi/errors/IntrusionException.java index 472e3076b..72261d9e1 100644 --- a/src/main/java/org/owasp/esapi/errors/IntrusionException.java +++ b/src/main/java/org/owasp/esapi/errors/IntrusionException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -25,7 +25,7 @@ *

        * Unlike other exceptions in the ESAPI, the IntrusionException is a RuntimeException so that it can be thrown from * anywhere and will not require a lot of special exception handling. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class IntrusionException extends EnterpriseSecurityRuntimeException { @@ -43,7 +43,7 @@ public class IntrusionException extends EnterpriseSecurityRuntimeException { /** * Creates a new instance of IntrusionException. - * + * * @param userMessage * the message to display to users * @param logMessage @@ -57,12 +57,12 @@ public IntrusionException(String userMessage, String logMessage) { /** * Instantiates a new intrusion exception. - * + * * @param userMessage * the message to display to users * @param logMessage * the message logged - * @param cause + * @param cause * the cause */ public IntrusionException(String userMessage, String logMessage, Throwable cause) { @@ -73,7 +73,7 @@ public IntrusionException(String userMessage, String logMessage, Throwable cause /** * Returns a String containing a message that is safe to display to users - * + * * @return a String containing a message that is safe to display to users */ public String getUserMessage() { @@ -82,7 +82,7 @@ public String getUserMessage() { /** * Returns a String that is safe to display in logs, but probably not to users - * + * * @return a String containing a message that is safe to display in logs, but probably not to users */ public String getLogMessage() { diff --git a/src/main/java/org/owasp/esapi/errors/ValidationAvailabilityException.java b/src/main/java/org/owasp/esapi/errors/ValidationAvailabilityException.java index 02136dab6..5274da5d8 100644 --- a/src/main/java/org/owasp/esapi/errors/ValidationAvailabilityException.java +++ b/src/main/java/org/owasp/esapi/errors/ValidationAvailabilityException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -49,7 +49,7 @@ public ValidationAvailabilityException(String userMessage, String logMessage) { * the message logged * @param cause * the cause - */ + */ public ValidationAvailabilityException(String userMessage, String logMessage, Throwable cause) { super(userMessage, logMessage, cause); } diff --git a/src/main/java/org/owasp/esapi/errors/ValidationException.java b/src/main/java/org/owasp/esapi/errors/ValidationException.java index b93990890..c185574fb 100644 --- a/src/main/java/org/owasp/esapi/errors/ValidationException.java +++ b/src/main/java/org/owasp/esapi/errors/ValidationException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -19,7 +19,7 @@ * A ValidationException should be thrown to indicate that the data provided by * the user or from some other external source does not match the validation * rules that have been specified for that data. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class ValidationException extends EnterpriseSecurityException { @@ -38,7 +38,7 @@ protected ValidationException() { /** * Creates a new instance of ValidationException. - * + * * @param userMessage * the message to display to users * @param logMessage @@ -50,7 +50,7 @@ public ValidationException(String userMessage, String logMessage) { /** * Instantiates a new ValidationException. - * + * * @param userMessage * the message to display to users * @param logMessage @@ -61,10 +61,10 @@ public ValidationException(String userMessage, String logMessage) { public ValidationException(String userMessage, String logMessage, Throwable cause) { super(userMessage, logMessage, cause); } - + /** * Creates a new instance of ValidationException. - * + * * @param userMessage * the message to display to users * @param logMessage @@ -76,10 +76,10 @@ public ValidationException(String userMessage, String logMessage, String context super(userMessage, logMessage); setContext(context); } - + /** * Instantiates a new ValidationException. - * + * * @param userMessage * the message to display to users * @param logMessage @@ -93,10 +93,10 @@ public ValidationException(String userMessage, String logMessage, Throwable caus super(userMessage, logMessage, cause); setContext(context); } - + /** * Returns the UI reference that caused this ValidationException - * + * * @return context, the source that caused the exception, stored as a string */ public String getContext() { @@ -105,7 +105,7 @@ public String getContext() { /** * Set's the UI reference that caused this ValidationException - * + * * @param context * the context to set, passed as a String */ diff --git a/src/main/java/org/owasp/esapi/errors/ValidationUploadException.java b/src/main/java/org/owasp/esapi/errors/ValidationUploadException.java index 41e2e7ce8..825f15430 100644 --- a/src/main/java/org/owasp/esapi/errors/ValidationUploadException.java +++ b/src/main/java/org/owasp/esapi/errors/ValidationUploadException.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -32,7 +32,7 @@ protected ValidationUploadException() { /** * Create a new ValidationException - * + * * @param userMessage * the message to display to users * @param logMessage @@ -44,7 +44,7 @@ public ValidationUploadException(String userMessage, String logMessage) { /** * Create a new ValidationException - * + * * @param userMessage * the message to display to users * @param logMessage diff --git a/src/main/java/org/owasp/esapi/filters/ClickjackFilter.java b/src/main/java/org/owasp/esapi/filters/ClickjackFilter.java index c9a55d4a1..e10a4e163 100644 --- a/src/main/java/org/owasp/esapi/filters/ClickjackFilter.java +++ b/src/main/java/org/owasp/esapi/filters/ClickjackFilter.java @@ -1,15 +1,15 @@ /** * 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 February 6, 2009 */ @@ -37,7 +37,7 @@ * <param-value>DENY</param-value> * </init-param> * </filter> - * + * * <filter> * <filter-name>ClickjackFilterSameOrigin</filter-name> * <filter-class>org.owasp.filters.ClickjackFilter</filter-class> @@ -46,15 +46,15 @@ * <param-value>SAMEORIGIN</param-value> * </init-param> * </filter> - * + * * <!-- use the Deny version to prevent anyone, including yourself, from framing the page --> - * <filter-mapping> + * <filter-mapping> * <filter-name>ClickjackFilterDeny</filter-name> * <url-pattern>/*</url-pattern> * </filter-mapping> - * + * * <!-- use the SameOrigin version to allow your application to frame, but nobody else - * <filter-mapping> + * <filter-mapping> * <filter-name>ClickjackFilterSameOrigin</filter-name> * <url-pattern>/*</url-pattern> * </filter-mapping> @@ -66,17 +66,17 @@ * @see * OWASP - Clickjacking Defense Cheat Sheet */ -public class ClickjackFilter implements Filter +public class ClickjackFilter implements Filter { private String mode = "DENY"; /** - * Initialize "mode" parameter from web.xml. Valid values are "DENY" and "SAMEORIGIN". + * Initialize "mode" parameter from web.xml. Valid values are "DENY" and "SAMEORIGIN". * If you leave this parameter out, the default is to use the DENY mode. - * + * * @param filterConfig A filter configuration object used by a servlet container - * to pass information to a filter during initialization. + * to pass information to a filter during initialization. */ public void init(FilterConfig filterConfig) { String configMode = filterConfig.getInitParameter("mode"); @@ -84,13 +84,13 @@ public void init(FilterConfig filterConfig) { mode = configMode; } } - + /** * Add X-FRAME-OPTIONS response header to tell IE8 (and any other browsers who * decide to implement) not to display this content in a frame. For details, please * refer to * @link http://blogs.msdn.com/sdl/archive/2009/02/05/clickjacking-defense-in-ie8.aspx - * + * * @param request The request object. * @param response The response object. * @param chain Refers to the {@code FilterChain} object to pass control to the @@ -110,5 +110,5 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha */ public void destroy() { } - + } diff --git a/src/main/java/org/owasp/esapi/filters/ESAPIFilter.java b/src/main/java/org/owasp/esapi/filters/ESAPIFilter.java index f38e7fae4..be0417bcf 100644 --- a/src/main/java/org/owasp/esapi/filters/ESAPIFilter.java +++ b/src/main/java/org/owasp/esapi/filters/ESAPIFilter.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -59,7 +59,7 @@ public class ESAPIFilter implements Filter { * Default is "WEB-INF/index.jsp". *

      *

      - * + * * @param filterConfig * configuration object */ @@ -84,7 +84,7 @@ public void init(FilterConfig filterConfig) { * for a resource at the end of the chain. The FilterChain passed in to this * method allows the Filter to pass on the request and response to the next * entity in the chain. - * + * * @param req * Request object to be processed * @param resp @@ -98,7 +98,7 @@ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; ESAPI.httpUtilities().setCurrentHTTP(request, response); - + try { // figure out who the current user is try { @@ -124,7 +124,7 @@ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain // check for CSRF attacks // ESAPI.httpUtilities().checkCSRFToken(); - + // forward this request on to the web application chain.doFilter(request, response); @@ -135,11 +135,11 @@ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain // only do this if the entire site should not be cached // otherwise you should do this strategically in your controller or actions ESAPI.httpUtilities().setNoCacheHeaders( response ); - + } catch (Exception e) { logger.error( Logger.SECURITY_FAILURE, "Error in ESAPI security filter: " + e.getMessage(), e ); request.setAttribute("message", e.getMessage() ); - + } finally { // VERY IMPORTANT // clear out the ThreadLocal variables in the authenticator diff --git a/src/main/java/org/owasp/esapi/filters/RequestRateThrottleFilter.java b/src/main/java/org/owasp/esapi/filters/RequestRateThrottleFilter.java index 31fbfef6e..ed263e55e 100644 --- a/src/main/java/org/owasp/esapi/filters/RequestRateThrottleFilter.java +++ b/src/main/java/org/owasp/esapi/filters/RequestRateThrottleFilter.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -48,7 +48,7 @@ public class RequestRateThrottleFilter implements Filter * placed into service. The servlet container calls the init method exactly * once after instantiating the filter. The init method must complete * successfully before the filter is asked to do any filtering work. - * + * * @param filterConfig * configuration object */ @@ -64,9 +64,9 @@ public void init(FilterConfig filterConfig) * exceeded, then a short error message is written to the output stream and * no further processing is done on the request. Otherwise the request is * processed as normal. - * @param request - * @param response - * @param chain + * @param request + * @param response + * @param chain * @throws IOException * @throws ServletException */ @@ -74,7 +74,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpSession session = httpRequest.getSession(true); - + synchronized( session.getId().intern() ) { List times = ESAPI.httpUtilities().getSessionAttribute("times"); if (times == null) { diff --git a/src/main/java/org/owasp/esapi/filters/SecurityWrapper.java b/src/main/java/org/owasp/esapi/filters/SecurityWrapper.java index 9180a8018..cea61ba65 100644 --- a/src/main/java/org/owasp/esapi/filters/SecurityWrapper.java +++ b/src/main/java/org/owasp/esapi/filters/SecurityWrapper.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -132,5 +132,5 @@ public void destroy() { public void init(FilterConfig filterConfig) throws ServletException { this.allowableResourcesRoot = StringUtilities.replaceNull( filterConfig.getInitParameter( "allowableResourcesRoot" ), allowableResourcesRoot ); } - + } diff --git a/src/main/java/org/owasp/esapi/filters/SecurityWrapperRequest.java b/src/main/java/org/owasp/esapi/filters/SecurityWrapperRequest.java index dae6a8460..26fa7a7a3 100644 --- a/src/main/java/org/owasp/esapi/filters/SecurityWrapperRequest.java +++ b/src/main/java/org/owasp/esapi/filters/SecurityWrapperRequest.java @@ -6,7 +6,7 @@ * 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 @@ -57,10 +57,10 @@ public class SecurityWrapperRequest extends HttpServletRequestWrapper implements private String allowableContentRoot = "WEB-INF"; - /** + /** * Construct a safe request that overrides the default request methods with * safer versions. - * + * * @param request The {@code HttpServletRequest} we are wrapping. */ public SecurityWrapperRequest(HttpServletRequest request) { @@ -70,7 +70,7 @@ public SecurityWrapperRequest(HttpServletRequest request) { private HttpServletRequest getHttpServletRequest() { return (HttpServletRequest)super.getRequest(); } - + /** * Same as HttpServletRequest, no security changes required. * @param name The attribute name @@ -159,7 +159,7 @@ public Cookie[] getCookies() { int maxAge = c.getMaxAge(); String domain = c.getDomain(); String path = c.getPath(); - + Cookie n = new Cookie(name, value); n.setMaxAge(maxAge); @@ -398,7 +398,7 @@ public Map getParameterMap() { String name = (String) e.getKey(); SecurityConfiguration sc = ESAPI.securityConfiguration(); String cleanName = ESAPI.validator().getValidInput("HTTP parameter name: " + name, name, "HTTPParameterName", sc.getIntProp("HttpUtilities.httpQueryParamNameLength"), true); - + String[] value = (String[]) e.getValue(); String[] cleanValues = new String[value.length]; for (int j = 0; j < value.length; j++) { @@ -520,7 +520,7 @@ public String getQueryString() { * Same as HttpServletRequest, no security changes required. Note that this * reader may contain attacks and the developer is responsible for * canonicalizing, validating, and encoding any data from this stream. - * @return aA {@code BufferedReader} containing the body of the request. + * @return aA {@code BufferedReader} containing the body of the request. * @throws IOException If an input error occurred while reading the request * body (e.g., premature EOF). */ @@ -689,7 +689,7 @@ public int getServerPort() { } return port; } - + /** * Returns the server path from the HttpServletRequest after canonicalizing diff --git a/src/main/java/org/owasp/esapi/filters/SecurityWrapperResponse.java b/src/main/java/org/owasp/esapi/filters/SecurityWrapperResponse.java index 3cb152477..f05682cba 100644 --- a/src/main/java/org/owasp/esapi/filters/SecurityWrapperResponse.java +++ b/src/main/java/org/owasp/esapi/filters/SecurityWrapperResponse.java @@ -6,7 +6,7 @@ * 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 @@ -45,7 +45,7 @@ public class SecurityWrapperResponse extends HttpServletResponseWrapper implemen /** * Construct a safe response that overrides the default response methods * with safer versions. Default is 'log' mode. - * + * * @param response */ public SecurityWrapperResponse(HttpServletResponse response) { @@ -54,8 +54,8 @@ public SecurityWrapperResponse(HttpServletResponse response) { /** * Construct a safe response that overrides the default response methods - * with safer versions. - * + * with safer versions. + * * @param response * @param mode The mode for this wrapper. Legal modes are "log", "skip", "sanitize", "throw". */ @@ -149,7 +149,7 @@ private String createCookieHeader(String name, String value, int maxAge, String /** * Add a cookie to the response after ensuring that there are no encoded or * illegal characters in the name. - * @param name + * @param name * @param date */ public void addDateHeader(String name, long date) { @@ -183,25 +183,25 @@ public void addHeader(String name, String value) { } catch (ValidationException e) { logger.warning(Logger.SECURITY_FAILURE, "Attempt to add invalid header NAME denied: HTTPHeaderName:"+ name, e); } - + try { safeValue = ESAPI.validator().getValidInput("addHeader", strippedValue, "HTTPHeaderValue", sc.getIntProp("HttpUtilities.MaxHeaderValueSize"), false); } catch (ValidationException e) { logger.warning(Logger.SECURITY_FAILURE, "Attempt to add invalid header VALUE denied: HTTPHeaderName:"+ name, e); } - + boolean validName = StringUtilities.notNullOrEmpty(safeName, true); boolean validValue = StringUtilities.notNullOrEmpty(safeValue, true); - + if (validName && validValue) { getHttpServletResponse().addHeader(safeName, safeValue); } } - + /** - * Add a referer header to the response, after validating there are no illegal characters according to the - * Validator.isValidURI() method, as well as ensuring there are no instances of mixed or double encoding - * depending on how you have configured ESAPI defaults. + * Add a referer header to the response, after validating there are no illegal characters according to the + * Validator.isValidURI() method, as well as ensuring there are no instances of mixed or double encoding + * depending on how you have configured ESAPI defaults. * @param uri */ public void addReferer( String uri) { @@ -213,14 +213,14 @@ public void addReferer( String uri) { if(isValidURI) { safeValue = strippedValue; } - + getHttpServletResponse().addHeader("referer", safeValue); } /** * Add an int header to the response after ensuring that there are no * encoded or illegal characters in the name and value. git - * @param name + * @param name * @param value */ public void addIntHeader(String name, int value) { @@ -248,7 +248,7 @@ public boolean containsHeader(String name) { * Session ID to the URL if support for cookies is not detected. This * exposes the Session ID credential in bookmarks, referer headers, server * logs, and more. - * + * * @param url * @return original url * @deprecated in servlet spec 2.1. Use @@ -265,7 +265,7 @@ public String encodeRedirectUrl(String url) { * Session ID to the URL if support for cookies is not detected. This * exposes the Session ID credential in bookmarks, referer headers, server * logs, and more. - * + * * @param url * @return original url */ @@ -279,7 +279,7 @@ public String encodeRedirectURL(String url) { * Session ID to the URL if support for cookies is not detected. This * exposes the Session ID credential in bookmarks, referer headers, server * logs, and more. - * + * * @param url * @return original url * @deprecated in servlet spec 2.1. Use @@ -296,7 +296,7 @@ public String encodeUrl(String url) { * Session ID to the URL if support for cookies is not detected. This * exposes the Session ID credential in bookmarks, referer headers, server * logs, and more. - * + * * @param url * @return original url */ @@ -387,7 +387,7 @@ public void resetBuffer() { /** * Override the error code with a 200 in order to confound attackers using * automated scanners. Overwriting is controlled by {@code HttpUtilities.OverwriteStatusCodes} - * in ESAPI.properties. + * in ESAPI.properties. * @param sc -- http status code * @throws IOException */ @@ -404,7 +404,7 @@ public void sendError(int sc) throws IOException { * Override the error code with a 200 in order to confound attackers using * automated scanners. The message is canonicalized and filtered for * dangerous characters. Overwriting is controlled by {@code HttpUtilities.OverwriteStatusCodes} - * in ESAPI.properties. + * in ESAPI.properties. * @param sc -- http status code * @param msg -- error message * @throws IOException @@ -425,7 +425,7 @@ public void sendError(int sc, String msg) throws IOException { * be modified by attackers, so do not rely information contained within * redirect requests, and do not include sensitive information in a * redirect. - * @param location + * @param location * @throws IOException */ public void sendRedirect(String location) throws IOException { @@ -472,7 +472,7 @@ public void setContentType(String type) { /** * Add a date header to the response after ensuring that there are no * encoded or illegal characters in the name. - * @param name + * @param name * @param date */ public void setDateHeader(String name, long date) { @@ -491,7 +491,7 @@ public void setDateHeader(String name, long date) { * linear white space with a single SP before interpreting the field value * or forwarding the message downstream." * http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 - * @param name + * @param name * @param value */ public void setHeader(String name, String value) { @@ -505,16 +505,16 @@ public void setHeader(String name, String value) { } catch (ValidationException e) { logger.warning(Logger.SECURITY_FAILURE, "Attempt to set invalid header NAME denied: HTTPHeaderName:"+ name, e); } - + try { safeValue = ESAPI.validator().getValidInput("setHeader", strippedValue, "HTTPHeaderValue", sc.getIntProp("HttpUtilities.MaxHeaderValueSize"), false); } catch (ValidationException e) { logger.warning(Logger.SECURITY_FAILURE, "Attempt to set invalid header VALUE denied: HTTPHeaderName:"+ name, e); } - + boolean validName = StringUtilities.notNullOrEmpty(safeName, true); boolean validValue = StringUtilities.notNullOrEmpty(safeValue, true); - + if (validName && validValue) { getHttpServletResponse().setHeader(safeName, safeValue); } @@ -523,7 +523,7 @@ public void setHeader(String name, String value) { /** * Add an int header to the response after ensuring that there are no * encoded or illegal characters in the name. - * @param name + * @param name * @param value */ public void setIntHeader(String name, int value) { @@ -557,14 +557,14 @@ public void setStatus(int sc) { }else{ getHttpServletResponse().setStatus(sc); } - + } /** * Override the status code with a 200 in order to confound attackers using * automated scanners. The message is canonicalized and filtered for * dangerous characters. - * @param sc + * @param sc * @param sm * @deprecated In Servlet spec 2.1. */ diff --git a/src/main/java/org/owasp/esapi/logging/appender/ClientInfoSupplier.java b/src/main/java/org/owasp/esapi/logging/appender/ClientInfoSupplier.java index 5a8524340..cfb8bea61 100644 --- a/src/main/java/org/owasp/esapi/logging/appender/ClientInfoSupplier.java +++ b/src/main/java/org/owasp/esapi/logging/appender/ClientInfoSupplier.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ @@ -83,7 +83,7 @@ public String get() { /** * Specify whether the instance should record the client info. - * + * * @param log {@code true} to record */ public void setLogClientInfo(boolean log) { diff --git a/src/main/java/org/owasp/esapi/logging/appender/EventTypeLogSupplier.java b/src/main/java/org/owasp/esapi/logging/appender/EventTypeLogSupplier.java index 4af1bd50b..681839af5 100644 --- a/src/main/java/org/owasp/esapi/logging/appender/EventTypeLogSupplier.java +++ b/src/main/java/org/owasp/esapi/logging/appender/EventTypeLogSupplier.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ @@ -33,7 +33,7 @@ public class EventTypeLogSupplier // implements Supplier /** * Ctr - * + * * @param evtyp EventType reference to supply log representation for */ public EventTypeLogSupplier(EventType evtyp) { diff --git a/src/main/java/org/owasp/esapi/logging/appender/LogAppender.java b/src/main/java/org/owasp/esapi/logging/appender/LogAppender.java index b3aba0534..b764a7ad4 100644 --- a/src/main/java/org/owasp/esapi/logging/appender/LogAppender.java +++ b/src/main/java/org/owasp/esapi/logging/appender/LogAppender.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ diff --git a/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java b/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java index 9beb1a97e..20f692ebf 100644 --- a/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java +++ b/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ @@ -38,7 +38,7 @@ public class LogPrefixAppender implements LogAppender { /** * Ctr. - * + * * @param logUserInfo Whether or not to record user information * @param logClientInfo Whether or not to record client information * @param logServerIp Whether or not to record server ip information @@ -59,10 +59,10 @@ public String appendTo(String logName, EventType eventType, String message) { UserInfoSupplier userInfoSupplier = new UserInfoSupplier(); userInfoSupplier.setLogUserInfo(logUserInfo); - + ClientInfoSupplier clientInfoSupplier = new ClientInfoSupplier(); clientInfoSupplier.setLogClientInfo(logClientInfo); - + ServerInfoSupplier serverInfoSupplier = new ServerInfoSupplier(logName); serverInfoSupplier.setLogServerIp(logServerIp); serverInfoSupplier.setLogApplicationName(logApplicationName, appName); @@ -71,10 +71,10 @@ public String appendTo(String logName, EventType eventType, String message) { String userInfoMsg = userInfoSupplier.get().trim(); String clientInfoMsg = clientInfoSupplier.get().trim(); String serverInfoMsg = serverInfoSupplier.get().trim(); - + //If both user and client have content, then postfix the semicolon to the userInfoMsg at this point to simplify the StringBuilder operations later. userInfoMsg = (!userInfoMsg.isEmpty() && !clientInfoMsg.isEmpty()) ? userInfoMsg + ":" : userInfoMsg; - + //If both server has content, then prefix the arrow to the serverInfoMsg at this point to simplify the StringBuilder operations later. serverInfoMsg = (!serverInfoMsg.isEmpty()) ? "-> " + serverInfoMsg: serverInfoMsg; @@ -83,14 +83,14 @@ public String appendTo(String logName, EventType eventType, String message) { StringBuilder logPrefix = new StringBuilder(); //EventType is always appended logPrefix.append(eventTypeMsg); - + for (String element : optionalPrefixContent) { if (!element.isEmpty()) { logPrefix.append(" "); logPrefix.append(element); } } - + return String.format(RESULT_FORMAT, logPrefix.toString(), message); } } diff --git a/src/main/java/org/owasp/esapi/logging/appender/ServerInfoSupplier.java b/src/main/java/org/owasp/esapi/logging/appender/ServerInfoSupplier.java index c9e0d8e02..8fbef3e6c 100644 --- a/src/main/java/org/owasp/esapi/logging/appender/ServerInfoSupplier.java +++ b/src/main/java/org/owasp/esapi/logging/appender/ServerInfoSupplier.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ @@ -40,7 +40,7 @@ public class ServerInfoSupplier // implements Supplier /** * Ctr. - * + * * @param logName Reference to the logName to record as the module information */ public ServerInfoSupplier(String logName) { @@ -65,7 +65,7 @@ public String get() { /** * Specify whether the instance should record the server connection info. - * + * * @param log {@code true} to record */ public void setLogServerIp(boolean log) { @@ -74,7 +74,7 @@ public void setLogServerIp(boolean log) { /** * Specify whether the instance should record the application name - * + * * @param log {@code true} to record * @param appName String to record as the application name */ diff --git a/src/main/java/org/owasp/esapi/logging/appender/UserInfoSupplier.java b/src/main/java/org/owasp/esapi/logging/appender/UserInfoSupplier.java index 6065ed366..445be3dc2 100644 --- a/src/main/java/org/owasp/esapi/logging/appender/UserInfoSupplier.java +++ b/src/main/java/org/owasp/esapi/logging/appender/UserInfoSupplier.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ @@ -29,30 +29,30 @@ public class UserInfoSupplier // implements Supplier { /** Default UserName string if the Authenticated user is null.*/ private static final String DEFAULT_USERNAME = "#ANONYMOUS#"; - + /** Whether to log the user info from this instance. */ private boolean logUserInfo = true; - + // @Override -- Uncomment when we switch to Java 8 as minimal baseline. public String get() { // log user information - username:session@ipaddr User user = ESAPI.authenticator().getCurrentUser(); - + String userInfo = ""; if (logUserInfo) { if (user == null) { userInfo = DEFAULT_USERNAME; } else { - userInfo = user.getAccountName(); + userInfo = user.getAccountName(); } - } - + } + return userInfo; } /** * Specify whether the instance should record the client info. - * + * * @param log {@code true} to record */ public void setLogUserInfo(boolean log) { diff --git a/src/main/java/org/owasp/esapi/logging/cleaning/CodecLogScrubber.java b/src/main/java/org/owasp/esapi/logging/cleaning/CodecLogScrubber.java index 257ba140a..4ce14bac5 100644 --- a/src/main/java/org/owasp/esapi/logging/cleaning/CodecLogScrubber.java +++ b/src/main/java/org/owasp/esapi/logging/cleaning/CodecLogScrubber.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.cleaning; @@ -31,7 +31,7 @@ public class CodecLogScrubber implements LogScrubber { /** * Ctr. - * + * * @param messageCodec * Delegate codec. Cannot be {@code null} * @param immuneChars diff --git a/src/main/java/org/owasp/esapi/logging/cleaning/CompositeLogScrubber.java b/src/main/java/org/owasp/esapi/logging/cleaning/CompositeLogScrubber.java index 79ad7d4bc..1638ca51f 100644 --- a/src/main/java/org/owasp/esapi/logging/cleaning/CompositeLogScrubber.java +++ b/src/main/java/org/owasp/esapi/logging/cleaning/CompositeLogScrubber.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.cleaning; @@ -31,7 +31,7 @@ public class CompositeLogScrubber implements LogScrubber { /** * Ctr. - * + * * @param orderedCleaner * Ordered List of delegate implementations. Cannot be {@code null} */ diff --git a/src/main/java/org/owasp/esapi/logging/cleaning/LogScrubber.java b/src/main/java/org/owasp/esapi/logging/cleaning/LogScrubber.java index 4e833cdfa..fd8a54a41 100644 --- a/src/main/java/org/owasp/esapi/logging/cleaning/LogScrubber.java +++ b/src/main/java/org/owasp/esapi/logging/cleaning/LogScrubber.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ @@ -24,7 +24,7 @@ public interface LogScrubber { /** * Updates the given message to account for restrictions for this implementation * and returns the result. - * + * * @param message * Original message to clean. * @return Cleaned message. diff --git a/src/main/java/org/owasp/esapi/logging/cleaning/NewlineLogScrubber.java b/src/main/java/org/owasp/esapi/logging/cleaning/NewlineLogScrubber.java index 5ba267a6a..025896861 100644 --- a/src/main/java/org/owasp/esapi/logging/cleaning/NewlineLogScrubber.java +++ b/src/main/java/org/owasp/esapi/logging/cleaning/NewlineLogScrubber.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.cleaning; diff --git a/src/main/java/org/owasp/esapi/logging/java/ESAPICustomJavaLevel.java b/src/main/java/org/owasp/esapi/logging/java/ESAPICustomJavaLevel.java index 148082944..36a005eb0 100644 --- a/src/main/java/org/owasp/esapi/logging/java/ESAPICustomJavaLevel.java +++ b/src/main/java/org/owasp/esapi/logging/java/ESAPICustomJavaLevel.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ @@ -34,11 +34,11 @@ public class ESAPICustomJavaLevel extends Level { * Defines a custom level that should result in content always being recorded, unless the Java Logging configuration is set to OFF. */ public static final Level ALWAYS_LEVEL = new ESAPICustomJavaLevel( "ALWAYS", Level.OFF.intValue() - 1); - + /** * Constructs an instance of a JavaLoggerLevel which essentially provides a mapping between the name of * the defined level and its numeric value. - * + * * @param name The name of the JavaLoggerLevel * @param value The associated numeric value */ diff --git a/src/main/java/org/owasp/esapi/logging/java/ESAPIErrorJavaLevel.java b/src/main/java/org/owasp/esapi/logging/java/ESAPIErrorJavaLevel.java index 9a2b98aa7..f8288c3ad 100644 --- a/src/main/java/org/owasp/esapi/logging/java/ESAPIErrorJavaLevel.java +++ b/src/main/java/org/owasp/esapi/logging/java/ESAPIErrorJavaLevel.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ @@ -39,7 +39,7 @@ public class ESAPIErrorJavaLevel extends Level { /** * Constructs an instance of a JavaLoggerLevel which essentially provides a mapping between the name of * the defined level and its numeric value. - * + * * @param name The name of the JavaLoggerLevel * @param value The associated numeric value */ diff --git a/src/main/java/org/owasp/esapi/logging/java/JavaLogBridge.java b/src/main/java/org/owasp/esapi/logging/java/JavaLogBridge.java index c085766dc..078afdf9b 100644 --- a/src/main/java/org/owasp/esapi/logging/java/JavaLogBridge.java +++ b/src/main/java/org/owasp/esapi/logging/java/JavaLogBridge.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ package org.owasp.esapi.logging.java; @@ -20,7 +20,7 @@ /** * Contract for translating an ESAPI log event into an Java log event. - * + * */ public interface JavaLogBridge { /** diff --git a/src/main/java/org/owasp/esapi/logging/java/JavaLogBridgeImpl.java b/src/main/java/org/owasp/esapi/logging/java/JavaLogBridgeImpl.java index df599eaf1..042a56202 100644 --- a/src/main/java/org/owasp/esapi/logging/java/JavaLogBridgeImpl.java +++ b/src/main/java/org/owasp/esapi/logging/java/JavaLogBridgeImpl.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ diff --git a/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java b/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java index 038d19b5e..e094361b7 100644 --- a/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java +++ b/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ package org.owasp.esapi.logging.java; @@ -43,7 +43,7 @@ /** * LogFactory implementation which creates JAVA supporting Loggers. - * + * * This implementation requires that a file named 'esapi-java-logging.properties' exists on the classpath. *
      * A default file implementation is available in the configuration jar on GitHub under the 'Releases' @@ -103,7 +103,7 @@ public class JavaLogFactory implements LogFactory { } logManager.readConfiguration(stream); } catch (IOException ioe) { - throw new ConfigurationException("Failed to load esapi-java-logging.properties.", ioe); + throw new ConfigurationException("Failed to load esapi-java-logging.properties.", ioe); } } @@ -126,21 +126,21 @@ public class JavaLogFactory implements LogFactory { /** * Populates the default log appender for use in factory-created loggers. - * @param appName - * @param logApplicationName - * @param logServerIp - * @param logClientInfo - * + * @param appName + * @param logApplicationName + * @param logServerIp + * @param logClientInfo + * * @return LogAppender instance. */ /*package*/ static LogAppender createLogAppender(boolean logUserInfo, boolean logClientInfo, boolean logServerIp, boolean logApplicationName, String appName) { - return new LogPrefixAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); + return new LogPrefixAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); } @Override public Logger getLogger(String moduleName) { - java.util.logging.Logger javaLogger = java.util.logging.Logger.getLogger(moduleName); + java.util.logging.Logger javaLogger = java.util.logging.Logger.getLogger(moduleName); return new JavaLogger(javaLogger, LOG_BRIDGE, Logger.ALL); } diff --git a/src/main/java/org/owasp/esapi/logging/java/JavaLogLevelHandler.java b/src/main/java/org/owasp/esapi/logging/java/JavaLogLevelHandler.java index ee28a1a4f..ea237459d 100644 --- a/src/main/java/org/owasp/esapi/logging/java/JavaLogLevelHandler.java +++ b/src/main/java/org/owasp/esapi/logging/java/JavaLogLevelHandler.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ package org.owasp.esapi.logging.java; @@ -18,7 +18,7 @@ /** * Contract used to isolate translations for each Java Logging Level. - * + * * @see JavaLogLevelHandlers * @see JavaLogBridgeImpl * diff --git a/src/main/java/org/owasp/esapi/logging/java/JavaLogLevelHandlers.java b/src/main/java/org/owasp/esapi/logging/java/JavaLogLevelHandlers.java index 69c03f9e9..57a90dae7 100644 --- a/src/main/java/org/owasp/esapi/logging/java/JavaLogLevelHandlers.java +++ b/src/main/java/org/owasp/esapi/logging/java/JavaLogLevelHandlers.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ package org.owasp.esapi.logging.java; @@ -30,11 +30,11 @@ public enum JavaLogLevelHandlers implements JavaLogLevelHandler { ERROR(ESAPICustomJavaLevel.ERROR_LEVEL); private final Level level; - + private JavaLogLevelHandlers(Level lvl) { this.level = lvl; } - + @Override public boolean isEnabled(Logger logger) { return logger.isLoggable(level); diff --git a/src/main/java/org/owasp/esapi/logging/java/JavaLogger.java b/src/main/java/org/owasp/esapi/logging/java/JavaLogger.java index 6e57c39e0..1ac4a484f 100644 --- a/src/main/java/org/owasp/esapi/logging/java/JavaLogger.java +++ b/src/main/java/org/owasp/esapi/logging/java/JavaLogger.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ package org.owasp.esapi.logging.java; @@ -27,7 +27,7 @@ public class JavaLogger implements org.owasp.esapi.Logger { private int loggingLevel; /** - * Constructs a new instance. + * Constructs a new instance. * @param JavaLogger Delegate Java logger. * @param bridge Translator for ESAPI -> Java logging events. * @param defaultEsapiLevel Maximum ESAPI log level events to propagate. @@ -112,7 +112,7 @@ public void error(EventType type, String message) { @Override public void error(EventType type, String message, Throwable throwable) { - log (Logger.ERROR, type, message, throwable); + log (Logger.ERROR, type, message, throwable); } @Override @@ -141,7 +141,7 @@ public boolean isDebugEnabled() { } @Override public boolean isInfoEnabled() { - return isEnabled(Logger.INFO); + return isEnabled(Logger.INFO); } @Override public boolean isWarningEnabled() { diff --git a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridge.java b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridge.java index 5c17ee4f5..4b73f7a83 100644 --- a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridge.java +++ b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridge.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.slf4j; @@ -18,7 +18,7 @@ import org.slf4j.Logger; /** * Contract for translating an ESAPI log event into an SLF4J log event. - * + * */ public interface Slf4JLogBridge { /** @@ -38,5 +38,5 @@ public interface Slf4JLogBridge { * @param throwable ESAPI event Throwable content */ void log(Logger logger, int esapiLevel, EventType type, String message, Throwable throwable) ; - + } diff --git a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridgeImpl.java b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridgeImpl.java index a6c7d1730..2955f9459 100644 --- a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridgeImpl.java +++ b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridgeImpl.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ @@ -39,7 +39,7 @@ public class Slf4JLogBridgeImpl implements Slf4JLogBridge { private final LogScrubber scrubber; /** Appender used for assembling default message content for all logs.*/ private final LogAppender appender; - + /** * Constructor. * @param logScrubber Log message cleaner. @@ -60,7 +60,7 @@ public void log(Logger logger, int esapiLevel, EventType type, String message) { if (handler.isEnabled(logger)) { String fullMessage = appender.appendTo(logger.getName(), type, message); String cleanString = scrubber.cleanMessage(fullMessage); - + Marker typeMarker = MARKER_FACTORY.getMarker(type.toString()); handler.log(logger, typeMarker, cleanString); } diff --git a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java index d2e6c6305..af113b80c 100644 --- a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java +++ b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.slf4j; @@ -58,11 +58,11 @@ public class Slf4JLogFactory implements LogFactory { private static LogScrubber SLF4J_LOG_SCRUBBER; /** Bridge class for mapping esapi -> slf4j log levels.*/ private static Slf4JLogBridge LOG_BRIDGE; - + static { boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(LOG_ENCODING_REQUIRED); SLF4J_LOG_SCRUBBER = createLogScrubber(encodeLog); - + boolean logUserInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_USER_INFO); boolean logClientInfo = ESAPI.securityConfiguration().getBooleanProp(LOG_CLIENT_INFO); @@ -70,7 +70,7 @@ public class Slf4JLogFactory implements LogFactory { String appName = ESAPI.securityConfiguration().getStringProp(APPLICATION_NAME); boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(LOG_SERVER_IP); SLF4J_LOG_APPENDER = createLogAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); - + Map levelLookup = new HashMap<>(); levelLookup.put(Logger.ALL, Slf4JLogLevelHandlers.TRACE); levelLookup.put(Logger.TRACE, Slf4JLogLevelHandlers.TRACE); @@ -80,10 +80,10 @@ public class Slf4JLogFactory implements LogFactory { levelLookup.put(Logger.WARNING, Slf4JLogLevelHandlers.WARN); levelLookup.put(Logger.FATAL, Slf4JLogLevelHandlers.ERROR); //LEVEL.OFF not used. If it's off why would we try to log it? - + LOG_BRIDGE = new Slf4JLogBridgeImpl(SLF4J_LOG_APPENDER, SLF4J_LOG_SCRUBBER, levelLookup); } - + /** * Populates the default log scrubber for use in factory-created loggers. * @param requiresEncoding {@code true} if encoding is required for log content. @@ -92,29 +92,29 @@ public class Slf4JLogFactory implements LogFactory { /*package*/ static LogScrubber createLogScrubber(boolean requiresEncoding) { List messageScrubber = new ArrayList<>(); messageScrubber.add(new NewlineLogScrubber()); - + if (requiresEncoding) { messageScrubber.add(new CodecLogScrubber(HTML_CODEC, IMMUNE_SLF4J_HTML)); } - + return new CompositeLogScrubber(messageScrubber); - + } - + /** * Populates the default log appender for use in factory-created loggers. - * @param appName - * @param logApplicationName - * @param logServerIp - * @param logClientInfo - * + * @param appName + * @param logApplicationName + * @param logServerIp + * @param logClientInfo + * * @return LogAppender instance. */ /*package*/ static LogAppender createLogAppender(boolean logUserInfo, boolean logClientInfo, boolean logServerIp, boolean logApplicationName, String appName) { - return new LogPrefixAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); + return new LogPrefixAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); } - - + + @Override public Logger getLogger(String moduleName) { org.slf4j.Logger slf4JLogger = LoggerFactory.getLogger(moduleName); diff --git a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandler.java b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandler.java index 1e8bb7f7c..1232374a9 100644 --- a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandler.java +++ b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandler.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.slf4j; @@ -18,7 +18,7 @@ import org.slf4j.Marker; /** * Contract used to isolate translations for each SLF4J Logging Level. - * + * * @see Slf4JLogLevelHandlers * @see Slf4JLogBridgeImpl * diff --git a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandlers.java b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandlers.java index d2748fe77..e26da6509 100644 --- a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandlers.java +++ b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandlers.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ @@ -78,7 +78,7 @@ public boolean isEnabled(Logger logger) { @Override public void log(Logger logger, Marker marker, String msg) { - logger.debug(marker, msg); + logger.debug(marker, msg); } @Override diff --git a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogger.java b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogger.java index 62fead5d1..adb64ce20 100644 --- a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogger.java +++ b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogger.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.slf4j; @@ -25,9 +25,9 @@ public class Slf4JLogger implements org.owasp.esapi.Logger { private final Slf4JLogBridge logBridge; /** Maximum log level that will be forwarded to SLF4J from the ESAPI context.*/ private int loggingLevel; - + /** - * Constructs a new instance. + * Constructs a new instance. * @param slf4JLogger Delegate SLF4J logger. * @param bridge Translator for ESAPI -> SLF4J logging events. * @param defaultEsapiLevel Maximum ESAPI log level events to propagate. @@ -37,24 +37,24 @@ public Slf4JLogger(org.slf4j.Logger slf4JLogger, Slf4JLogBridge bridge, int defa this.logBridge = bridge; loggingLevel = defaultEsapiLevel; } - + private void log(int esapiLevel, EventType type, String message) { if (isEnabled(esapiLevel)) { logBridge.log(delegate, esapiLevel, type, message); } } - + private void log(int esapiLevel, EventType type, String message, Throwable throwable) { if (isEnabled(esapiLevel)) { logBridge.log(delegate, esapiLevel, type, message, throwable); } } - + private boolean isEnabled(int esapiLevel) { return esapiLevel >= loggingLevel; } - + @Override public void always(EventType type, String message) { log (Logger.ALL, type, message); @@ -69,7 +69,7 @@ public void always(EventType type, String message, Throwable throwable) { public void trace(EventType type, String message) { log (Logger.TRACE, type, message); } - + @Override public void trace(EventType type, String message, Throwable throwable) { log (Logger.TRACE, type, message, throwable); @@ -84,22 +84,22 @@ public void debug(EventType type, String message) { public void debug(EventType type, String message, Throwable throwable) { log (Logger.DEBUG, type, message, throwable); } - + @Override public void info(EventType type, String message) { log (Logger.INFO, type, message); } - + @Override public void info(EventType type, String message, Throwable throwable) { log (Logger.INFO, type, message, throwable); } - + @Override public void warning(EventType type, String message) { log (Logger.WARNING, type, message); } - + @Override public void warning(EventType type, String message, Throwable throwable) { log (Logger.WARNING, type, message, throwable); @@ -112,7 +112,7 @@ public void error(EventType type, String message) { @Override public void error(EventType type, String message, Throwable throwable) { - log (Logger.ERROR, type, message, throwable); + log (Logger.ERROR, type, message, throwable); } @Override @@ -124,44 +124,44 @@ public void fatal(EventType type, String message) { public void fatal(EventType type, String message, Throwable throwable) { log (Logger.FATAL, type, message, throwable); } - + @Override public int getESAPILevel() { return loggingLevel; } - + @Override public boolean isTraceEnabled() { return isEnabled(Logger.TRACE); } - + @Override public boolean isDebugEnabled() { return isEnabled(Logger.DEBUG); } @Override public boolean isInfoEnabled() { - return isEnabled(Logger.INFO); + return isEnabled(Logger.INFO); } @Override public boolean isWarningEnabled() { return isEnabled(Logger.WARNING); } - + @Override public boolean isErrorEnabled() { return isEnabled(Logger.ERROR); } - + @Override public boolean isFatalEnabled() { return isEnabled(Logger.FATAL); } - + @Override public void setLevel(int level) { loggingLevel = level; } - + } diff --git a/src/main/java/org/owasp/esapi/package.html b/src/main/java/org/owasp/esapi/package.html index cb23a58ac..02df5ede7 100644 --- a/src/main/java/org/owasp/esapi/package.html +++ b/src/main/java/org/owasp/esapi/package.html @@ -28,46 +28,46 @@

      Sponsor

      is free to participate in OWASP and all of our materials are available under an open source license. The OWASP Foundation is a 501c3 not-for-profit charitable organization that ensures the ongoing -availability and support for our work.

      - +availability and support for our work.

      +

      The OWASP ESAPI Project is led by Jeff Williams, Aspect Security. - +

      You can find more information about the ESAPI Java project, or join the mailing list and help us make it better from the OWASP project page at http://www.owasp.org/index.php/ESAPI#tab=Java_EE.

      - +href="http://www.owasp.org/index.php/ESAPI#tab=Java_EE">http://www.owasp.org/index.php/ESAPI#tab=Java_EE.

      +

      ESAPI Architecture

      - +

      The ESAPI class library builds on the excellent security libraries available, such as Java Logging, JCE, and Adobe Commons FileUpload. It uses the concepts from many of the security packages out there, such as ACEGI, Apache Commons Validator, Microsoft's AntiXSS library, and many many more. This library provides a single consistent interface to security -functions that is intuitive for enterprise developers.

      +functions that is intuitive for enterprise developers.

      - +

      Addressing OWASP Top Ten

      - +

      Used properly, the ESAPI provides enough functions to protect against most of the OWASP Top Ten. The only real exception is the Insecure Communications category, which is generally outside the control -of the software developer.

      - +of the software developer.

      +

      Copyright and License

      - -

      This project and all associated code is Copyright (c) 2007 - The OWASP Foundation

      - -

      This project licensed under the BSD license, -which is very permissive and about as close to public domain as is possible. You can use or modify + +

      This project and all associated code is Copyright (c) 2007 - The OWASP Foundation

      + +

      This project licensed under the BSD license, +which is very permissive and about as close to public domain as is possible. You can use or modify ESAPI however you want, even include it in commercial products.

      References

      diff --git a/src/main/java/org/owasp/esapi/reference/AbstractAccessReferenceMap.java b/src/main/java/org/owasp/esapi/reference/AbstractAccessReferenceMap.java index 4e988c45b..242ff3e47 100644 --- a/src/main/java/org/owasp/esapi/reference/AbstractAccessReferenceMap.java +++ b/src/main/java/org/owasp/esapi/reference/AbstractAccessReferenceMap.java @@ -28,16 +28,16 @@ /** * Abstract Implementation of the AccessReferenceMap. *
      - * Implementation offers default synchronization on all public API + * Implementation offers default synchronization on all public API * to assist with thread safety. *
      - * For complex interactions spanning multiple calls, it is recommended + * For complex interactions spanning multiple calls, it is recommended * to add a synchronized block around all invocations to maintain intended data integrity. - * + * *
        * public MyClassUsingAARM {
        *  private AbstractAccessReferenceMap aarm;
      - * 
      + *
        *  public void replaceAARMDirect(Object oldDirect, Object newDirect) {
        *     synchronized (aarm) {
        *        aarm.removeDirectReference(oldDirect);
      @@ -181,23 +181,23 @@ public synchronized  K removeDirectReference(T direct) throws AccessControlEx
          public final synchronized void update(Set directReferences) {
              Map new_dtoi = new HashMap( directReferences.size() );
              Map new_itod = new HashMap( directReferences.size() );
      -       
      +
              Set newDirect = new HashSet<>(directReferences);
              Set dtoiCurrent = new HashSet<>(dtoi.keySet());
       
              //Preserve all keys that are in the new set
              dtoiCurrent.retainAll(newDirect);
      -       
      +
              //Transfer existing values into the new map
              for (Object current: dtoiCurrent) {
                  K idCurrent = dtoi.get(current);
                  new_dtoi.put(current, idCurrent);
                  new_itod.put(idCurrent, current);
              }
      -       
      +
              //Trim the new map to only new values
              newDirect.removeAll(dtoiCurrent);
      -       
      +
              //Add new values with new indirect keys to the new map
              for (Object newD : newDirect) {
                  K idCurrent;
      @@ -205,11 +205,11 @@ public final synchronized void update(Set directReferences) {
                      idCurrent = getUniqueReference();
                      //Unlikey, but just in case we generate the exact same key multiple times...
                  } while (dtoi.containsValue(idCurrent));
      -           
      +
                  new_dtoi.put(newD, idCurrent);
                  new_itod.put(idCurrent, newD);
              }
      -    
      +
              dtoi = new_dtoi;
              itod = new_itod;
          }
      diff --git a/src/main/java/org/owasp/esapi/reference/AbstractAuthenticator.java b/src/main/java/org/owasp/esapi/reference/AbstractAuthenticator.java
      index c412a3be1..9e3f7843b 100644
      --- a/src/main/java/org/owasp/esapi/reference/AbstractAuthenticator.java
      +++ b/src/main/java/org/owasp/esapi/reference/AbstractAuthenticator.java
      @@ -27,9 +27,9 @@ public abstract class AbstractAuthenticator implements org.owasp.esapi.Authentic
            * Key for user in session
            */
           protected static final String USER = "ESAPIUserSessionKey";
      -    
      +
           private final Logger logger = ESAPI.getLogger("Authenticator");
      -    
      +
           /**
            * The currentUser ThreadLocal variable is used to make the currentUser available to any call in any part of an
            * application. Otherwise, each thread would have to pass the User object through the calltree to any methods that
      @@ -53,14 +53,14 @@ public void setUser(User newUser) {
                   super.set(newUser);
               }
           }
      -    
      +
           /**
            *
            */
           public AbstractAuthenticator() {
               super();
           }
      -    
      +
           /**
            * {@inheritDoc}
            */
      @@ -68,14 +68,14 @@ public void clearCurrent() {
               // logger.logWarning(Logger.SECURITY, "************Clearing threadlocals. Thread" + Thread.currentThread().getName() );
               currentUser.setUser(null);
           }
      -    
      +
           /**
            * {@inheritDoc}
            */
           public boolean exists(String accountName) {
               return getUser(accountName) != null;
           }
      -    
      +
           /**
            * {@inheritDoc}
            * 

      @@ -89,7 +89,7 @@ public User getCurrentUser() { } return user; } - + /** * Gets the user from session. * @@ -102,7 +102,7 @@ protected User getUserFromSession() { if (session == null) return null; return ESAPI.httpUtilities().getSessionAttribute(USER); } - + /** * Returns the user if a matching remember token is found, or null if the token * is missing, token is corrupt, token is expired, account name does not match @@ -117,7 +117,7 @@ protected DefaultUser getUserFromRememberToken() { HTTPUtilities utils =ESAPI.httpUtilities(); String token = utils.getCookie(ESAPI.currentRequest(), HTTPUtilities.REMEMBER_TOKEN_COOKIE_NAME); if (token == null) return null; - + // See Google Issue 144 regarding first URLDecode the token and THEN unsealing. // Note that this Google Issue was marked as "WontFix". @@ -147,7 +147,7 @@ protected DefaultUser getUserFromRememberToken() { ESAPI.httpUtilities().killCookie(ESAPI.currentRequest(), ESAPI.currentResponse(), HTTPUtilities.REMEMBER_TOKEN_COOKIE_NAME); return null; } - + /** * Utility method to extract credentials and verify them. * @@ -183,14 +183,14 @@ private User loginWithUsernameAndPassword(HttpServletRequest request) throws Aut request.setAttribute(user.getCSRFToken(), "authenticated"); return user; } - + /** * {@inheritDoc} */ public User login() throws AuthenticationException { return login(ESAPI.currentRequest(), ESAPI.currentResponse()); } - + /** * {@inheritDoc} */ @@ -279,7 +279,7 @@ public User login(HttpServletRequest request, HttpServletResponse response) thro setCurrentUser(user); return user; } - + /** * {@inheritDoc} */ diff --git a/src/main/java/org/owasp/esapi/reference/DefaultAccessController.java b/src/main/java/org/owasp/esapi/reference/DefaultAccessController.java index 23b80ebb0..7f978ca37 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultAccessController.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultAccessController.java @@ -30,7 +30,7 @@ public static AccessController getInstance() throws AccessControlException { private DefaultAccessController() throws AccessControlException { ACRPolicyFileLoader policyDescriptor = new ACRPolicyFileLoader(); - PolicyDTO policyDTO = policyDescriptor.load(); + PolicyDTO policyDTO = policyDescriptor.load(); ruleMap = policyDTO.getAccessControlRules(); } @@ -42,18 +42,18 @@ public boolean isAuthorized(Object key, Object runtimeParameter) { AccessControlRule rule = (AccessControlRule)ruleMap.get(key); if(rule == null) { throw new AccessControlException("Access Denied", - "AccessControlRule was not found for key: " + key); + "AccessControlRule was not found for key: " + key); } if(logger.isDebugEnabled()){ logger.debug(Logger.EVENT_SUCCESS, "Evaluating Authorization Rule \"" + key + "\" Using class: " + rule.getClass().getCanonicalName()); } return rule.isAuthorized(runtimeParameter); } catch(Exception e) { try { //Log the exception by throwing and then catching it. - //TODO figure out what which string goes where. + //TODO figure out what which string goes where. throw new AccessControlException("Access Denied", "An unhandled Exception was " + - "caught, so access is denied.", - e); + "caught, so access is denied.", + e); } catch(AccessControlException ace) { //the exception was just logged. There's nothing left to do. } @@ -67,25 +67,25 @@ public void assertAuthorized(Object key, Object runtimeParameter) throws AccessC try { AccessControlRule rule = (AccessControlRule)ruleMap.get(key); if(rule == null) { - throw new AccessControlException("Access Denied", - "AccessControlRule was not found for key: " + key); + throw new AccessControlException("Access Denied", + "AccessControlRule was not found for key: " + key); } if(logger.isDebugEnabled()){ logger.debug(Logger.EVENT_SUCCESS, "Asserting Authorization Rule \"" + key + "\" Using class: " + rule.getClass().getCanonicalName()); } isAuthorized = rule.isAuthorized(runtimeParameter); } catch(Exception e) { - //TODO figure out what which string goes where. + //TODO figure out what which string goes where. throw new AccessControlException("Access Denied", "An unhandled Exception was " + "caught, so access is denied." + "AccessControlException.", e); } if(!isAuthorized) { - throw new AccessControlException("Access Denied", - "Access Denied for key: " + key + + throw new AccessControlException("Access Denied", + "Access Denied for key: " + key + " runtimeParameter: " + runtimeParameter); } } - + /** {@inheritDoc} */ public void assertAuthorizedForData(String action, Object data) throws AccessControlException { diff --git a/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java b/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java index aa019a810..7c16de54c 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -50,7 +50,7 @@ * Reference implementation of the Encoder interface. This implementation takes * a whitelist approach to encoding, meaning that everything not specifically identified in a * list of "immune" characters is encoded. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -81,7 +81,7 @@ public static Encoder getInstance() { private CSSCodec cssCodec = new CSSCodec(); private final Logger logger = ESAPI.getLogger("Encoder"); - + /** * Character sets that define characters (in addition to alphanumerics) that are * immune from encoding in various formats @@ -96,8 +96,8 @@ public static Encoder getInstance() { private final static char[] IMMUNE_OS = { '-' }; private final static char[] IMMUNE_XMLATTR = { ',', '.', '-', '_' }; private final static char[] IMMUNE_XPATH = { ',', '.', '-', '_', ' ' }; - - + + /** * Instantiates a new {@code DefaultEncoder} based on the property {@code Encoder.DefaultCodecList} * from the {@code ESAPI.properties} file. @@ -105,7 +105,7 @@ public static Encoder getInstance() { private DefaultEncoder() { this( ESAPI.securityConfiguration().getDefaultCanonicalizationCodecs() ); } - + /** * Instantiates a new {@code DefaultEncoder} based on the specified list of * codec names. Unqualified codec names are assumed to belong to the package @@ -121,7 +121,7 @@ public DefaultEncoder( List codecNames ) { } } } - + /** * {@inheritDoc} */ @@ -131,12 +131,12 @@ public String canonicalize( String input ) { } // Issue 231 - These are reverse boolean logic in the Encoder interface, so we need to invert these values - CS - return canonicalize(input, + return canonicalize(input, !ESAPI.securityConfiguration().getAllowMultipleEncoding(), !ESAPI.securityConfiguration().getAllowMixedEncoding() ); } - + /** * {@inheritDoc} */ @@ -152,7 +152,7 @@ public String canonicalize( String input, boolean restrictMultiple, boolean rest if ( input == null ) { return null; } - + String working = input; Codec codecFound = null; int mixedCount = 1; @@ -160,7 +160,7 @@ public String canonicalize( String input, boolean restrictMultiple, boolean rest boolean clean = false; while( !clean ) { clean = true; - + // try each codec and keep track of which ones work Iterator i = codecs.iterator(); while ( i.hasNext() ) { @@ -179,7 +179,7 @@ public String canonicalize( String input, boolean restrictMultiple, boolean rest } } } - + // do strict tests and handle if any mixed, multiple, nested encoding were found if ( foundCount >= 2 && mixedCount > 1 ) { if ( restrictMultiple || restrictMixed ) { @@ -212,20 +212,20 @@ public String encodeForHTML(String input) { if( input == null ) { return null; } - return htmlCodec.encode( IMMUNE_HTML, input); + return htmlCodec.encode( IMMUNE_HTML, input); } - + /** * {@inheritDoc} */ public String decodeForHTML(String input) { - + if( input == null ) { return null; } - return htmlCodec.decode( input); + return htmlCodec.decode( input); } - + /** * {@inheritDoc} */ @@ -236,7 +236,7 @@ public String encodeForHTMLAttribute(String input) { return htmlCodec.encode( IMMUNE_HTMLATTR, input); } - + /** * {@inheritDoc} */ @@ -247,7 +247,7 @@ public String encodeForCSS(String input) { return cssCodec.encode( IMMUNE_CSS, input); } - + /** * {@inheritDoc} */ @@ -265,10 +265,10 @@ public String encodeForVBScript(String input) { if( input == null ) { return null; } - return vbScriptCodec.encode(IMMUNE_VBSCRIPT, input); + return vbScriptCodec.encode(IMMUNE_VBSCRIPT, input); } - + /** * {@inheritDoc} */ @@ -284,7 +284,7 @@ public String encodeForSQL(Codec codec, String input) { */ public String encodeForOS(Codec codec, String input) { if( input == null ) { - return null; + return null; } return codec.encode( IMMUNE_OS, input); } @@ -295,13 +295,13 @@ public String encodeForOS(Codec codec, String input) { public String encodeForLDAP(String input) { return encodeForLDAP(input, true); } - + /** * {@inheritDoc} */ public String encodeForLDAP(String input, boolean encodeWildcards) { if( input == null ) { - return null; + return null; } // TODO: replace with LDAP codec StringBuilder sb = new StringBuilder(); @@ -321,14 +321,14 @@ public String encodeForLDAP(String input, boolean encodeWildcards) { case '/': sb.append("\\2f"); break; - case '*': + case '*': if (encodeWildcards) { - sb.append("\\2a"); + sb.append("\\2a"); } else { sb.append(c); } - + break; case '(': sb.append("\\28"); @@ -351,7 +351,7 @@ public String encodeForLDAP(String input, boolean encodeWildcards) { */ public String encodeForDN(String input) { if( input == null ) { - return null; + return null; } // TODO: replace with DN codec StringBuilder sb = new StringBuilder(); @@ -403,7 +403,7 @@ public String encodeForDN(String input) { */ public String encodeForXPath(String input) { if( input == null ) { - return null; + return null; } return htmlCodec.encode( IMMUNE_XPATH, input); } @@ -413,7 +413,7 @@ public String encodeForXPath(String input) { */ public String encodeForXML(String input) { if( input == null ) { - return null; + return null; } return xmlCodec.encode( IMMUNE_XML, input); } @@ -423,7 +423,7 @@ public String encodeForXML(String input) { */ public String encodeForXMLAttribute(String input) { if( input == null ) { - return null; + return null; } return xmlCodec.encode( IMMUNE_XMLATTR, input); } @@ -484,28 +484,28 @@ public byte[] decodeFromBase64(String input) throws IOException { } return Base64.decode( input ); } - + /** * {@inheritDoc} - * - * This will extract each piece of a URI according to parse zone as specified in RFC-3986 section 3, - * and it will construct a canonicalized String representing a version of the URI that is safe to - * run regex against. - * + * + * This will extract each piece of a URI according to parse zone as specified in RFC-3986 section 3, + * and it will construct a canonicalized String representing a version of the URI that is safe to + * run regex against. + * * @param dirtyUri * @return Canonicalized URI string. * @throws IntrusionException */ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ - -// From RFC-3986 section 3 + +// From RFC-3986 section 3 // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] // // hier-part = "//" authority path-abempty // / path-absolute // / path-rootless // / path-empty - + // The following are two example URIs and their component parts: // // foo://example.com:8042/over/there?name=ferret#nose @@ -527,14 +527,14 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ parseMap.put(UriSegment.PATH, dirtyUri.getRawPath()); parseMap.put(UriSegment.QUERY, dirtyUri.getRawQuery()); parseMap.put(UriSegment.FRAGMENT, dirtyUri.getRawFragment()); - - //Now we canonicalize each part and build our string. + + //Now we canonicalize each part and build our string. StringBuilder sb = new StringBuilder(); - + //Replace all the items in the map with canonicalized versions. - + Set set = parseMap.keySet(); - + SecurityConfiguration sg = ESAPI.securityConfiguration(); boolean allowMixed = sg.getBooleanProp("Encoder.AllowMixedEncoding"); boolean allowMultiple = sg.getBooleanProp("Encoder.AllowMultipleEncoding"); @@ -549,7 +549,7 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ Set>> query = canonicalizedMap.entrySet(); Iterator>> i = query.iterator(); while(i.hasNext()){ - Entry> e = i.next(); + Entry> e = i.next(); String key = e.getKey(); String qVal = ""; List list = e.getValue(); @@ -559,7 +559,7 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ qBuilder.append(key) .append("=") .append(qVal); - + if(i.hasNext()){ qBuilder.append("&"); } @@ -577,13 +577,13 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ } parseMap.put(seg, value ); } - + return buildUrl(parseMap); } - + /** - * All the parts should be canonicalized by this point. This is straightforward assembly. - * + * All the parts should be canonicalized by this point. This is straightforward assembly. + * * @param parseMap The parts of the URL to put back together. * @return The canonicalized URL. */ @@ -592,28 +592,28 @@ protected String buildUrl(Map parseMap){ sb.append(parseMap.get(UriSegment.SCHEME)) .append("://") //can't use SCHEMESPECIFICPART for this, because we need to canonicalize all the parts of the query. - //USERINFO is also deprecated. So we technically have more than we need. + //USERINFO is also deprecated. So we technically have more than we need. .append(parseMap.get(UriSegment.AUTHORITY) == null || parseMap.get(UriSegment.AUTHORITY).equals("") ? "" : parseMap.get(UriSegment.AUTHORITY)) .append(parseMap.get(UriSegment.PATH) == null || parseMap.get(UriSegment.PATH).equals("") ? "" : parseMap.get(UriSegment.PATH)) - .append(parseMap.get(UriSegment.QUERY) == null || parseMap.get(UriSegment.QUERY).equals("") + .append(parseMap.get(UriSegment.QUERY) == null || parseMap.get(UriSegment.QUERY).equals("") ? "" : "?" + parseMap.get(UriSegment.QUERY)) .append((parseMap.get(UriSegment.FRAGMENT) == null) || parseMap.get(UriSegment.FRAGMENT).equals("") ? "": "#" + parseMap.get(UriSegment.FRAGMENT)) ; return sb.toString(); } - + public enum UriSegment { AUTHORITY, SCHEME, SCHEMSPECIFICPART, USERINFO, HOST, PORT, PATH, QUERY, FRAGMENT } - - + + /** * The meat of this method was taken from StackOverflow: http://stackoverflow.com/a/13592567/557153 - * It has been modified to return a canonicalized key and value pairing. - * + * It has been modified to return a canonicalized key and value pairing. + * * @param uri The URI to analyze. - * @return a map of canonicalized query parameters. + * @return a map of canonicalized query parameters. * @throws UnsupportedEncodingException */ public Map> splitQuery(URI uri) throws UnsupportedEncodingException { diff --git a/src/main/java/org/owasp/esapi/reference/DefaultExecutor.java b/src/main/java/org/owasp/esapi/reference/DefaultExecutor.java index a086b247f..619e633ec 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultExecutor.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultExecutor.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -34,10 +34,10 @@ /** * Reference implementation of the Executor interface. This implementation is very restrictive. Commands must exactly - * equal the canonical path to an executable on the system. - * + * equal the canonical path to an executable on the system. + * *

      Valid characters for parameters are codec dependent, but will usually only include alphanumeric, forward-slash, and dash.

      - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 * @see org.owasp.esapi.Executor @@ -60,7 +60,7 @@ public static Executor getInstance() { private final Logger logger = ESAPI.getLogger("Executor"); private Codec codec = null; //private final int MAX_SYSTEM_COMMAND_LENGTH = 2500; - + /** * Instantiate a new Executor @@ -100,18 +100,18 @@ public ExecuteResult executeSystemCommand(File executable, List params, File wor if (!executable.exists()) { throw new ExecutorException("Execution failure", "No such executable: " + executable); } - + // executable must use canonical path if ( !executable.isAbsolute() ) { throw new ExecutorException("Execution failure", "Attempt to invoke an executable using a non-absolute path: " + executable); } - + // executable must use canonical path if ( !executable.getPath().equals( executable.getCanonicalPath() ) ) { throw new ExecutorException("Execution failure", "Attempt to invoke an executable using a non-canonical path: " + executable); } - - // exact, absolute, canonical path to executable must be listed in ESAPI configuration + + // exact, absolute, canonical path to executable must be listed in ESAPI configuration List approved = ESAPI.securityConfiguration().getAllowedExecutables(); if (!approved.contains(executable.getPath())) { throw new ExecutorException("Execution failure", "Attempt to invoke executable that is not listed as an approved executable in ESAPI configuration: " + executable.getPath() + " not listed in " + approved ); @@ -122,19 +122,19 @@ public ExecuteResult executeSystemCommand(File executable, List params, File wor String param = (String)params.get(i); params.set( i, ESAPI.encoder().encodeForOS(codec, param)); } - + // working directory must exist if (!workdir.exists()) { throw new ExecutorException("Execution failure", "No such working directory for running executable: " + workdir.getPath()); } - + // set the command into the list and create command array params.add(0, executable.getCanonicalPath()); // Legacy - this is how to implement in Java 1.4 // String[] command = (String[])params.toArray( new String[0] ); // Process process = Runtime.getRuntime().exec(command, new String[0], workdir); - + // The following is host to implement in Java 1.5+ ProcessBuilder pb = new ProcessBuilder(params); Map env = pb.environment(); @@ -196,7 +196,7 @@ public ExecuteResult executeSystemCommand(File executable, List params, File wor /** * readStream reads lines from an input stream and returns all of them in a single string - * + * * @param is * input stream to read from * @throws IOException @@ -209,7 +209,7 @@ private static void readStream( InputStream is, StringBuilder sb ) throws IOExce sb.append(line).append('\n'); } } - + private static class ReadThread extends Thread { volatile IOException exception; private final InputStream stream; diff --git a/src/main/java/org/owasp/esapi/reference/DefaultHTTPUtilities.java b/src/main/java/org/owasp/esapi/reference/DefaultHTTPUtilities.java index 9bd2a98f4..53fe6135e 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultHTTPUtilities.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultHTTPUtilities.java @@ -256,7 +256,7 @@ public void assertSecureChannel() throws AccessControlException { /** * {@inheritDoc} - * + * * This implementation ignores the built-in isSecure() method * and uses the URL to determine if the request was transmitted over SSL. * This is because SSL may have been terminated somewhere outside the @@ -430,7 +430,7 @@ public void encryptStateInCookie(HttpServletResponse response, Map T getRequestAttribute(HttpServletRequest request, String key) { return (T) request.getAttribute( key ); } - + ///////////////////// - + /* Helper method to encrypt using new Encryptor encryption methods and * return the serialized ciphertext as a hex-encoded string. */ @@ -1086,7 +1086,7 @@ private String encryptString(String plaintext) throws EncryptionException { byte[] serializedCiphertext = ct.asPortableSerializedByteArray(); return Hex.encode(serializedCiphertext, false); } - + /* Helper method to decrypt a hex-encode serialized ciphertext string and * to decrypt it using the new Encryptor decryption methods. */ diff --git a/src/main/java/org/owasp/esapi/reference/DefaultIntrusionDetector.java b/src/main/java/org/owasp/esapi/reference/DefaultIntrusionDetector.java index 53910bcbf..9f9c0e432 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultIntrusionDetector.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultIntrusionDetector.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -39,7 +39,7 @@ * user's session, so that it will be properly cleaned up when the session is * terminated. State is not otherwise persisted, so attacks that span sessions * will not be detectable. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -52,7 +52,7 @@ public class DefaultIntrusionDetector implements org.owasp.esapi.IntrusionDetect public DefaultIntrusionDetector() { } - + /** * {@inheritDoc} * @@ -60,21 +60,21 @@ public DefaultIntrusionDetector() { */ public void addException(Exception e) { if (ESAPI.securityConfiguration().getDisableIntrusionDetection()) return; - + if ( e instanceof EnterpriseSecurityException ) { logger.warning( Logger.SECURITY_FAILURE, ((EnterpriseSecurityException)e).getLogMessage(), e ); } else { logger.warning( Logger.SECURITY_FAILURE, e.getMessage(), e ); } - // add the exception to the current user, which may trigger a detector + // add the exception to the current user, which may trigger a detector User user = ESAPI.authenticator().getCurrentUser(); String eventName = e.getClass().getName(); if ( e instanceof IntrusionException) { return; } - + // add the exception to the user's store, handle IntrusionException if thrown try { addSecurityEvent(user, eventName); @@ -94,10 +94,10 @@ public void addException(Exception e) { */ public void addEvent(String eventName, String logMessage) throws IntrusionException { if (ESAPI.securityConfiguration().getDisableIntrusionDetection()) return; - + logger.warning( Logger.SECURITY_FAILURE, "Security event " + eventName + " received : " + logMessage ); - // add the event to the current user, which may trigger a detector + // add the event to the current user, which may trigger a detector User user = ESAPI.authenticator().getCurrentUser(); try { addSecurityEvent(user, "event." + eventName); @@ -115,7 +115,7 @@ public void addEvent(String eventName, String logMessage) throws IntrusionExcept /** * Take a specified security action. In this implementation, acceptable * actions are: log, disable, logout. - * + * * @param action * the action to take (log, disable, logout) * @param message @@ -123,7 +123,7 @@ public void addEvent(String eventName, String logMessage) throws IntrusionExcept */ private void takeSecurityAction( String action, String message ) { if (ESAPI.securityConfiguration().getDisableIntrusionDetection()) return; - + if ( action.equals( "log" ) ) { logger.fatal( Logger.SECURITY_FAILURE, "INTRUSION - " + message ); } @@ -141,7 +141,7 @@ private void takeSecurityAction( String action, String message ) { /** * Adds a security event to the user. These events are used to check that the user has not * reached the security thresholds set in the properties file. - * + * * @param user * The user that caused the event. * @param eventName @@ -149,11 +149,11 @@ private void takeSecurityAction( String action, String message ) { */ private void addSecurityEvent(User user, String eventName) { if (ESAPI.securityConfiguration().getDisableIntrusionDetection()) return; - + if ( user.isAnonymous() ) return; - + HashMap eventMap = user.getEventMap(); - + // if there is a threshold, then track this event Threshold threshold = ESAPI.securityConfiguration().getQuota( eventName ); if ( threshold != null ) { @@ -176,14 +176,14 @@ public Event( String key ) { } public void increment(int count, long interval) throws IntrusionException { if (ESAPI.securityConfiguration().getDisableIntrusionDetection()) return; - + Date now = new Date(); times.add( 0, now ); while ( times.size() > count ) times.remove( times.size()-1 ); if ( times.size() == count ) { Date past = (Date)times.get( count-1 ); long plong = past.getTime(); - long nlong = now.getTime(); + long nlong = now.getTime(); if ( nlong - plong < interval * 1000 ) { throw new IntrusionException( "Threshold exceeded", "Exceeded threshold for " + key ); } diff --git a/src/main/java/org/owasp/esapi/reference/DefaultRandomizer.java b/src/main/java/org/owasp/esapi/reference/DefaultRandomizer.java index 6d4d65eb0..6ac3b4f70 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultRandomizer.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultRandomizer.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -28,7 +28,7 @@ /** * Reference implementation of the Randomizer interface. This implementation builds on the JCE provider to provide a * cryptographically strong source of entropy. The specific algorithm used is configurable in ESAPI.properties. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 * @see org.owasp.esapi.Randomizer @@ -83,21 +83,21 @@ public String getRandomString(int length, char[] characterSet) { public boolean getRandomBoolean() { return secureRandom.nextBoolean(); } - + /** * {@inheritDoc} */ public int getRandomInteger(int min, int max) { return secureRandom.nextInt(max - min) + min; } - + /** * {@inheritDoc} */ public long getRandomLong() { - return secureRandom.nextLong(); + return secureRandom.nextLong(); } - + /** * {@inheritDoc} */ @@ -114,14 +114,14 @@ public String getRandomFilename(String extension) { logger.debug(Logger.SECURITY_SUCCESS, "Generated new random filename: " + fn ); return fn; } - + /** * {@inheritDoc} */ public String getRandomGUID() throws EncryptionException { return UUID.randomUUID().toString(); } - + /** * {@inheritDoc} */ @@ -130,5 +130,5 @@ public byte[] getRandomBytes(int n) { secureRandom.nextBytes(result); return result; } - + } diff --git a/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java b/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java index da64fd894..50c4ba4d5 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java @@ -2,7 +2,7 @@ * 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{ + * Enterprise Security API (ESAPI) project. For details, please see{ * http://www.owasp.org/index.php/ESAPI. * * Copyright (c) 2007 - The OWASP Foundation diff --git a/src/main/java/org/owasp/esapi/reference/DefaultUser.java b/src/main/java/org/owasp/esapi/reference/DefaultUser.java index c9d448c2b..c9065427b 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultUser.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultUser.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -32,7 +32,7 @@ import java.util.HashMap; /** * Reference implementation of the User interface. This implementation is serialized into a flat file in a simple format. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @author Chris Schmidt (chrisisbeef .at. gmail.com) Digital Ritual Software * @since June 1, 2007 @@ -45,13 +45,13 @@ public class DefaultUser implements User, Serializable { /** The idle timeout length specified in the ESAPI config file. */ private static final int IDLE_TIMEOUT_LENGTH = ESAPI.securityConfiguration().getSessionIdleTimeoutLength(); - + /** The absolute timeout length specified in the ESAPI config file. */ private static final int ABSOLUTE_TIMEOUT_LENGTH = ESAPI.securityConfiguration().getSessionAbsoluteTimeoutLength(); - + /** The logger used by the class. */ private transient final Logger logger = ESAPI.getLogger("DefaultUser"); - + /** This user's account id. */ long accountId = 0; @@ -87,27 +87,27 @@ public class DefaultUser implements User, Serializable { /** The last failed login time for this user. */ private Date lastFailedLoginTime = new Date(0); - + /** The expiration date/time for this user's account. */ private Date expirationTime = new Date(Long.MAX_VALUE); /** The sessions this user is associated with */ private transient Set sessions = new HashSet(); - - /** The event map for this User */ + + /** The event map for this User */ private transient HashMap eventMap = new HashMap(); - + /* A flag to indicate that the password must be changed before the account can be used. */ // private boolean requiresPasswordChange = true; - + /** The failed login count for this user's account. */ private int failedLoginCount = 0; - + /** This user's Locale. */ private Locale locale; - + private static final int MAX_ROLE_LENGTH = 250; - + /** * Instantiates a new user. * @@ -162,7 +162,7 @@ public void disable() { enabled = false; logger.info( Logger.SECURITY_SUCCESS, "Account disabled: " + getAccountName() ); } - + /** * {@inheritDoc} */ @@ -205,10 +205,10 @@ public Date getExpirationTime() { public int getFailedLoginCount() { return failedLoginCount; } - + /** * Set the failed login count - * + * * @param count * the number of failed logins */ @@ -253,14 +253,14 @@ public Date getLastPasswordChangeTime() { public String getName() { return this.getAccountName(); } - + /** * {@inheritDoc} */ public Set getRoles() { return Collections.unmodifiableSet(roles); } - + /** * {@inheritDoc} */ @@ -274,21 +274,21 @@ public String getScreenName() { public void addSession( HttpSession s ) { sessions.add( s ); } - + /** * {@inheritDoc} */ public void removeSession( HttpSession s ) { sessions.remove( s ); } - + /** * {@inheritDoc} */ public Set getSessions() { return sessions; } - + /** * {@inheritDoc} */ @@ -386,28 +386,28 @@ public void loginWithPassword(String password) throws AuthenticationException { incrementFailedLoginCount(); throw new AuthenticationLoginException( "Login failed", "Missing password: " + accountName ); } - + // don't let disabled users log in if ( !isEnabled() ) { setLastFailedLoginTime(new Date()); incrementFailedLoginCount(); throw new AuthenticationLoginException("Login failed", "Disabled user attempt to login: " + accountName ); } - + // don't let locked users log in if ( isLocked() ) { setLastFailedLoginTime(new Date()); incrementFailedLoginCount(); throw new AuthenticationLoginException("Login failed", "Locked user attempt to login: " + accountName ); } - + // don't let expired users log in if ( isExpired() ) { setLastFailedLoginTime(new Date()); incrementFailedLoginCount(); throw new AuthenticationLoginException("Login failed", "Expired user attempt to login: " + accountName ); } - + logout(); if ( verifyPassword( password ) ) { @@ -427,14 +427,14 @@ public void loginWithPassword(String password) throws AuthenticationException { throw new AuthenticationLoginException("Login failed", "Incorrect password provided for " + getAccountName() ); } } - + /** * {@inheritDoc} */ public void logout() { ESAPI.httpUtilities().killCookie( ESAPI.currentRequest(), ESAPI.currentResponse(), HTTPUtilities.REMEMBER_TOKEN_COOKIE_NAME ); - + HttpSession session = ESAPI.currentRequest().getSession(false); if (session != null) { removeSession(session); @@ -456,14 +456,14 @@ public void removeRole(String role) { /** * {@inheritDoc} - * + * * In this implementation, we have chosen to use a random token that is * stored in the User object. Note that it is possible to avoid the use of * server side state by using either the hash of the users's session id or * an encrypted token that includes a timestamp and the user's IP address. * user's IP address. A relatively short 8 character string has been chosen * because this token will appear in all links and forms. - * + * * @return the string */ public String resetCSRFToken() { @@ -479,8 +479,8 @@ public String resetCSRFToken() { private void setAccountId(long accountId) { this.accountId = accountId; } - - + + /** * {@inheritDoc} */ @@ -510,7 +510,7 @@ public void setLastFailedLoginTime(Date lastFailedLoginTime) { this.lastFailedLoginTime = lastFailedLoginTime; logger.info(Logger.SECURITY_SUCCESS, "Set last failed login time to " + lastFailedLoginTime + " for " + getAccountName() ); } - + /** * {@inheritDoc} */ @@ -571,14 +571,14 @@ public void unlock() { this.failedLoginCount = 0; logger.info( Logger.SECURITY_SUCCESS, "Account unlocked: " + getAccountName() ); } - + /** * {@inheritDoc} */ public boolean verifyPassword(String password) { return ESAPI.authenticator().verifyPassword(this, password); } - + /** * Override clone and make final to prevent duplicate user objects. * @return Nothing, as clone() is not supported for this class. A CloneNotSupportedException is always thrown for this class. @@ -600,9 +600,9 @@ public Locale getLocale() { public void setLocale(Locale locale) { this.locale = locale; } - + public HashMap getEventMap() { return eventMap; } - + } diff --git a/src/main/java/org/owasp/esapi/reference/DefaultValidator.java b/src/main/java/org/owasp/esapi/reference/DefaultValidator.java index 09573ed9d..6dd3728ac 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultValidator.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultValidator.java @@ -88,7 +88,7 @@ * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @author Jim Manico (jim@manico.net) Manico.net - * @author Matt Seil (mseil .at. acm.org) + * @author Matt Seil (mseil .at. acm.org) * * @since June 1, 2007 * @see org.owasp.esapi.Validator @@ -349,14 +349,14 @@ public boolean isValidDate(String context, String input, DateFormat format, bool */ @Override public Date getValidDate(String context, String input, DateFormat format, boolean allowNull) throws ValidationException, IntrusionException { - + ValidationErrorList vel = new ValidationErrorList(); Date validDate = getValidDate(context, input, format, allowNull, vel); - + if (vel.isEmpty()) { return validDate; } - + throw vel.errors().get(0); } @@ -1354,7 +1354,7 @@ private final boolean isEmpty(byte[] input) { private final boolean isEmpty(char[] input) { return (input==null || input.length == 0); } - + /** * {@inheritDoc} */ @@ -1367,12 +1367,12 @@ public boolean isValidURI(String context, String input, boolean allowNull) { URI compliantURI = null == input ? new URI("") : this.getRfcCompliantURI(input); if(null != compliantURI && input != null){ String canonicalizedURI = encoder.getCanonicalizedURI(compliantURI); - //if getCanonicalizedURI doesn't throw an IntrusionException, then the URI contains no mixed or - //double-encoding attacks. + //if getCanonicalizedURI doesn't throw an IntrusionException, then the URI contains no mixed or + //double-encoding attacks. logger.debug(Logger.SECURITY_SUCCESS, "We did not detect any mixed or multiple encoding in the uri:[" + input + "]"); Validator v = ESAPI.validator(); - //This part will use the regex from validation.properties. This regex should be super-simple, and - //used mainly to restrict certain parts of a URL. + //This part will use the regex from validation.properties. This regex should be super-simple, and + //used mainly to restrict certain parts of a URL. Pattern p = ESAPI.securityConfiguration().getValidationPattern( "URL" ); if(p != null){ //We're doing this instead of using the normal validator API, because it will canonicalize the input again @@ -1387,18 +1387,18 @@ public boolean isValidURI(String context, String input, boolean allowNull) { isValid = true; } } - + }catch (IntrusionException e){ logger.error(Logger.SECURITY_FAILURE, e.getMessage()); isValid = false; } catch (URISyntaxException e) { logger.error(Logger.EVENT_FAILURE, e.getMessage()); } - - + + return isValid; } - + /** * {@inheritDoc} */ diff --git a/src/main/java/org/owasp/esapi/reference/FileBasedAuthenticator.java b/src/main/java/org/owasp/esapi/reference/FileBasedAuthenticator.java index ed0b16b17..111e3f8be 100644 --- a/src/main/java/org/owasp/esapi/reference/FileBasedAuthenticator.java +++ b/src/main/java/org/owasp/esapi/reference/FileBasedAuthenticator.java @@ -252,9 +252,9 @@ public synchronized User createUser(String accountName, String password1, String if (password1 == null) { throw new AuthenticationCredentialsException("Invalid account name", "Attempt to create account " + accountName + " with a null password"); } - + DefaultUser user = new DefaultUser(accountName); - + verifyPasswordStrength(null, password1, user); if (!password1.equals(password2)) { @@ -389,7 +389,7 @@ public synchronized User getUser(String accountName) { return null; } - + /** * {@inheritDoc} @@ -666,7 +666,7 @@ private String dump(Collection c) { return sb.toString().substring(0, sb.length() - 1); } return ""; - + } /** @@ -741,9 +741,9 @@ public void verifyPasswordStrength(String oldPassword, String newPassword, User if (strength < 16) { throw new AuthenticationCredentialsException("Invalid password", "New password is not long and complex enough"); } - + String accountName = user.getAccountName(); - + //jtm - 11/3/2010 - fix for bug http://code.google.com/p/owasp-esapi-java/issues/detail?id=108 if (accountName.equalsIgnoreCase(newPassword)) { //password can't be account name diff --git a/src/main/java/org/owasp/esapi/reference/IntegerAccessReferenceMap.java b/src/main/java/org/owasp/esapi/reference/IntegerAccessReferenceMap.java index 32dab104a..24ff9d6e9 100644 --- a/src/main/java/org/owasp/esapi/reference/IntegerAccessReferenceMap.java +++ b/src/main/java/org/owasp/esapi/reference/IntegerAccessReferenceMap.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -20,7 +20,7 @@ /** * Reference implementation of the AccessReferenceMap interface. This * implementation generates integers for indirect references. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) * @author Chris Schmidt (chrisisbeef@gmail.com) * @since June 1, 2007 diff --git a/src/main/java/org/owasp/esapi/reference/accesscontrol/AlwaysTrueACR.java b/src/main/java/org/owasp/esapi/reference/accesscontrol/AlwaysTrueACR.java index f58e4e783..a132722ba 100644 --- a/src/main/java/org/owasp/esapi/reference/accesscontrol/AlwaysTrueACR.java +++ b/src/main/java/org/owasp/esapi/reference/accesscontrol/AlwaysTrueACR.java @@ -1,7 +1,7 @@ package org.owasp.esapi.reference.accesscontrol; public class AlwaysTrueACR extends BaseACR { - + // @Override public boolean isAuthorized(Object runtimeParameter) { return true; diff --git a/src/main/java/org/owasp/esapi/reference/accesscontrol/BaseACR.java b/src/main/java/org/owasp/esapi/reference/accesscontrol/BaseACR.java index 8814b954f..1e307a731 100644 --- a/src/main/java/org/owasp/esapi/reference/accesscontrol/BaseACR.java +++ b/src/main/java/org/owasp/esapi/reference/accesscontrol/BaseACR.java @@ -5,12 +5,12 @@ abstract public class BaseACR implements AccessControlRule { protected P policyParameters; - + // @Override public void setPolicyParameters(P policyParameter) { this.policyParameters = policyParameter; } - + // @Override public P getPolicyParameters() { return policyParameters; diff --git a/src/main/java/org/owasp/esapi/reference/accesscontrol/DelegatingACR.java b/src/main/java/org/owasp/esapi/reference/accesscontrol/DelegatingACR.java index 91a86d74b..eaa35799c 100644 --- a/src/main/java/org/owasp/esapi/reference/accesscontrol/DelegatingACR.java +++ b/src/main/java/org/owasp/esapi/reference/accesscontrol/DelegatingACR.java @@ -11,7 +11,7 @@ public class DelegatingACR extends BaseACR { protected Method delegateMethod; protected Object delegateInstance; - + @Override public void setPolicyParameters(DynaBeanACRParameter policyParameter) { String delegateClassName = policyParameter.getString("delegateClass", "").trim(); @@ -24,35 +24,35 @@ public void setPolicyParameters(DynaBeanACRParameter policyParameter) { try { this.delegateMethod = delegateClass.getMethod(methodName, parameterClasses); } catch (SecurityException e) { - throw new IllegalArgumentException(e.getMessage() + - " delegateClass.delegateMethod(parameterClasses): \"" + + throw new IllegalArgumentException(e.getMessage() + + " delegateClass.delegateMethod(parameterClasses): \"" + delegateClassName + "." + methodName + "(" + Arrays.toString(parameterClassNames) + ")\" must be public.", e); } catch (NoSuchMethodException e) { - throw new IllegalArgumentException(e.getMessage() + - " delegateClass.delegateMethod(parameterClasses): \"" + + throw new IllegalArgumentException(e.getMessage() + + " delegateClass.delegateMethod(parameterClasses): \"" + delegateClassName + "." + methodName + "(" + Arrays.toString(parameterClassNames) + ")\" does not exist.", e); } - + //static methods do not need a delegateInstance. Non-static methods do. if(!Modifier.isStatic(this.delegateMethod.getModifiers())) { try { this.delegateInstance = delegateClass.newInstance(); } catch (InstantiationException ex) { - throw new IllegalArgumentException( - " Delegate class \"" + delegateClassName + + throw new IllegalArgumentException( + " Delegate class \"" + delegateClassName + "\" must be concrete, because method " + delegateClassName + "." + methodName + "(" + Arrays.toString(parameterClassNames) + ") is not static.", ex); } catch (IllegalAccessException ex) { - new IllegalArgumentException( - " Delegate class \"" + delegateClassName + + new IllegalArgumentException( + " Delegate class \"" + delegateClassName + "\" must must have a zero-argument constructor, because " + - "method delegateClass.delegateMethod(parameterClasses): \"" + + "method delegateClass.delegateMethod(parameterClasses): \"" + delegateClassName + "." + methodName + "(" + Arrays.toString(parameterClassNames) + ")\" is not static.", ex); - } + } } else { this.delegateInstance = null; } @@ -84,10 +84,10 @@ protected final Class getClass(String className, String purpose) { Class theClass = Class.forName(className); return theClass; } catch ( ClassNotFoundException ex ) { - throw new IllegalArgumentException(ex.getMessage() + - " " + purpose + " Class " + className + + throw new IllegalArgumentException(ex.getMessage() + + " " + purpose + " Class " + className + " must be in the classpath", ex); - } + } } /** * Delegates to the method specified in setPolicyParameters diff --git a/src/main/java/org/owasp/esapi/reference/accesscontrol/DynaBeanACRParameter.java b/src/main/java/org/owasp/esapi/reference/accesscontrol/DynaBeanACRParameter.java index 5eea24a91..c0d29f382 100644 --- a/src/main/java/org/owasp/esapi/reference/accesscontrol/DynaBeanACRParameter.java +++ b/src/main/java/org/owasp/esapi/reference/accesscontrol/DynaBeanACRParameter.java @@ -9,18 +9,18 @@ import org.owasp.esapi.reference.accesscontrol.policyloader.PolicyParameters; /** - * A DynaBean comes from the apache bean utils. It is basically a - * convenient way to dynamically assign getters and setters. Essentially, + * A DynaBean comes from the apache bean utils. It is basically a + * convenient way to dynamically assign getters and setters. Essentially, * the way we use DynaBean is a HashMap that can be set to read only. * @author Mike H. Fauzy */ public class DynaBeanACRParameter implements PolicyParameters { protected LazyDynaMap policyProperties; - + public DynaBeanACRParameter() { policyProperties = new LazyDynaMap(); } - + /* (non-Javadoc) * @see org.owasp.esapi.reference.accesscontrol.policyloader.PolicyParameters#get(java.lang.String) */ @@ -107,7 +107,7 @@ public BigInteger getBigInteger(String key) { public Date getDate(String key) { return (Date)get(key); } - + /** * Convenience method to avoid common casts. Note that the time object * is the same as a date object @@ -117,7 +117,7 @@ public Date getDate(String key) { public Date getTime(String key) { return (Date)get(key); } - + /** * Convenience method to avoid common casts. * @param key @@ -126,7 +126,7 @@ public Date getTime(String key) { public String getString(String key) { return (String)get(key); } - + /** * Convenience method to avoid common casts. * @param key @@ -135,7 +135,7 @@ public String getString(String key) { public String getString(String key, String defaultValue) { return (String)get(key) == null ? defaultValue : (String)get(key); } - + /** * Convenience method to avoid common casts. * @param key @@ -144,15 +144,15 @@ public String getString(String key, String defaultValue) { public String[] getStringArray(String key) { return (String[])get(key); } - + /** * Convenience method to avoid common casts. * @param key - * @return The value of the specified key, returned generically as an Object. + * @return The value of the specified key, returned generically as an Object. */ public Object getObject(String key) { return get(key); - } + } /* (non-Javadoc) * @see org.owasp.esapi.reference.accesscontrol.policyloader.PolicyParameters#set(java.lang.String, java.lang.Object) @@ -166,18 +166,18 @@ public void set(String key, Object value) throws IllegalArgumentException { public void put(String key, Object value) throws IllegalArgumentException { set(key, value); } - + /** - * This makes the map itself read only, but the mutability of objects - * that this map contains is not affected. Specifically, properties - * cannot be added or removed and the reference cannot be changed to - * a different object, but this does not change whether the values that the - * object contains can be changed. + * This makes the map itself read only, but the mutability of objects + * that this map contains is not affected. Specifically, properties + * cannot be added or removed and the reference cannot be changed to + * a different object, but this does not change whether the values that the + * object contains can be changed. */ public void lock() { policyProperties.setRestricted(true); } - + public String toString() { StringBuilder sb = new StringBuilder(); Iterator keys = policyProperties.getMap().keySet().iterator(); diff --git a/src/main/java/org/owasp/esapi/reference/accesscontrol/ExperimentalAccessController.java b/src/main/java/org/owasp/esapi/reference/accesscontrol/ExperimentalAccessController.java index 1d1d6d3a2..0b1e4cfb2 100644 --- a/src/main/java/org/owasp/esapi/reference/accesscontrol/ExperimentalAccessController.java +++ b/src/main/java/org/owasp/esapi/reference/accesscontrol/ExperimentalAccessController.java @@ -14,33 +14,33 @@ public class ExperimentalAccessController implements AccessController { private Map ruleMap; protected final Logger logger = ESAPI.getLogger("DefaultAccessController"); - + public ExperimentalAccessController(Map ruleMap) { - this.ruleMap = ruleMap; + this.ruleMap = ruleMap; } public ExperimentalAccessController() throws AccessControlException { ACRPolicyFileLoader policyDescriptor = new ACRPolicyFileLoader(); - PolicyDTO policyDTO = policyDescriptor.load(); + PolicyDTO policyDTO = policyDescriptor.load(); ruleMap = policyDTO.getAccessControlRules(); } - + public boolean isAuthorized(Object key, Object runtimeParameter) { try { AccessControlRule rule = (AccessControlRule)ruleMap.get(key); if(rule == null) { throw new AccessControlException("Access Denied", - "AccessControlRule was not found for key: " + key); + "AccessControlRule was not found for key: " + key); } if(logger.isDebugEnabled()){ logger.debug(Logger.EVENT_SUCCESS, "Evaluating Authorization Rule \"" + key + "\" Using class: " + rule.getClass().getCanonicalName()); } return rule.isAuthorized(runtimeParameter); } catch(Exception e) { try { //Log the exception by throwing and then catching it. - //TODO figure out what which string goes where. + //TODO figure out what which string goes where. throw new AccessControlException("Access Denied", "An unhandled Exception was " + - "caught, so access is denied.", - e); + "caught, so access is denied.", + e); } catch(AccessControlException ace) { //the exception was just logged. There's nothing left to do. } @@ -54,27 +54,27 @@ public void assertAuthorized(Object key, Object runtimeParameter) try { AccessControlRule rule = (AccessControlRule)ruleMap.get(key); if(rule == null) { - throw new AccessControlException("Access Denied", - "AccessControlRule was not found for key: " + key); + throw new AccessControlException("Access Denied", + "AccessControlRule was not found for key: " + key); } if(logger.isDebugEnabled()){ logger.debug(Logger.EVENT_SUCCESS, "Asserting Authorization Rule \"" + key + "\" Using class: " + rule.getClass().getCanonicalName()); } isAuthorized = rule.isAuthorized(runtimeParameter); } catch(Exception e) { - //TODO figure out what which string goes where. + //TODO figure out what which string goes where. throw new AccessControlException("Access Denied", "An unhandled Exception was " + "caught, so access is denied." + "AccessControlException.", e); } if(!isAuthorized) { - throw new AccessControlException("Access Denied", - "Access Denied for key: " + key + + throw new AccessControlException("Access Denied", + "Access Denied for key: " + key + " runtimeParameter: " + runtimeParameter); } } - + /**** Below this line is legacy support ****/ - + /** * @param action * @param data diff --git a/src/main/java/org/owasp/esapi/reference/accesscontrol/FileBasedACRs.java b/src/main/java/org/owasp/esapi/reference/accesscontrol/FileBasedACRs.java index 8562beb35..2e19304f5 100644 --- a/src/main/java/org/owasp/esapi/reference/accesscontrol/FileBasedACRs.java +++ b/src/main/java/org/owasp/esapi/reference/accesscontrol/FileBasedACRs.java @@ -1,15 +1,15 @@ /** * 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 Mike Fauzy Aspect Security * @author Jeff Williams Aspect Security * @created 2007 @@ -37,7 +37,7 @@ // CHECKME: If this exists for backward compatibility, should this // class be deprecated??? If so, mark it using annotation. /** - * This class exists for backwards compatibility with the AccessController 1.0 + * This class exists for backwards compatibility with the AccessController 1.0 * reference implementation. * * This reference implementation uses a simple model for specifying a set of @@ -78,7 +78,7 @@ * the AccessController interface. These files are located in the ESAPI * resources directory as specified when the JVM was started. The use of a * default deny rule is STRONGLY recommended. The file format is as follows: - * + * *
        * path          | role,role   | allow/deny | comment
        * ------------------------------------------------------------------------------------
      @@ -86,7 +86,7 @@
        * /admin        | admin       | allow      | only admin role can access /admin
        * /             | any         | deny       | default deny rule
        * 
      - * + * * To find the matching rules, this implementation follows the general approach * used in Java EE when matching HTTP requests to servlets in web.xml. The four * mapping rules are used in the following order: @@ -97,7 +97,7 @@ *
    • extension match, beginning *., e.g. *.css
    • *
    • default rule, specified by the single character pattern /
    • * - * + * * @author Mike Fauzy (mike.fauzy@aspectsecurity.com) * @author Jeff Williams (jeff.williams@aspectsecurity.com) * @since June 1, 2007 @@ -146,17 +146,17 @@ public boolean isAuthorizedForFunction(String functionName) throws AccessControl } return matchRule(functionMap, functionName); } - + /** * TODO Javadoc */ public boolean isAuthorizedForData(String action, Object data) throws AccessControlException{ if (dataMap==null || dataMap.isEmpty()) { dataMap = loadDataRules("DataAccessRules.txt"); - } - return matchRule(dataMap, (Class)data, action); + } + return matchRule(dataMap, (Class)data, action); } - + /** * TODO Javadoc */ @@ -170,7 +170,7 @@ public boolean isAuthorizedForFile(String filepath) throws AccessControlExceptio /** * TODO Javadoc */ - public boolean isAuthorizedForService(String serviceName) throws AccessControlException { + public boolean isAuthorizedForService(String serviceName) throws AccessControlException { if (serviceMap==null || serviceMap.isEmpty()) { serviceMap = loadRules("ServiceAccessRules.txt"); } @@ -179,17 +179,17 @@ public boolean isAuthorizedForService(String serviceName) throws AccessControlEx /** * Checks to see if the current user has access to the specified data, File, Object, etc. - * If the User has access, as specified by the map parameter, this method returns true. If the + * If the User has access, as specified by the map parameter, this method returns true. If the * User does not have access or an exception is thrown, false is returned. - * + * * @param map * the map containing access rules * @param path * the path of the requested File, URL, Object, etc. - * - * @return + * + * @return * true, if the user has access, false otherwise - * + * */ private boolean matchRule(Map map, String path) { // get users roles @@ -199,21 +199,21 @@ private boolean matchRule(Map map, String path) { Rule rule = searchForRule(map, roles, path); return rule.allow; } - + /** * Checks to see if the current user has access to the specified Class and action. * If the User has access, as specified by the map parameter, this method returns true. * If the User does not have access or an exception is thrown, false is returned. - * + * * @param map * the map containing access rules * @param clazz * the Class being requested for access * @param action * the action the User has asked to perform - * @return + * @return * true, if the user has access, false otherwise - * + * */ private boolean matchRule(Map map, Class clazz, String action) { // get users roles @@ -229,17 +229,17 @@ private boolean matchRule(Map map, Class clazz, String action) { * e.g. /access/login - longest path prefix match, beginning / and ending * /*, e.g. /access/* or /* - extension match, beginning *., e.g. *.css - * default servlet, specified by the single character pattern / - * + * * @param map * the map containing access rules * @param roles * the roles of the User being checked for access * @param path * the File, URL, Object, etc. being checked for access - * - * @return + * + * @return * the rule stating whether to allow or deny access - * + * */ private Rule searchForRule(Map map, Set roles, String path) { String canonical = ESAPI.encoder().canonicalize(path); @@ -248,7 +248,7 @@ private Rule searchForRule(Map map, Set roles, String path) { if ( part == null ) { part = ""; } - + while (part.endsWith("/")) { part = part.substring(0, part.length() - 1); } @@ -256,7 +256,7 @@ private Rule searchForRule(Map map, Set roles, String path) { if (part.indexOf("..") != -1) { throw new IntrusionException("Attempt to manipulate access control path", "Attempt to manipulate access control path: " + path ); } - + // extract extension if any String extension = ""; int extIndex = part.lastIndexOf("."); @@ -284,22 +284,22 @@ private Rule searchForRule(Map map, Set roles, String path) { if ( slash == -1 ) { return deny; } - + // if there are more parts, strip off the last part and recurse part = part.substring(0, part.lastIndexOf('/')); - + // return default deny if (part.length() <= 1) { return deny; } - + return searchForRule(map, roles, part); } - + /** - * Search for rule. Searches the specified access map to see if any of the roles specified have + * Search for rule. Searches the specified access map to see if any of the roles specified have * access to perform the specified action on the specified Class. - * + * * @param map * the map containing access rules * @param roles @@ -308,10 +308,10 @@ private Rule searchForRule(Map map, Set roles, String path) { * the Class being requested for access * @param action * the action the User has asked to perform - * - * @return + * + * @return * the rule that allows the specified roles access to perform the requested action on the specified Class, or null if access is not granted - * + * */ private Rule searchForRule(Map map, Set roles, Class clazz, String action) { @@ -324,15 +324,15 @@ private Rule searchForRule(Map map, Set roles, Class clazz, String action) { } /** - * Return true if there is overlap between the two sets. This method merely checks to see if + * Return true if there is overlap between the two sets. This method merely checks to see if * ruleRoles contains any of the roles listed in userRoles. - * + * * @param ruleRoles * the rule roles * @param userRoles * the user roles - * - * @return + * + * @return * true, if any roles exist in both Sets. False otherwise. */ private boolean overlap(Set ruleRoles, Set userRoles) { @@ -348,16 +348,16 @@ private boolean overlap(Set ruleRoles, Set userRoles) { } return false; } - + /** * This method merely checks to see if ruleActions contains the action requested. - * + * * @param ruleActions * actions listed for a rule * @param action * the action requested that will be searched for in ruleActions - * - * @return + * + * @return * true, if any action exists in ruleActions. False otherwise. */ private boolean overlap( List ruleActions, String action){ @@ -365,46 +365,46 @@ private boolean overlap( List ruleActions, String action){ return true; return false; } - + /** * Checks that the roles passed in contain only letters, numbers, and underscores. Also checks that - * roles are no more than 10 characters long. If a role does not pass validation, it is not included in the + * roles are no more than 10 characters long. If a role does not pass validation, it is not included in the * list of roles returned by this method. A log warning is also generated for any invalid roles. - * + * * @param roles * roles to validate according to criteria started above * @return * a List of roles that are valid according to the criteria stated above. - * + * */ private List validateRoles(List roles){ - List ret = new ArrayList(); + List ret = new ArrayList(); for(int x = 0; x < roles.size(); x++){ String canonical = ESAPI.encoder().canonicalize(((String)roles.get(x)).trim()); if(!ESAPI.validator().isValidInput("Validating user roles in FileBasedAccessController", canonical, "RoleName", 20, false)) { logger.warning( Logger.SECURITY_FAILURE, "Role: " + ((String)roles.get(x)).trim() + " is invalid, so was not added to the list of roles for this Rule."); - } else { + } else { ret.add(canonical.trim()); } } return ret; } - + /** * Loads access rules by storing them in a hashmap. This method begins reading the File specified by * the ruleset parameter, ignoring any lines that begin with '#' characters as comments. Sections of the access rules file * are split by the pipe character ('|'). The method loads all paths, replacing '\' characters with '/' for uniformity then loads - * the list of comma separated roles. The roles are validated to be sure they are within a + * the list of comma separated roles. The roles are validated to be sure they are within a * length and character set, specified in the validateRoles(String) method. Then the permissions are stored for each item in the rules list. * If the word "allow" appears on the line, the specified roles are granted access to the data - otherwise, they will be denied access. - * - * Each path may only appear once in the access rules file. Any entry, after the first, containing the same path will be logged and ignored. - * + * + * Each path may only appear once in the access rules file. Any entry, after the first, containing the same path will be logged and ignored. + * * @param ruleset * the name of the data that contains access rules - * - * @return + * + * @return * a hash map containing the ruleset */ private Map loadRules(String ruleset) { @@ -420,12 +420,12 @@ private Map loadRules(String ruleset) { String[] parts = line.split("\\|"); // fix Windows paths rule.path = parts[0].trim().replaceAll("\\\\", "/"); - + List roles = commaSplit(parts[1].trim().toLowerCase()); roles = validateRoles(roles); for(int x = 0; x < roles.size(); x++) rule.roles.add(((String)roles.get(x)).trim()); - + String action = parts[2].trim(); rule.allow = action.equalsIgnoreCase("allow"); if (map.containsKey(rule.path)) { @@ -448,19 +448,19 @@ private Map loadRules(String ruleset) { } return map; } - + /** * Loads access rules by storing them in a hashmap. This method begins reading the File specified by * the ruleset parameter, ignoring any lines that begin with '#' characters as comments. Sections of the access rules file - * are split by the pipe character ('|'). The method then loads all Classes, loads the list of comma separated roles, then the list of comma separated actions. - * The roles are validated to be sure they are within a length and character set, specified in the validateRoles(String) method. - * - * Each path may only appear once in the access rules file. Any entry, after the first, containing the same path will be logged and ignored. - * + * are split by the pipe character ('|'). The method then loads all Classes, loads the list of comma separated roles, then the list of comma separated actions. + * The roles are validated to be sure they are within a length and character set, specified in the validateRoles(String) method. + * + * Each path may only appear once in the access rules file. Any entry, after the first, containing the same path will be logged and ignored. + * * @param ruleset * the name of the data that contains access rules - * - * @return + * + * @return * a hash map containing the ruleset */ private Map loadDataRules(String ruleset) { @@ -476,27 +476,27 @@ private Map loadDataRules(String ruleset) { Rule rule = new Rule(); String[] parts = line.split("\\|"); rule.clazz = Class.forName(parts[0].trim()); - + List roles = commaSplit(parts[1].trim().toLowerCase()); roles = validateRoles(roles); for(int x = 0; x < roles.size(); x++) rule.roles.add(((String)roles.get(x)).trim()); - + List action = commaSplit(parts[2].trim().toLowerCase()); for(int x = 0; x < action.size(); x++) rule.actions.add(((String) action.get(x)).trim()); - + if (map.containsKey(rule.path)) { logger.warning( Logger.SECURITY_FAILURE, "Problem in access control file. Duplicate rule ignored: " + rule); } else { - map.put(rule.clazz, rule); + map.put(rule.clazz, rule); } } } } catch (Exception e) { logger.warning( Logger.SECURITY_FAILURE, "Problem in access control file : " + ruleset, e ); } finally { - + try { if (is != null) { is.close(); @@ -510,7 +510,7 @@ private Map loadDataRules(String ruleset) { /** * This method splits a String by the ',' and returns the result as a List. - * + * * @param input * the String to split by ',' * @return @@ -520,29 +520,29 @@ private List commaSplit(String input){ String[] array = input.split(","); return Arrays.asList(array); } - + /** * The Class Rule. */ private class Rule { - + protected String path = ""; - + protected Set roles = new HashSet(); - + protected boolean allow = false; - - + + protected Class clazz = null; - - + + protected List actions = new ArrayList(); /** - * + * * Creates a new Rule object. */ protected Rule() { diff --git a/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/ACRParameterLoaderHelper.java b/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/ACRParameterLoaderHelper.java index cc17bdbe0..d0846fc2a 100644 --- a/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/ACRParameterLoaderHelper.java +++ b/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/ACRParameterLoaderHelper.java @@ -3,44 +3,44 @@ import org.apache.commons.configuration.XMLConfiguration; final public class ACRParameterLoaderHelper { - + public static Object getParameterValue(XMLConfiguration config, int currentRule, int currentParameter, String parameterType) throws Exception { - String key = "AccessControlRules.AccessControlRule(" + + String key = "AccessControlRules.AccessControlRule(" + currentRule + ").Parameters.Parameter(" + currentParameter + ")[@value]"; Object parameterValue; if("String".equalsIgnoreCase(parameterType)) { parameterValue = config.getString(key); } else if("StringArray".equalsIgnoreCase(parameterType)) { parameterValue = config.getStringArray(key); - } else if("Boolean".equalsIgnoreCase(parameterType)){ + } else if("Boolean".equalsIgnoreCase(parameterType)){ parameterValue = config.getBoolean(key); - } else if("Byte".equalsIgnoreCase(parameterType)){ + } else if("Byte".equalsIgnoreCase(parameterType)){ parameterValue = config.getByte(key); - } else if("Int".equalsIgnoreCase(parameterType)){ + } else if("Int".equalsIgnoreCase(parameterType)){ parameterValue = config.getInt(key); - } else if("Long".equalsIgnoreCase(parameterType)){ + } else if("Long".equalsIgnoreCase(parameterType)){ parameterValue = config.getLong(key); - } else if("Float".equalsIgnoreCase(parameterType)){ + } else if("Float".equalsIgnoreCase(parameterType)){ parameterValue = config.getFloat(key); - } else if("Double".equalsIgnoreCase(parameterType)){ + } else if("Double".equalsIgnoreCase(parameterType)){ parameterValue = config.getDouble(key); - } else if("BigDecimal".equalsIgnoreCase(parameterType)){ + } else if("BigDecimal".equalsIgnoreCase(parameterType)){ parameterValue = config.getBigDecimal(key); - } else if("BigInteger".equalsIgnoreCase(parameterType)){ + } else if("BigInteger".equalsIgnoreCase(parameterType)){ parameterValue = config.getBigInteger(key); } else if("Date".equalsIgnoreCase(parameterType)){ parameterValue = java.text.DateFormat.getDateInstance().parse(config.getString(key)); } else if("Time".equalsIgnoreCase(parameterType)){ java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("h:mm a"); - parameterValue = sdf.parseObject(config.getString(key)); + parameterValue = sdf.parseObject(config.getString(key)); // parameterValue = java.text.DateFormat.getTimeInstance().parse(config.getString(key)); - } + } //add timestamp. check for other stuff. else { - throw new IllegalArgumentException("Unable to load the key \"" + key - + "\", because " + "the type \"" + parameterType + + throw new IllegalArgumentException("Unable to load the key \"" + key + + "\", because " + "the type \"" + parameterType + "\" was not recognized." ); } return parameterValue; - } + } } diff --git a/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/ACRPolicyFileLoader.java b/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/ACRPolicyFileLoader.java index cc97d8580..9a7f5955b 100644 --- a/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/ACRPolicyFileLoader.java +++ b/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/ACRPolicyFileLoader.java @@ -11,14 +11,14 @@ final public class ACRPolicyFileLoader { protected final Logger logger = ESAPI.getLogger("ACRPolicyFileLoader"); - + public PolicyDTO load() throws AccessControlException { PolicyDTO policyDTO = new PolicyDTO(); XMLConfiguration config; - File file = ESAPI.securityConfiguration().getResourceFile("ESAPI-AccessControlPolicy.xml"); + File file = ESAPI.securityConfiguration().getResourceFile("ESAPI-AccessControlPolicy.xml"); try { - config = new XMLConfiguration(file); + config = new XMLConfiguration(file); } catch(ConfigurationException cex) { @@ -26,7 +26,7 @@ public PolicyDTO load() throws AccessControlException { throw new AccessControlException("Unable to load configuration file for the following: " + "ESAPI-AccessControlPolicy.xml", "", cex); } throw new AccessControlException("Unable to load configuration file from the following location: " + file.getAbsolutePath(), "", cex); - } + } Object property = config.getProperty("AccessControlRules.AccessControlRule[@name]"); logger.info(Logger.EVENT_SUCCESS, "Loading Property: " + property); @@ -34,12 +34,12 @@ public PolicyDTO load() throws AccessControlException { if(property instanceof Collection) { numberOfRules = ((Collection)property).size(); } //implied else property == null -> return new PolicyDTO - + String ruleName = ""; String ruleClass = ""; Object rulePolicyParameter = null; int currentRule = 0; - try { + try { logger.info(Logger.EVENT_SUCCESS, "Number of rules: " + numberOfRules); for(currentRule = 0; currentRule < numberOfRules; currentRule++) { logger.trace(Logger.EVENT_SUCCESS, "----"); @@ -52,12 +52,12 @@ public PolicyDTO load() throws AccessControlException { policyDTO.addAccessControlRule( ruleName, ruleClass, - rulePolicyParameter); + rulePolicyParameter); } logger.info(Logger.EVENT_SUCCESS, "policyDTO loaded: " + policyDTO); } catch (Exception e) { - throw new AccessControlException("Unable to load AccessControlRule parameter. " + - " Rule number: " + currentRule + + throw new AccessControlException("Unable to load AccessControlRule parameter. " + + " Rule number: " + currentRule + " Probably: Rule.name: " + ruleName + " Probably: Rule.class: " + ruleClass + e.getMessage(), "", e); @@ -73,15 +73,15 @@ protected Object getPolicyParameter(XMLConfiguration config, int currentRule) if(property == null) { return null; } - - int numberOfProperties = 0; + + int numberOfProperties = 0; if(property instanceof Collection) { - numberOfProperties = ((Collection)property).size(); + numberOfProperties = ((Collection)property).size(); } else { numberOfProperties = 1; } logger.info(Logger.EVENT_SUCCESS, "Number of properties: " + numberOfProperties); - + if(numberOfProperties < 1) { return null; } @@ -91,9 +91,9 @@ protected Object getPolicyParameter(XMLConfiguration config, int currentRule) parametersLoaderClassName = "org.owasp.esapi.reference.accesscontrol.policyloader.DynaBeanACRParameterLoader"; } logger.info(Logger.EVENT_SUCCESS, "Parameters Loader:" + parametersLoaderClassName); - ACRParameterLoader acrParamaterLoader = + ACRParameterLoader acrParamaterLoader = (ACRParameterLoader) Class.forName(parametersLoaderClassName).newInstance(); - return acrParamaterLoader.getParameters(config, currentRule); + return acrParamaterLoader.getParameters(config, currentRule); } } \ No newline at end of file diff --git a/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/DynaBeanACRParameterLoader.java b/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/DynaBeanACRParameterLoader.java index ce6b28096..14174625d 100644 --- a/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/DynaBeanACRParameterLoader.java +++ b/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/DynaBeanACRParameterLoader.java @@ -7,11 +7,11 @@ import static org.owasp.esapi.reference.accesscontrol.policyloader.ACRParameterLoaderHelper.getParameterValue; -final public class DynaBeanACRParameterLoader +final public class DynaBeanACRParameterLoader implements ACRParameterLoader { - + Logger logger = ESAPI.getLogger(this.getClass()); - + // @Override public DynaBeanACRParameter getParameters(XMLConfiguration config, int currentRule) throws java.lang.Exception { //TODO reduce the exception DynaBeanACRParameter policyParameter = new DynaBeanACRParameter(); @@ -22,8 +22,8 @@ public DynaBeanACRParameter getParameters(XMLConfiguration config, int currentRu Object parameterValue = getParameterValue(config, currentRule, currentParameter, parameterType); policyParameter.set(parameterName, parameterValue); } - policyParameter.lock(); //This line makes the policyParameter read only. - logger.info(Logger.SECURITY_SUCCESS, "Loaded " + numberOfParameters + + policyParameter.lock(); //This line makes the policyParameter read only. + logger.info(Logger.SECURITY_SUCCESS, "Loaded " + numberOfParameters + " parameters: " + policyParameter.toString()); return policyParameter; } diff --git a/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/EchoDynaBeanPolicyParameterACR.java b/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/EchoDynaBeanPolicyParameterACR.java index 4b8424393..f30919c71 100644 --- a/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/EchoDynaBeanPolicyParameterACR.java +++ b/src/main/java/org/owasp/esapi/reference/accesscontrol/policyloader/EchoDynaBeanPolicyParameterACR.java @@ -9,7 +9,7 @@ public class EchoDynaBeanPolicyParameterACR extends BaseACRhttp://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 */ @@ -43,7 +43,7 @@ * encrypted properties file. A better approach would be to allow unencrypted * properties in the file and to encrypt them the first time the file is * accessed. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @author kevin.w.wall@gmail.com @@ -89,7 +89,7 @@ public synchronized String getProperty(String key) throws EncryptionException { CipherText restoredCipherText = CipherText.fromPortableSerializedBytes(serializedCiphertext); progressMark++; PlainText plaintext = ESAPI.encryptor().decrypt(restoredCipherText); - + return plaintext.toString(); } catch (Exception e) { throw new EncryptionException("Property retrieval failure", @@ -158,13 +158,13 @@ public void store(OutputStream out, String comments) throws IOException { } /** - * Loads encrypted properties file based on the location passed in args then prompts the - * user to input key-value pairs. When the user enters a null or blank key, the values + * Loads encrypted properties file based on the location passed in args then prompts the + * user to input key-value pairs. When the user enters a null or blank key, the values * are stored to the properties file. - * + * * @param args * the location of the properties file to load and write to - * + * * @throws Exception * Any exception thrown * @deprecated Use {@code EncryptedPropertiesUtils} instead, which allows creating, reading, @@ -185,7 +185,7 @@ public static void main(String[] args) throws Exception { in = new FileInputStream(f); out = new FileOutputStream(f); - ep.load(in); + ep.load(in); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String key = null; do { @@ -204,7 +204,7 @@ public static void main(String[] args) throws Exception { try { if ( in != null ) in.close(); } catch( Exception e ) {} try { if ( out != null ) out.close(); } catch( Exception e ) {} } - + Iterator i = ep.keySet().iterator(); while (i.hasNext()) { String k = (String) i.next(); diff --git a/src/main/java/org/owasp/esapi/reference/crypto/EncryptedPropertiesUtils.java b/src/main/java/org/owasp/esapi/reference/crypto/EncryptedPropertiesUtils.java index 6aa93aa50..dee385ff1 100644 --- a/src/main/java/org/owasp/esapi/reference/crypto/EncryptedPropertiesUtils.java +++ b/src/main/java/org/owasp/esapi/reference/crypto/EncryptedPropertiesUtils.java @@ -17,7 +17,7 @@ *

      * Usage:
      * - * java org.owasp.esapi.reference.crypto.EncryptedPropertiesUtils [--in file] [--out file] + * java org.owasp.esapi.reference.crypto.EncryptedPropertiesUtils [--in file] [--out file] * [--in-encrypted true|false] [--verbose true|false] * *

      @@ -208,5 +208,5 @@ public static Object addProperty(Properties props, String key, String value) { } return null; } - + } diff --git a/src/main/java/org/owasp/esapi/reference/crypto/ReferenceEncryptedProperties.java b/src/main/java/org/owasp/esapi/reference/crypto/ReferenceEncryptedProperties.java index d5a375449..1137a5fbc 100644 --- a/src/main/java/org/owasp/esapi/reference/crypto/ReferenceEncryptedProperties.java +++ b/src/main/java/org/owasp/esapi/reference/crypto/ReferenceEncryptedProperties.java @@ -184,7 +184,7 @@ public void load(InputStream in) throws IOException { * * For JDK 1.5 compatibility, this method has been overridden convert the Reader * into an InputStream and call the superclass constructor. - * + * * @throws IOException Thrown if {@code Reader} input stream invalid or does not * correspond to Java properties file format. */ @@ -256,7 +256,7 @@ public Enumeration elements() { /** * This method has been overridden to only accept Strings for key and value, and to encrypt * those Strings before storing them. Outside classes should always use {@code setProperty} - * to add values to the Properties map. If an outside class does erroneously call this method + * to add values to the Properties map. If an outside class does erroneously call this method * with non-String parameters an {@code IllegalArgumentException} will be thrown. * * @param key A String key to add diff --git a/src/main/java/org/owasp/esapi/reference/validation/BaseValidationRule.java b/src/main/java/org/owasp/esapi/reference/validation/BaseValidationRule.java index 275ca2725..b9251198c 100644 --- a/src/main/java/org/owasp/esapi/reference/validation/BaseValidationRule.java +++ b/src/main/java/org/owasp/esapi/reference/validation/BaseValidationRule.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -29,7 +29,7 @@ /** * A ValidationRule 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 @@ -40,23 +40,23 @@ public abstract class BaseValidationRule implements ValidationRule { private String typeName = null; protected boolean allowNull = false; protected Encoder encoder = null; - + private BaseValidationRule() { // prevent use of no-arg constructor } - + public BaseValidationRule( String typeName ) { this(); setEncoder( ESAPI.encoder() ); setTypeName( typeName ); } - + public BaseValidationRule( String typeName, Encoder encoder ) { this(); setEncoder( encoder ); setTypeName( typeName ); } - + /** * {@inheritDoc} */ @@ -70,21 +70,21 @@ public void setAllowNull( boolean flag ) { public String getTypeName() { return typeName; } - + /** * {@inheritDoc} */ public final void setTypeName( String typeName ) { this.typeName = typeName; } - + /** * {@inheritDoc} */ public final void setEncoder( Encoder encoder ) { this.encoder = encoder; } - + /** * {@inheritDoc} */ @@ -100,7 +100,7 @@ public Object getValid( String context, String input, ValidationErrorList errorL try { valid = getValid( context, input ); } catch (ValidationException e) { - if( errorList == null) { + if( errorList == null) { throw e; } else { errorList.addError(context, e); @@ -108,7 +108,7 @@ public Object getValid( String context, String input, ValidationErrorList errorL } return valid; } - + /** * {@inheritDoc} */ @@ -128,13 +128,13 @@ public Object getSafe( String context, String input ) { * input (in some cases you may not care). In most cases this should be the * same as the getSafe method only instead of throwing an exception, return * some default value. - * + * * @param context * @param input * @return a parsed version of the input or a default value. */ protected abstract Object sanitize( String context, String input ); - + /** * {@inheritDoc} */ @@ -146,7 +146,7 @@ public boolean isValid( String context, String input ) { } catch( Exception e ) { valid = false; } - + return valid; } @@ -156,13 +156,13 @@ public boolean isValid( String context, String input ) { public String whitelist( String input, char[] whitelist) { return whitelist(input, charArrayToSet(whitelist)); } - + /** - * Removes characters that aren't in the whitelist from the input String. + * Removes characters that aren't in the whitelist from the input String. * O(input.length) whitelist performance * @param input String to be sanitized * @param whitelist allowed characters - * @return input stripped of all chars that aren't in the whitelist + * @return input stripped of all chars that aren't in the whitelist */ public String whitelist( String input, Set whitelist) { StringBuilder stripped = new StringBuilder(); @@ -174,7 +174,7 @@ public String whitelist( String input, Set whitelist) { } return stripped.toString(); } - + // CHECKME should be moved to some utility class (Would potentially be used by new EncoderConstants class) // Is there a standard way to convert an array of primitives to a Collection /** @@ -191,7 +191,7 @@ public static Set charArrayToSet(char[] array) { } return toReturn; } - + public boolean isAllowNull() { return allowNull; } diff --git a/src/main/java/org/owasp/esapi/reference/validation/CreditCardValidationRule.java b/src/main/java/org/owasp/esapi/reference/validation/CreditCardValidationRule.java index dea2a6370..1e82c0e9a 100644 --- a/src/main/java/org/owasp/esapi/reference/validation/CreditCardValidationRule.java +++ b/src/main/java/org/owasp/esapi/reference/validation/CreditCardValidationRule.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -26,7 +26,7 @@ /** * A validator performs syntax and possibly semantic validation of Credit Card * String from an untrusted source. - * + * * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security * @since June 1, 2007 @@ -34,14 +34,14 @@ */ public class CreditCardValidationRule extends BaseValidationRule { private int maxCardLength = 19; - + /** * Key used to pull out encoder in configuration. Prefixed with "Validator." */ protected static final String CREDIT_CARD_VALIDATOR_KEY = "CreditCard"; - - private StringValidationRule ccrule = null; - + + private StringValidationRule ccrule = null; + /** * Creates a CreditCardValidator using the rule found in security configuration * @param typeName a description of the type of card being validated @@ -51,7 +51,7 @@ public CreditCardValidationRule( String typeName, Encoder encoder ) { super( typeName, encoder ); ccrule = readDefaultCreditCardRule(); } - + public CreditCardValidationRule( String typeName, Encoder encoder, StringValidationRule validationRule ) { super( typeName, encoder ); ccrule = validationRule; @@ -64,7 +64,7 @@ private StringValidationRule readDefaultCreditCardRule() { ccr.setAllowNull( false ); return ccr; } - + /** * {@inheritDoc} */ @@ -76,14 +76,14 @@ public String getValid( String context, String input ) throws ValidationExceptio } throw new ValidationException( context + ": Input credit card required", "Input credit card required: context=" + context + ", input=" + input, context ); } - + String canonical = ccrule.getValid( context, input ); if( ! validCreditCardFormat(canonical)) { throw new ValidationException( context + ": Invalid credit card input", "Invalid credit card input: context=" + context, context ); } - - return canonical; + + return canonical; } /** @@ -93,7 +93,7 @@ public String getValid( String context, String input ) throws ValidationExceptio * @return true if the ccNum passes the Luhn Algorithm */ protected boolean validCreditCardFormat(String ccNum) { - + StringBuilder digitsOnly = new StringBuilder(); char c; for (int i = 0; i < ccNum.length(); i++) { @@ -102,12 +102,12 @@ protected boolean validCreditCardFormat(String ccNum) { digitsOnly.append(c); } } - + int sum = 0; int digit = 0; int addend = 0; boolean timesTwo = false; - + for (int i = digitsOnly.length() - 1; i >= 0; i--) { // guaranteed to be an int digit = Integer.valueOf(digitsOnly.substring(i, i + 1)); @@ -123,10 +123,10 @@ protected boolean validCreditCardFormat(String ccNum) { timesTwo = !timesTwo; } - return sum % 10 == 0; - + return sum % 10 == 0; + } - + /** * {@inheritDoc} */ diff --git a/src/main/java/org/owasp/esapi/reference/validation/DateValidationRule.java b/src/main/java/org/owasp/esapi/reference/validation/DateValidationRule.java index b890b92be..340800409 100644 --- a/src/main/java/org/owasp/esapi/reference/validation/DateValidationRule.java +++ b/src/main/java/org/owasp/esapi/reference/validation/DateValidationRule.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -27,7 +27,7 @@ /** * 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 @@ -35,18 +35,18 @@ */ public class DateValidationRule extends BaseValidationRule { private DateFormat format = DateFormat.getDateInstance(); - + public DateValidationRule( String typeName, Encoder encoder, DateFormat newFormat ) { - super( typeName, encoder ); + super( typeName, encoder ); setDateFormat( newFormat ); } - + public final void setDateFormat( DateFormat newFormat ) { if (newFormat == null) { throw new IllegalArgumentException("DateValidationRule.setDateFormat requires a non-null DateFormat"); } // CHECKME fail fast? -/* +/* try { newFormat.parse(new Date()); } catch (ParseException e) { @@ -71,10 +71,10 @@ public Date getValid( String context, String input ) throws ValidationException public Date sanitize( String context, String input ) { return sanitize(context, input, null); } - + /** * Same as sanitize(String, String) except it returns any ValidationException generated in the provided errorList. - * + * * @param errorList The error list to add any ValidationException to. * @return The valid sanitized Date, or Date(0) if the supplied input was not a valid date. */ @@ -89,7 +89,7 @@ public Date sanitize( String context, String input, ValidationErrorList errorLis } return date; } - + private Date safelyParse(String context, String input, boolean sanitize) throws ValidationException { // CHECKME should this allow empty Strings? " " use IsBlank instead? diff --git a/src/main/java/org/owasp/esapi/reference/validation/HTMLValidationRule.java b/src/main/java/org/owasp/esapi/reference/validation/HTMLValidationRule.java index e813a0222..87de340d5 100644 --- a/src/main/java/org/owasp/esapi/reference/validation/HTMLValidationRule.java +++ b/src/main/java/org/owasp/esapi/reference/validation/HTMLValidationRule.java @@ -59,49 +59,49 @@ public class HTMLValidationRule extends StringValidationRule { /*package */ static InputStream getResourceStreamFromClassLoader(String contextDescription, ClassLoader classLoader, String fileName, List searchPaths) { InputStream result = null; - + for (String searchPath: searchPaths) { result = classLoader.getResourceAsStream(searchPath + fileName); - + if (result != null) { - LOGGER.info(Logger.EVENT_SUCCESS, "SUCCESSFULLY LOADED " + fileName + " via the CLASSPATH from '" + + LOGGER.info(Logger.EVENT_SUCCESS, "SUCCESSFULLY LOADED " + fileName + " via the CLASSPATH from '" + searchPath + "' using " + contextDescription + "!"); - break; + break; } } - + return result; } - + /*package */ static InputStream getResourceStreamFromClasspath(String fileName) { LOGGER.info(Logger.EVENT_FAILURE, "Loading " + fileName + " from classpaths"); - + InputStream resourceStream = null; - - List orderedSearchPaths = Arrays.asList(DefaultSearchPath.ROOT.value(), + + List orderedSearchPaths = Arrays.asList(DefaultSearchPath.ROOT.value(), DefaultSearchPath.RESOURCE_DIRECTORY.value(), DefaultSearchPath.DOT_ESAPI.value(), DefaultSearchPath.ESAPI.value(), DefaultSearchPath.RESOURCES.value(), DefaultSearchPath.SRC_MAIN_RESOURCES.value()); - + resourceStream = getResourceStreamFromClassLoader("current thread context class loader", Thread.currentThread().getContextClassLoader(), fileName, orderedSearchPaths); - + //I'm lazy. Using ternary for shorthand "if null then do next thing" Harder to read, sorry resourceStream = resourceStream != null ? resourceStream : getResourceStreamFromClassLoader("system class loader", ClassLoader.getSystemClassLoader(), fileName, orderedSearchPaths); resourceStream = resourceStream != null ? resourceStream : getResourceStreamFromClassLoader("class loader for DefaultSecurityConfiguration class", ESAPI.securityConfiguration().getClass().getClassLoader(), fileName, orderedSearchPaths); - + return resourceStream; } - + /*package */ static Policy loadAntisamyPolicy(String antisamyPolicyFilename) throws IOException, PolicyException { InputStream resourceStream = null; SecurityConfiguration secCfg = ESAPI.securityConfiguration(); - + //Rather than catching the IOException from the resource stream, let's ask if the file exists to give this a best-case resolution. //This helps with the IOException handling too. If the file is there and we get an IOException from the SecurityConfiguration, then the file is there and something else is wrong (FAIL -- don't try the other path) File file = secCfg.getResourceFile(antisamyPolicyFilename); - + resourceStream = file == null ? getResourceStreamFromClasspath(antisamyPolicyFilename) : secCfg.getResourceStream(antisamyPolicyFilename); return resourceStream == null ? null : Policy.getInstance(resourceStream); } @@ -111,14 +111,14 @@ public class HTMLValidationRule extends StringValidationRule { try { antisamyPolicyFilename = ESAPI.securityConfiguration().getStringProp( VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE ); } catch (ConfigurationException cex) { - - LOGGER.info(Logger.EVENT_FAILURE, "ESAPI property " + + + LOGGER.info(Logger.EVENT_FAILURE, "ESAPI property " + VALIDATOR_HTML_VALIDATION_CONFIGURATION_FILE + " not set, using default value: " + ANTISAMYPOLICY_FILENAME); } return antisamyPolicyFilename; } - + /*package */ static void configureInstance() { String antisamyPolicyFilename = resolveAntisamyFilename(); @@ -131,14 +131,14 @@ public class HTMLValidationRule extends StringValidationRule { //Thrown if the resource stream was created, but the contents of the file are not compatible with antisamy expectations. throw new ConfigurationException("Couldn't parse " + antisamyPolicyFilename, e); } - + if (antiSamyPolicy == null) { throw new ConfigurationException("Couldn't find " + antisamyPolicyFilename); } } - - static { + + static { configureInstance(); } @@ -207,7 +207,7 @@ private boolean legacyHtmlValidation() { legacy = true; // Give the caller that legacy behavior of sanitizing. break; default: - LOGGER.warning(Logger.EVENT_FAILURE, "ESAPI property " + + LOGGER.warning(Logger.EVENT_FAILURE, "ESAPI property " + VALIDATOR_HTML_VALIDATION_ACTION + " was set to \"" + propValue + "\". Must be set to either \"clean\"" + " (the default for legacy support) or \"throw\"; assuming \"clean\" for legacy behavior."); @@ -217,7 +217,7 @@ private boolean legacyHtmlValidation() { } catch( ConfigurationException cex ) { // OPEN ISSUE: Should we log this? I think so. Convince me otherwise. But maybe // we should only log it once or every Nth time?? - LOGGER.warning(Logger.EVENT_FAILURE, "ESAPI property " + + LOGGER.warning(Logger.EVENT_FAILURE, "ESAPI property " + VALIDATOR_HTML_VALIDATION_ACTION + " must be set to either \"clean\" (the default for legacy support) or \"throw\"; assuming \"clean\"", cex); diff --git a/src/main/java/org/owasp/esapi/reference/validation/IntegerValidationRule.java b/src/main/java/org/owasp/esapi/reference/validation/IntegerValidationRule.java index 6f99197fd..3137781e3 100644 --- a/src/main/java/org/owasp/esapi/reference/validation/IntegerValidationRule.java +++ b/src/main/java/org/owasp/esapi/reference/validation/IntegerValidationRule.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -23,17 +23,17 @@ /** * 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 */ public class IntegerValidationRule extends BaseValidationRule { - + private int minValue = Integer.MIN_VALUE; private int maxValue = Integer.MAX_VALUE; - + public IntegerValidationRule( String typeName, Encoder encoder ) { super( typeName, encoder ); } @@ -49,24 +49,24 @@ public Integer getValid( String context, String input ) throws ValidationExcepti } private Integer safelyParse(String context, String input) throws ValidationException { - // do not allow empty Strings such as " " - so trim to ensure + // do not allow empty Strings such as " " - so trim to ensure // isEmpty catches " " if (input != null) input = input.trim(); - + if ( StringUtilities.isEmpty(input) ) { if (allowNull) { return null; } throw new ValidationException( context + ": Input number required", "Input number required: context=" + context + ", input=" + input, context ); } - + // canonicalize String canonical = encoder.canonicalize( input ); if (minValue > maxValue) { throw new ValidationException( context + ": Invalid number input: context", "Validation parameter error for number: maxValue ( " + maxValue + ") must be greater than minValue ( " + minValue + ") for " + context, context ); } - + // validate min and max try { int i = Integer.valueOf(canonical); @@ -75,7 +75,7 @@ private Integer safelyParse(String context, String input) throws ValidationExcep } if (i > maxValue) { throw new ValidationException( "Invalid number input must be between " + minValue + " and " + maxValue + ": context=" + context, "Invalid number input must be between " + minValue + " and " + maxValue + ": context=" + context + ", input=" + input, context ); - } + } return i; } catch (NumberFormatException e) { throw new ValidationException( context + ": Invalid number input", "Invalid number input format: context=" + context + ", input=" + input, e, context); diff --git a/src/main/java/org/owasp/esapi/reference/validation/NumberValidationRule.java b/src/main/java/org/owasp/esapi/reference/validation/NumberValidationRule.java index 0d83a5746..c19f2ab98 100644 --- a/src/main/java/org/owasp/esapi/reference/validation/NumberValidationRule.java +++ b/src/main/java/org/owasp/esapi/reference/validation/NumberValidationRule.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -25,17 +25,17 @@ /** * 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 */ public class NumberValidationRule extends BaseValidationRule { - + private double minValue = Double.NEGATIVE_INFINITY; private double maxValue = Double.POSITIVE_INFINITY; - + public NumberValidationRule( String typeName, Encoder encoder ) { super( typeName, encoder ); } @@ -52,7 +52,7 @@ public NumberValidationRule( String typeName, Encoder encoder, double minValue, public Double getValid( String context, String input ) throws ValidationException { return safelyParse(context, input); } - + /** * {@inheritDoc} */ @@ -73,17 +73,17 @@ public Double sanitize( String context, String input ) { private static BigDecimal smallBad; static { - + BigDecimal one = new BigDecimal(1); BigDecimal two = new BigDecimal(2); - + BigDecimal tiny = one.divide(two.pow(1022)); - + // 2^(-1022) ­ 2^(-1076) bigBad = tiny.subtract(one.divide(two.pow(1076))); //2^(-1022) ­ 2^(-1075) smallBad = tiny.subtract(one.divide(two.pow(1075))); - } + } private Double safelyParse(String context, String input) throws ValidationException { @@ -94,7 +94,7 @@ private Double safelyParse(String context, String input) throws ValidationExcept } throw new ValidationException( context + ": Input number required", "Input number required: context=" + context + ", input=" + input, context ); } - + // canonicalize String canonical = encoder.canonicalize( input ); @@ -102,8 +102,8 @@ private Double safelyParse(String context, String input) throws ValidationExcept if (minValue > maxValue) { throw new ValidationException( context + ": Invalid number input: context", "Validation parameter error for number: maxValue ( " + maxValue + ") must be greater than minValue ( " + minValue + ") for " + context, context ); } - - //convert to BigDecimal so we can safely parse dangerous numbers to + + //convert to BigDecimal so we can safely parse dangerous numbers to //check if the number may DOS the double parser BigDecimal bd; try { @@ -111,15 +111,15 @@ private Double safelyParse(String context, String input) throws ValidationExcept } catch (NumberFormatException e) { throw new ValidationException( context + ": Invalid number input", "Invalid number input format: context=" + context + ", input=" + input, e, context); } - + // Thanks to Brian Chess for this suggestion // Check if string input is in the "dangerous" double parsing range if (bd.compareTo(smallBad) >= 0 && bd.compareTo(bigBad) <= 0) { // if you get here you know you're looking at a bad value. The final - // value for any double in this range is supposed to be the following safe # + // value for any double in this range is supposed to be the following safe # return new Double("2.2250738585072014E-308"); } - + // the number is safe to parseDouble Double d; // validate min and max @@ -128,7 +128,7 @@ private Double safelyParse(String context, String input) throws ValidationExcept } catch (NumberFormatException e) { throw new ValidationException( context + ": Invalid number input", "Invalid number input format: context=" + context + ", input=" + input, e, context); } - + if (d.isInfinite()) { throw new ValidationException( "Invalid number input: context=" + context, "Invalid double input is infinite: context=" + context + ", input=" + input, context ); } @@ -140,7 +140,7 @@ private Double safelyParse(String context, String input) throws ValidationExcept } if (d.doubleValue() > maxValue) { throw new ValidationException( "Invalid number input must be between " + minValue + " and " + maxValue + ": context=" + context, "Invalid number input must be between " + minValue + " and " + maxValue + ": context=" + context + ", input=" + input, context ); - } + } return d; } } diff --git a/src/main/java/org/owasp/esapi/reference/validation/StringValidationRule.java b/src/main/java/org/owasp/esapi/reference/validation/StringValidationRule.java index 16c607cfa..740db8c7d 100644 --- a/src/main/java/org/owasp/esapi/reference/validation/StringValidationRule.java +++ b/src/main/java/org/owasp/esapi/reference/validation/StringValidationRule.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -32,12 +32,12 @@ /** * 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 { @@ -284,7 +284,7 @@ public String getValid( String context, String input ) throws ValidationExceptio // check blacklist patterns checkBlacklist(context, data, input); - + // validation passed return data; } diff --git a/src/main/java/org/owasp/esapi/reference/validation/package.html b/src/main/java/org/owasp/esapi/reference/validation/package.html index b950c12a7..271bb16ea 100644 --- a/src/main/java/org/owasp/esapi/reference/validation/package.html +++ b/src/main/java/org/owasp/esapi/reference/validation/package.html @@ -6,6 +6,6 @@ This package contains data format-specific validation rule functions. - + diff --git a/src/main/java/org/owasp/esapi/util/ByteConversionUtil.java b/src/main/java/org/owasp/esapi/util/ByteConversionUtil.java index 506af4f07..abb82c018 100644 --- a/src/main/java/org/owasp/esapi/util/ByteConversionUtil.java +++ b/src/main/java/org/owasp/esapi/util/ByteConversionUtil.java @@ -1,6 +1,6 @@ /* * 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. diff --git a/src/main/java/org/owasp/esapi/util/CollectionsUtil.java b/src/main/java/org/owasp/esapi/util/CollectionsUtil.java index 73f919766..2607f6255 100644 --- a/src/main/java/org/owasp/esapi/util/CollectionsUtil.java +++ b/src/main/java/org/owasp/esapi/util/CollectionsUtil.java @@ -1,5 +1,5 @@ /** - * + * */ package org.owasp.esapi.util; @@ -9,20 +9,20 @@ /** * @author Neil Matatall (neil.matatall .at. gmail.com) - * + * * Are these necessary? Are there any libraries or java.lang classes to take * care of the conversions? - * + * * FIXME: we can convert to using this, but it requires that the array be of Character, not char * new HashSet(Arrays.asList(array)) - * + * */ public class CollectionsUtil { private static final char[] EMPTY_CHAR_ARRAY = new char[0]; /** - * Converts an array of chars to a Set of Characters. + * Converts an array of chars to a Set of Characters. * @param array the contents of the new Set * @return a Set containing the elements in the array */ diff --git a/src/main/java/org/owasp/esapi/util/DefaultMessageUtil.java b/src/main/java/org/owasp/esapi/util/DefaultMessageUtil.java index 6d1a45217..ee9de4286 100644 --- a/src/main/java/org/owasp/esapi/util/DefaultMessageUtil.java +++ b/src/main/java/org/owasp/esapi/util/DefaultMessageUtil.java @@ -1,15 +1,15 @@ /** * 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 Pawan Singh (pawan.singh@owasp.org) OWASP * @created 2009 */ @@ -29,9 +29,9 @@ public class DefaultMessageUtil { private final String DEFAULT_LOCALE_LANG = "en"; private final String DEFAULT_LOCALE_LOC = "US"; - + private ResourceBundle messages = null; - + public void initialize() { try { messages = ResourceBundle.getBundle("ESAPI", ESAPI.authenticator().getCurrentUser().getLocale()); @@ -42,7 +42,7 @@ public void initialize() { public String getMessage(String msgKey, Object[] arguments) { - + initialize(); return MessageFormat.format( messages.getString(msgKey), arguments ); } diff --git a/src/main/java/org/owasp/esapi/util/ObjFactory.java b/src/main/java/org/owasp/esapi/util/ObjFactory.java index beca4391e..0e3340894 100644 --- a/src/main/java/org/owasp/esapi/util/ObjFactory.java +++ b/src/main/java/org/owasp/esapi/util/ObjFactory.java @@ -1,6 +1,6 @@ /* * 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. @@ -53,7 +53,7 @@ public class ObjFactory { /** * Create an object based on the className parameter. - * + * * @param className The name of the class to construct. Should be a fully qualified name and * generally the same as type T * @param typeName A type name used in error messages / exceptions. diff --git a/src/main/java/org/owasp/esapi/waf/ConfigurationException.java b/src/main/java/org/owasp/esapi/waf/ConfigurationException.java index 9dd0ef639..8368e222a 100644 --- a/src/main/java/org/owasp/esapi/waf/ConfigurationException.java +++ b/src/main/java/org/owasp/esapi/waf/ConfigurationException.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -21,7 +21,7 @@ /** * The Exception to be thrown when there is an error parsing a policy file. - * + * * @author Arshan Dabirsiaghi * @see org.owasp.esapi.waf.configuration.ConfigurationParser * diff --git a/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java b/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java index 7f47ae43e..bd5e7f9a3 100644 --- a/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java +++ b/src/main/java/org/owasp/esapi/waf/ESAPIWebApplicationFirewallFilter.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -48,11 +48,11 @@ * standard J2EE servlet filter that, in different methods, invokes the reading * of the configuration file and handles the runtime processing and enforcing of * the developer-specified rules. - * + * * Ideally the filter should be configured to catch all requests (/*) in * web.xml. If there are URL segments that need to be extremely fast and don't * require any protection, the pattern may be modified with extreme caution. - * + * * @author Arshan Dabirsiaghi * */ @@ -82,7 +82,7 @@ public class ESAPIWebApplicationFirewallFilter implements Filter { /** * This function is used in testing to dynamically alter the configuration. - * + * * @param policyFilePath * The path to the policy file * @param webRootDir @@ -120,11 +120,11 @@ public AppGuardianConfiguration getConfiguration() { } /** - * + * * This function is invoked at application startup and when the * configuration file polling period has elapsed and a change in the * configuration file has been detected. - * + * * It's main purpose is to read the configuration file and establish the * configuration object model for use at runtime during the * doFilter() method. diff --git a/src/main/java/org/owasp/esapi/waf/actions/Action.java b/src/main/java/org/owasp/esapi/waf/actions/Action.java index fe8cb3e57..46db8e350 100644 --- a/src/main/java/org/owasp/esapi/waf/actions/Action.java +++ b/src/main/java/org/owasp/esapi/waf/actions/Action.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -17,7 +17,7 @@ /** * The base class indicating what is to be done after a rule executes. - * + * * @author Arshan Dabirsiaghi * @see org.owasp.esapi.waf.rules.Rule */ diff --git a/src/main/java/org/owasp/esapi/waf/actions/BlockAction.java b/src/main/java/org/owasp/esapi/waf/actions/BlockAction.java index c216985f2..a9cf60fc8 100644 --- a/src/main/java/org/owasp/esapi/waf/actions/BlockAction.java +++ b/src/main/java/org/owasp/esapi/waf/actions/BlockAction.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -18,7 +18,7 @@ /** * The class that indicates the request processing should be halted and that a blank response * should be returned. - * + * * @author Arshan Dabirsiaghi */ public class BlockAction extends Action { diff --git a/src/main/java/org/owasp/esapi/waf/actions/DefaultAction.java b/src/main/java/org/owasp/esapi/waf/actions/DefaultAction.java index 732f3d87e..7aad503fa 100644 --- a/src/main/java/org/owasp/esapi/waf/actions/DefaultAction.java +++ b/src/main/java/org/owasp/esapi/waf/actions/DefaultAction.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -18,7 +18,7 @@ /** * The class that indicates the default action as indicated by the policy file * should be executed. - * + * * @author Arshan Dabirsiaghi */ public class DefaultAction extends Action { diff --git a/src/main/java/org/owasp/esapi/waf/actions/DoNothingAction.java b/src/main/java/org/owasp/esapi/waf/actions/DoNothingAction.java index cd2f58a8a..70d5970f2 100644 --- a/src/main/java/org/owasp/esapi/waf/actions/DoNothingAction.java +++ b/src/main/java/org/owasp/esapi/waf/actions/DoNothingAction.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -17,7 +17,7 @@ /** * The class that indicates that no further action is necessary. - * + * * @author Arshan Dabirsiaghi */ public class DoNothingAction extends Action { diff --git a/src/main/java/org/owasp/esapi/waf/actions/RedirectAction.java b/src/main/java/org/owasp/esapi/waf/actions/RedirectAction.java index f80af4de8..b16fa4e64 100644 --- a/src/main/java/org/owasp/esapi/waf/actions/RedirectAction.java +++ b/src/main/java/org/owasp/esapi/waf/actions/RedirectAction.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -17,7 +17,7 @@ /** * The class that indicates the user should be redirected to another location. - * + * * @author Arshan Dabirsiaghi */ public class RedirectAction extends Action { diff --git a/src/main/java/org/owasp/esapi/waf/actions/package.html b/src/main/java/org/owasp/esapi/waf/actions/package.html index 89657d08c..4fee1e14a 100644 --- a/src/main/java/org/owasp/esapi/waf/actions/package.html +++ b/src/main/java/org/owasp/esapi/waf/actions/package.html @@ -5,7 +5,7 @@ -This package contains the Action objects that are executed after a Rule subclass executes. - +This package contains the Action objects that are executed after a Rule subclass executes. + diff --git a/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java b/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java index aeeebb1e8..25eb24847 100644 --- a/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java +++ b/src/main/java/org/owasp/esapi/waf/configuration/AppGuardianConfiguration.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -23,7 +23,7 @@ /** * This class is the object model of the policy file. Also holds a number of constants * used throughout the WAF. - * + * * @author Arshan Dabirsiaghi * */ @@ -72,7 +72,7 @@ public class AppGuardianConfiguration { private boolean forceSecureFlagToSession = false; private String sessionCookieName; - + public String getSessionCookieName() { return sessionCookieName; } @@ -152,7 +152,7 @@ public void setApplyHTTPOnlyFlagToSessionCookie(boolean shouldApply) { public void setApplySecureFlagToSessionCookie(boolean shouldApply) { forceSecureFlagToSession = shouldApply; } - + public boolean isUsingHttpOnlyFlagOnSessionCookie() { return forceHttpOnlyFlagToSession; } @@ -160,7 +160,7 @@ public boolean isUsingHttpOnlyFlagOnSessionCookie() { public boolean isUsingSecureFlagOnSessionCookie() { return forceSecureFlagToSession; } - + public String toString() { StringBuilder sb = new StringBuilder( "WAF Configuration\n" ); sb.append( "Before body rules:\n" ); diff --git a/src/main/java/org/owasp/esapi/waf/configuration/ConfigurationParser.java b/src/main/java/org/owasp/esapi/waf/configuration/ConfigurationParser.java index 0370d2ec2..b5474c460 100644 --- a/src/main/java/org/owasp/esapi/waf/configuration/ConfigurationParser.java +++ b/src/main/java/org/owasp/esapi/waf/configuration/ConfigurationParser.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -51,9 +51,9 @@ import bsh.EvalError; /** - * - * The class used to turn a policy file's contents into an object model. - * + * + * The class used to turn a policy file's contents into an object model. + * * @author Arshan Dabirsiaghi * @see org.owasp.esapi.waf.configuration.AppGuardianConfiguration */ @@ -63,7 +63,7 @@ public class ConfigurationParser { private static final String DEFAULT_PATH_APPLY_ALL = ".*"; private static final int DEFAULT_RESPONSE_CODE = 403; private static final String DEFAULT_SESSION_COOKIE; - + static { String sessionIdName = null; try { @@ -73,13 +73,13 @@ public class ConfigurationParser { } DEFAULT_SESSION_COOKIE = sessionIdName; } - + private static final String[] STAGES = { "before-request-body", "after-request-body", "before-response" }; - + public static AppGuardianConfiguration readConfigurationFile(InputStream stream, String webRootDir) throws ConfigurationException { AppGuardianConfiguration config = new AppGuardianConfiguration(); @@ -102,16 +102,16 @@ public static AppGuardianConfiguration readConfigurationFile(InputStream stream, Element virtualPatchesRoot = root.getFirstChildElement("virtual-patches"); Element outboundRoot = root.getFirstChildElement("outbound-rules"); Element beanShellRoot = root.getFirstChildElement("bean-shell-rules"); - - + + /** * Parse the 'settings' section. */ if ( settingsRoot == null ) { throw new ConfigurationException("", "The section is required"); } else if ( settingsRoot != null ) { - - + + try { String sessionCookieName = settingsRoot.getFirstChildElement("session-cookie-name").getValue(); if ( ! "".equals(sessionCookieName) ) { @@ -122,7 +122,7 @@ public static AppGuardianConfiguration readConfigurationFile(InputStream stream, } String mode = settingsRoot.getFirstChildElement("mode").getValue(); - + if ( "block".equals(mode.toLowerCase() ) ) { AppGuardianConfiguration.DEFAULT_FAIL_ACTION = AppGuardianConfiguration.BLOCK; } else if ( "redirect".equals(mode.toLowerCase() ) ){ @@ -130,18 +130,18 @@ public static AppGuardianConfiguration readConfigurationFile(InputStream stream, } else { AppGuardianConfiguration.DEFAULT_FAIL_ACTION = AppGuardianConfiguration.LOG; } - + Element errorHandlingRoot = settingsRoot.getFirstChildElement("error-handling"); - + config.setDefaultErrorPage( errorHandlingRoot.getFirstChildElement("default-redirect-page").getValue() ); - + try { config.setDefaultResponseCode( Integer.parseInt(errorHandlingRoot.getFirstChildElement("block-status").getValue()) ); } catch (Exception e) { config.setDefaultResponseCode( DEFAULT_RESPONSE_CODE ); } } - + /** * Parse the 'authentication-rules' section if they have one. */ @@ -338,7 +338,7 @@ public static AppGuardianConfiguration readConfigurationFile(InputStream stream, } if ( allow != null ) { - + config.addBeforeBodyRule( new RestrictUserAgentRule(id, Pattern.compile(allow), null) ); } else if ( deny != null ) { @@ -370,12 +370,12 @@ public static AppGuardianConfiguration readConfigurationFile(InputStream stream, /* if ( customRulesRoot != null ) { Elements rules = customRulesRoot.getChildElements("rule"); - + // Parse the complex rules. - + } */ - + if ( outboundRoot != null ) { /* @@ -473,12 +473,12 @@ public static AppGuardianConfiguration readConfigurationFile(InputStream stream, Element replacement = e.getFirstChildElement("replacement"); ReplaceContentRule rcr = new ReplaceContentRule( - id, - Pattern.compile(pattern,Pattern.DOTALL), + id, + Pattern.compile(pattern,Pattern.DOTALL), replacement.getValue(), contentType != null ? Pattern.compile(contentType) : null, urlPaths != null ? Pattern.compile(urlPaths) : null); - + config.addBeforeResponseRule(rcr); } @@ -504,49 +504,49 @@ public static AppGuardianConfiguration readConfigurationFile(InputStream stream, } DetectOutboundContentRule docr = new DetectOutboundContentRule( - id, + id, Pattern.compile(contentType), Pattern.compile(token,Pattern.DOTALL), path != null ? Pattern.compile(path) : null); - + config.addBeforeResponseRule(docr); } } - + /** * Parse the 'bean-shell-rules' section. */ - + if ( beanShellRoot != null ) { - + Elements beanShellRules = beanShellRoot.getChildElements("bean-shell-script"); - + for (int i=0;i -This package contains the both the configuration object model and the -utility class to create that object model from an existing policy file. - +This package contains the both the configuration object model and the +utility class to create that object model from an existing policy file. + diff --git a/src/main/java/org/owasp/esapi/waf/internal/InterceptingHTTPServletRequest.java b/src/main/java/org/owasp/esapi/waf/internal/InterceptingHTTPServletRequest.java index 97982db8b..8c4c2b09f 100644 --- a/src/main/java/org/owasp/esapi/waf/internal/InterceptingHTTPServletRequest.java +++ b/src/main/java/org/owasp/esapi/waf/internal/InterceptingHTTPServletRequest.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -38,9 +38,9 @@ /** * The wrapper for the HttpServletRequest object which will be passed to the application * being protected by the WAF. It contains logic for parsing multipart parameters out of - * the request and provided downstream application logic a way of accessing it like it + * the request and provided downstream application logic a way of accessing it like it * hasn't been touched. - * + * * @author Arshan Dabirsiaghi * */ @@ -49,27 +49,27 @@ public class InterceptingHTTPServletRequest extends HttpServletRequestWrapper { private Vector allParameters; private Vector allParameterNames; private static int CHUNKED_BUFFER_SIZE = 1024; - + private boolean isMultipart = false; private RandomAccessFile requestBody; private RAFInputStream is; - + public ServletInputStream getInputStream() throws IOException { - + if ( isMultipart ) { - return is; + return is; } else { return super.getInputStream(); } - + } - + public BufferedReader getReader() throws IOException { String enc = getCharacterEncoding(); if(enc == null) enc = "UTF-8"; return new BufferedReader(new InputStreamReader(getInputStream(), enc)); } - + public InterceptingHTTPServletRequest(HttpServletRequest request) throws FileUploadException, IOException { super(request); @@ -100,7 +100,7 @@ public InterceptingHTTPServletRequest(HttpServletRequest request) throws FileUpl if ( isMultipart ) { requestBody = new RandomAccessFile( File.createTempFile("oew","mpc"), "rw"); - + byte buffer[] = new byte[CHUNKED_BUFFER_SIZE]; long size = 0; @@ -110,12 +110,12 @@ public InterceptingHTTPServletRequest(HttpServletRequest request) throws FileUpl len = request.getInputStream().read(buffer, 0, CHUNKED_BUFFER_SIZE); if ( len != -1 ) { size += len; - requestBody.write(buffer,0,len); + requestBody.write(buffer,0,len); } } - + is = new RAFInputStream(requestBody); - + ServletFileUpload sfu = new ServletFileUpload(); FileItemIterator iter = sfu.getItemIterator(this); @@ -141,13 +141,13 @@ public InterceptingHTTPServletRequest(HttpServletRequest request) throws FileUpl * This is a multipart content that is not a * regular form field. Nothing to do here. */ - + } } - + requestBody.seek(0); - + } } @@ -160,20 +160,20 @@ public String getDictionaryParameter(String s) { return p.getValue(); } } - + return null; } public Enumeration getDictionaryParameterNames() { return allParameterNames.elements(); } - - + + private class RAFInputStream extends ServletInputStream { - + RandomAccessFile raf; boolean isDone = false; - + public RAFInputStream(RandomAccessFile raf) throws IOException { this.raf = raf; this.raf.seek(0); @@ -184,7 +184,7 @@ public int read() throws IOException { isDone = rval == -1; return rval; } - + public synchronized void reset() throws IOException { raf.seek(0); isDone=false; @@ -205,5 +205,5 @@ public void setReadListener(ReadListener readListener) { //NO-OP. Unused in this scope } } - + } diff --git a/src/main/java/org/owasp/esapi/waf/internal/InterceptingHTTPServletResponse.java b/src/main/java/org/owasp/esapi/waf/internal/InterceptingHTTPServletResponse.java index 72d80003c..37bf402ca 100644 --- a/src/main/java/org/owasp/esapi/waf/internal/InterceptingHTTPServletResponse.java +++ b/src/main/java/org/owasp/esapi/waf/internal/InterceptingHTTPServletResponse.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -34,7 +34,7 @@ * being protected by the WAF. It contains logic for the response building API in order * to allow the WAF rules regarding responses to work. Much of the work is delegated to * other classes, especially InterceptingServletOutputStream - * + * * @author Arshan Dabirsiaghi * */ @@ -52,9 +52,9 @@ public class InterceptingHTTPServletResponse extends HttpServletResponseWrapper public InterceptingHTTPServletResponse(HttpServletResponse response, boolean buffering, List cookieRules) throws IOException { super(response); - + this.contentType = response.getContentType(); - + this.isos = new InterceptingServletOutputStream(response.getOutputStream(), buffering); this.ipw = new InterceptingPrintWriter(new PrintWriter(isos)); @@ -122,7 +122,7 @@ public void commit() throws IOException { public void addCookie(Cookie cookie) { addCookie(cookie, cookie.getMaxAge()<=0); } - + public void addCookie(Cookie cookie, boolean isSession) { boolean addSecureFlag = cookie.getSecure(); diff --git a/src/main/java/org/owasp/esapi/waf/internal/InterceptingPrintWriter.java b/src/main/java/org/owasp/esapi/waf/internal/InterceptingPrintWriter.java index 4a7962669..57200e7a4 100644 --- a/src/main/java/org/owasp/esapi/waf/internal/InterceptingPrintWriter.java +++ b/src/main/java/org/owasp/esapi/waf/internal/InterceptingPrintWriter.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -22,9 +22,9 @@ /** * The PrintWriter needed to buffer outbound data generated by the application * being protected by the WAF. Currently no logic is needed here right now due - * to the WAF things have been architected in the main file, + * to the WAF things have been architected in the main file, * InterceptingHTTPServletResponse. - * + * * @author Arshan Dabirsiaghi * @see org.owasp.esapi.waf.internal.InterceptingHTTPServletResponse */ diff --git a/src/main/java/org/owasp/esapi/waf/internal/InterceptingServletOutputStream.java b/src/main/java/org/owasp/esapi/waf/internal/InterceptingServletOutputStream.java index 1f2ced68e..47fd19fe9 100644 --- a/src/main/java/org/owasp/esapi/waf/internal/InterceptingServletOutputStream.java +++ b/src/main/java/org/owasp/esapi/waf/internal/InterceptingServletOutputStream.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -31,7 +31,7 @@ * * If not, we just forward everything through, otherwise we write data to our * byte stream that we will eventually forward en totale to the user agent. - * + * * @author Arshan Dabirsiaghi */ @@ -42,25 +42,25 @@ public class InterceptingServletOutputStream extends ServletOutputStream { private boolean buffering; private boolean committed; private boolean closed; - + private RandomAccessFile out; - + public InterceptingServletOutputStream(ServletOutputStream os, boolean buffered) throws FileNotFoundException, IOException { super(); this.os = os; this.buffering = buffered; this.committed = false; this.closed = false; - + /* * Creating a RandomAccessFile to keep track of output generated. I made * the prefix and suffix small for less processing. The "oew" is intended * to stand for "OWASP ESAPI WAF" and the "hop" for HTTP output. */ File tempFile= File.createTempFile("oew", ".hop"); - this.out = new RandomAccessFile (tempFile, "rw" ); + this.out = new RandomAccessFile (tempFile, "rw" ); tempFile.deleteOnExit(); - + } public void reset() throws IOException { @@ -68,17 +68,17 @@ public void reset() throws IOException { } public byte[] getResponseBytes() throws IOException { - + byte[] buffer = new byte[(int) out.length()]; out.seek(0); out.read(buffer, 0, (int)out.length()); out.seek(out.length()); return buffer; - + } public void setResponseBytes(byte[] responseBytes) throws IOException { - + if ( ! buffering && out.length() > 0 ) { throw new IOException("Already committed response because not currently buffering"); } @@ -109,42 +109,42 @@ public void write(byte[] b, int off, int len) throws IOException { } public void flush() throws IOException { - + if (buffering) { - + synchronized(out) { out.seek(0); - + byte[] buff = new byte[FLUSH_BLOCK_SIZE]; - + for(int i=0;ihttp://www.owasp.org/index.php/ESAPI. * * Copyright (c) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -17,7 +17,7 @@ /** * A simple object to represent a name=value HTTP parameter. - * + * * @author Arshan Dabirsiaghi * */ diff --git a/src/main/java/org/owasp/esapi/waf/internal/package.html b/src/main/java/org/owasp/esapi/waf/internal/package.html index a94870056..92d808c9f 100644 --- a/src/main/java/org/owasp/esapi/waf/internal/package.html +++ b/src/main/java/org/owasp/esapi/waf/internal/package.html @@ -6,7 +6,7 @@ This package contains all HTTP-related classes used internally by the WAF for the implementation -of its rules. - +of its rules. + diff --git a/src/main/java/org/owasp/esapi/waf/package.html b/src/main/java/org/owasp/esapi/waf/package.html index 8f025e3ed..186c820f8 100644 --- a/src/main/java/org/owasp/esapi/waf/package.html +++ b/src/main/java/org/owasp/esapi/waf/package.html @@ -9,6 +9,6 @@ that can be used with or without ESAPI's other security controls in place. It's purpose is to provide fast virtual patching capabilities against known vulnerabilities or the enforcement of existing security policies where possible. - + diff --git a/src/main/java/org/owasp/esapi/waf/rules/AddHTTPOnlyFlagRule.java b/src/main/java/org/owasp/esapi/waf/rules/AddHTTPOnlyFlagRule.java index eaa68e8f6..21395cb5e 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/AddHTTPOnlyFlagRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/AddHTTPOnlyFlagRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -40,7 +40,7 @@ public AddHTTPOnlyFlagRule(String id, List name) { } public Action check(HttpServletRequest request, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { DoNothingAction action = new DoNothingAction(); diff --git a/src/main/java/org/owasp/esapi/waf/rules/AddHeaderRule.java b/src/main/java/org/owasp/esapi/waf/rules/AddHeaderRule.java index a52b4e79f..68bb05e7d 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/AddHeaderRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/AddHeaderRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -46,8 +46,8 @@ public AddHeaderRule(String id, String header, String value, Pattern path, List< } public Action check( - HttpServletRequest request, - InterceptingHTTPServletResponse response, + HttpServletRequest request, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { DoNothingAction action = new DoNothingAction(); @@ -68,7 +68,7 @@ public Action check( if ( ((Pattern)o).matcher(request.getRequestURI()).matches() ) { action.setFailed(false); action.setActionNecessary(false); - return action; + return action; } } diff --git a/src/main/java/org/owasp/esapi/waf/rules/AddSecureFlagRule.java b/src/main/java/org/owasp/esapi/waf/rules/AddSecureFlagRule.java index 6cbb1578e..515840196 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/AddSecureFlagRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/AddSecureFlagRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -40,9 +40,9 @@ public AddSecureFlagRule(String id, List name) { } public Action check(HttpServletRequest request, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { - + DoNothingAction action = new DoNothingAction(); return action; diff --git a/src/main/java/org/owasp/esapi/waf/rules/AuthenticatedRule.java b/src/main/java/org/owasp/esapi/waf/rules/AuthenticatedRule.java index 8d62959b6..d232b7e6d 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/AuthenticatedRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/AuthenticatedRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -47,7 +47,7 @@ public AuthenticatedRule(String id, String sessionAttribute, Pattern path, List< } public Action check(HttpServletRequest request, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { HttpSession session = request.getSession(); diff --git a/src/main/java/org/owasp/esapi/waf/rules/BeanShellRule.java b/src/main/java/org/owasp/esapi/waf/rules/BeanShellRule.java index 254c6a70e..7d0310796 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/BeanShellRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/BeanShellRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ diff --git a/src/main/java/org/owasp/esapi/waf/rules/DetectOutboundContentRule.java b/src/main/java/org/owasp/esapi/waf/rules/DetectOutboundContentRule.java index 2a9388ffc..92931fb80 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/DetectOutboundContentRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/DetectOutboundContentRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -38,7 +38,7 @@ public class DetectOutboundContentRule extends Rule { private Pattern contentType; private Pattern pattern; private Pattern uri; - + public DetectOutboundContentRule(String id, Pattern contentType, Pattern pattern, Pattern uri) { this.contentType = contentType; this.pattern = pattern; @@ -47,14 +47,14 @@ public DetectOutboundContentRule(String id, Pattern contentType, Pattern pattern } public Action check(HttpServletRequest request, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { /* * Early fail: if URI doesn't match. */ if ( uri != null && ! uri.matcher(request.getRequestURI()).matches() ) { - return new DoNothingAction(); + return new DoNothingAction(); } /* @@ -63,14 +63,14 @@ public Action check(HttpServletRequest request, String inboundContentType; String charEnc; - + if ( response != null ) { if ( response.getContentType() == null ) { response.setContentType(AppGuardianConfiguration.DEFAULT_CONTENT_TYPE); } inboundContentType = response.getContentType(); charEnc = response.getCharacterEncoding(); - + } else { if ( httpResponse.getContentType() == null ) { httpResponse.setContentType(AppGuardianConfiguration.DEFAULT_CONTENT_TYPE); @@ -78,7 +78,7 @@ public Action check(HttpServletRequest request, inboundContentType = httpResponse.getContentType(); charEnc = httpResponse.getCharacterEncoding(); } - + if ( contentType.matcher(inboundContentType).matches() ) { /* * Depending on the encoding, search through the bytes @@ -87,7 +87,7 @@ public Action check(HttpServletRequest request, try { byte[] bytes = null; - + try { bytes = response.getInterceptingServletOutputStream().getResponseBytes(); } catch (IOException ioe) { diff --git a/src/main/java/org/owasp/esapi/waf/rules/EnforceHTTPSRule.java b/src/main/java/org/owasp/esapi/waf/rules/EnforceHTTPSRule.java index 8b8cb441d..bd31562c3 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/EnforceHTTPSRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/EnforceHTTPSRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -51,7 +51,7 @@ public EnforceHTTPSRule(String id, Pattern path, List exceptions, String } public Action check(HttpServletRequest request, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { if ( ! request.isSecure() ) { diff --git a/src/main/java/org/owasp/esapi/waf/rules/GeneralAttackSignatureRule.java b/src/main/java/org/owasp/esapi/waf/rules/GeneralAttackSignatureRule.java index d427abda1..66edec401 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/GeneralAttackSignatureRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/GeneralAttackSignatureRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -28,7 +28,7 @@ import org.owasp.esapi.waf.internal.InterceptingHTTPServletResponse; /** - * This is the Rule subclass executed for <general-attack-signature> rules, which + * This is the Rule subclass executed for <general-attack-signature> rules, which * are not currently implemented. * @author Arshan Dabirsiaghi * @@ -43,7 +43,7 @@ public GeneralAttackSignatureRule(String id, Pattern signature) { } public Action check(HttpServletRequest req, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { InterceptingHTTPServletRequest request = (InterceptingHTTPServletRequest)req; diff --git a/src/main/java/org/owasp/esapi/waf/rules/HTTPMethodRule.java b/src/main/java/org/owasp/esapi/waf/rules/HTTPMethodRule.java index eecbcbfe2..1c8e8e1dd 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/HTTPMethodRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/HTTPMethodRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -44,7 +44,7 @@ public HTTPMethodRule(String id, Pattern allowedMethods, Pattern deniedMethods, } public Action check(HttpServletRequest request, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { /* diff --git a/src/main/java/org/owasp/esapi/waf/rules/IPRule.java b/src/main/java/org/owasp/esapi/waf/rules/IPRule.java index 3308ced68..eaa534ebe 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/IPRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/IPRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -54,20 +54,20 @@ public IPRule(String id, Pattern allowedIP, String exactPath) { } public Action check(HttpServletRequest request, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { String uri = request.getRequestURI(); if ( (!useExactPath && path.matcher(uri).matches()) || ( useExactPath && exactPath.equals(uri)) ) { - + String sourceIP = request.getRemoteAddr() + ""; - + if ( ipHeader != null ) { sourceIP = request.getHeader(ipHeader); } - + if ( ! allowedIP.matcher(sourceIP).matches() ) { log(request, "IP not allowed to access URI '" + uri + "'"); return new DefaultAction(); diff --git a/src/main/java/org/owasp/esapi/waf/rules/MustMatchRule.java b/src/main/java/org/owasp/esapi/waf/rules/MustMatchRule.java index 7c12f2ccd..9b0c42ff5 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/MustMatchRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/MustMatchRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ diff --git a/src/main/java/org/owasp/esapi/waf/rules/PathExtensionRule.java b/src/main/java/org/owasp/esapi/waf/rules/PathExtensionRule.java index 9c61eabd9..c059ca811 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/PathExtensionRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/PathExtensionRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -42,7 +42,7 @@ public PathExtensionRule (String id, Pattern allow, Pattern deny) { } public Action check(HttpServletRequest request, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { if ( allow != null && allow.matcher(request.getRequestURI()).matches() ) { diff --git a/src/main/java/org/owasp/esapi/waf/rules/ReplaceContentRule.java b/src/main/java/org/owasp/esapi/waf/rules/ReplaceContentRule.java index 4c8298401..b36062bcf 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/ReplaceContentRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/ReplaceContentRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -40,7 +40,7 @@ public class ReplaceContentRule extends Rule { private String replacement; private Pattern contentType; private Pattern path; - + public ReplaceContentRule(String id, Pattern pattern, String replacement, Pattern contentType, Pattern path) { this.pattern = pattern; this.replacement = replacement; @@ -54,7 +54,7 @@ public ReplaceContentRule(String id, Pattern pattern, String replacement, Patter */ public Action check(HttpServletRequest request, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { /* @@ -64,7 +64,7 @@ public Action check(HttpServletRequest request, if ( path != null && ! path.matcher(uri).matches() ) { return new DoNothingAction(); } - + /* * Second early fail: if the content type is one we'd like to search for output patterns. */ @@ -84,21 +84,21 @@ public Action check(HttpServletRequest request, return new DoNothingAction(); // yes this is a fail open! } - + try { String s = new String(bytes,response.getCharacterEncoding()); Matcher m = pattern.matcher(s); String canary = m.replaceAll(replacement); - + try { - + if ( ! s.equals(canary) ) { response.getInterceptingServletOutputStream().setResponseBytes(canary.getBytes(response.getCharacterEncoding())); logger.debug(Logger.SECURITY_SUCCESS, "Successfully replaced pattern '" + pattern.pattern() + "' on response to URL '" + request.getRequestURL() + "'"); } - + } catch (IOException ioe) { logger.error(Logger.SECURITY_FAILURE, "Failed to replace pattern '" + pattern.pattern() + "' on response to URL '" + request.getRequestURL() + "' due to [" + ioe.getMessage() + "]"); } diff --git a/src/main/java/org/owasp/esapi/waf/rules/RestrictContentTypeRule.java b/src/main/java/org/owasp/esapi/waf/rules/RestrictContentTypeRule.java index 0891dfc5e..43ea63aaf 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/RestrictContentTypeRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/RestrictContentTypeRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -42,7 +42,7 @@ public RestrictContentTypeRule(String id, Pattern allow, Pattern deny) { } public Action check(HttpServletRequest request, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { /* can't check content type if it's not available */ diff --git a/src/main/java/org/owasp/esapi/waf/rules/RestrictUserAgentRule.java b/src/main/java/org/owasp/esapi/waf/rules/RestrictUserAgentRule.java index 204bde2c4..ae31b1965 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/RestrictUserAgentRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/RestrictUserAgentRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -46,11 +46,11 @@ public RestrictUserAgentRule(String id, Pattern allow, Pattern deny) { } public Action check(HttpServletRequest request, InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { - + String userAgent = request.getHeader( USER_AGENT_HEADER ); - + if ( userAgent == null ) userAgent=""; - + if ( allow != null ) { if ( allow.matcher(userAgent).matches() ) { return new DoNothingAction(); @@ -62,12 +62,12 @@ public Action check(HttpServletRequest request, InterceptingHTTPServletResponse } log(request, "Disallowed user agent pattern '" + deny.pattern() + "' found in user agent '" + request.getHeader(USER_AGENT_HEADER) + "'"); - + /* * If we don't force this to "block", the user will be in an infinite loop, possibly * eating our bandwidth, and in the case of a dread false positive, really piss them * off. - * + * * Better to just reject. */ if ( AppGuardianConfiguration.DEFAULT_FAIL_ACTION == AppGuardianConfiguration.REDIRECT ) { diff --git a/src/main/java/org/owasp/esapi/waf/rules/Rule.java b/src/main/java/org/owasp/esapi/waf/rules/Rule.java index 8e1ee87a8..26adc95b9 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/Rule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/Rule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ diff --git a/src/main/java/org/owasp/esapi/waf/rules/RuleUtil.java b/src/main/java/org/owasp/esapi/waf/rules/RuleUtil.java index d8a43e1c7..3b22edbe7 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/RuleUtil.java +++ b/src/main/java/org/owasp/esapi/waf/rules/RuleUtil.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ diff --git a/src/main/java/org/owasp/esapi/waf/rules/SimpleVirtualPatchRule.java b/src/main/java/org/owasp/esapi/waf/rules/SimpleVirtualPatchRule.java index bd973f54c..44c8e181b 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/SimpleVirtualPatchRule.java +++ b/src/main/java/org/owasp/esapi/waf/rules/SimpleVirtualPatchRule.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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 Arshan Dabirsiaghi Aspect Security * @created 2009 */ @@ -51,7 +51,7 @@ public SimpleVirtualPatchRule(String id, Pattern path, String variable, Pattern } public Action check(HttpServletRequest req, - InterceptingHTTPServletResponse response, + InterceptingHTTPServletResponse response, HttpServletResponse httpResponse) { InterceptingHTTPServletRequest request = (InterceptingHTTPServletRequest)req; @@ -108,7 +108,7 @@ public Action check(HttpServletRequest req, } } } - + return new DoNothingAction(); } else { diff --git a/src/main/java/org/owasp/esapi/waf/rules/package.html b/src/main/java/org/owasp/esapi/waf/rules/package.html index 0f29d7ea3..bf418c05b 100644 --- a/src/main/java/org/owasp/esapi/waf/rules/package.html +++ b/src/main/java/org/owasp/esapi/waf/rules/package.html @@ -5,8 +5,8 @@ -This package contains all of the Rule subclasses that correspond to policy file entries. Each -class contains the logic for enforcing its rule. - +This package contains all of the Rule subclasses that correspond to policy file entries. Each +class contains the logic for enforcing its rule. + diff --git a/src/test/java/org/owasp/esapi/ESAPIContractAPITest.java b/src/test/java/org/owasp/esapi/ESAPIContractAPITest.java index e23a60650..059eb00aa 100644 --- a/src/test/java/org/owasp/esapi/ESAPIContractAPITest.java +++ b/src/test/java/org/owasp/esapi/ESAPIContractAPITest.java @@ -20,33 +20,33 @@ public class ESAPIContractAPITest { @Mock private SecurityConfiguration mockSecConfig; - + @Mock private Validator mockValidator; - + @Before public void configureStaticContexts() throws Exception { PowerMockito.mockStatic(ObjFactory.class); PowerMockito.when(ObjFactory.class, "make", ArgumentMatchers.anyString(), ArgumentMatchers.eq("SecurityConfiguration")).thenReturn(mockSecConfig); PowerMockito.when(ObjFactory.class, "make", ArgumentMatchers.eq("MOCK_TEST_VALIDATOR"), ArgumentMatchers.eq("Validator")).thenReturn(mockValidator); - + PowerMockito.when(mockSecConfig.getValidationImplementation()).thenReturn("MOCK_TEST_VALIDATOR"); } - + @Test public void testValidatorFromConfiguration() { Validator validator = ESAPI.validator(); Assert.assertEquals("ESAPI Configuration should return Validator as specified by the SecurityConfiguration", mockValidator, validator); - + PowerMockito.verifyStatic(ObjFactory.class, VerificationModeFactory.times(1)); ObjFactory.make(ArgumentMatchers.anyString(), ArgumentMatchers.eq("SecurityConfiguration")); - + PowerMockito.verifyStatic(ObjFactory.class, VerificationModeFactory.times(1)); ObjFactory.make(ArgumentMatchers.eq("MOCK_TEST_VALIDATOR"), ArgumentMatchers.eq("Validator")); - + PowerMockito.verifyNoMoreInteractions(ObjFactory.class); - + Mockito.verify(mockSecConfig, Mockito.times(1)).getValidationImplementation(); } - + } diff --git a/src/test/java/org/owasp/esapi/SecurityConfigurationWrapper.java b/src/test/java/org/owasp/esapi/SecurityConfigurationWrapper.java index 5cc0daf29..1d5a521b8 100644 --- a/src/test/java/org/owasp/esapi/SecurityConfigurationWrapper.java +++ b/src/test/java/org/owasp/esapi/SecurityConfigurationWrapper.java @@ -9,7 +9,7 @@ import java.util.regex.Pattern; /** - * Simple wrapper implementation of {@link SecurityConfiguration}. + * Simple wrapper implementation of {@link SecurityConfiguration}. * This allows for easy subclassing and property fixups for unit tests. * * Note that there are some compilers have issues with Override @@ -47,7 +47,7 @@ public String getApplicationName() { return wrapped.getApplicationName(); } - + /** * {@inheritDoc} */ @@ -56,7 +56,7 @@ public String getLogImplementation() { return wrapped.getLogImplementation(); } - + /** * {@inheritDoc} */ @@ -65,7 +65,7 @@ public String getAuthenticationImplementation() { return wrapped.getAuthenticationImplementation(); } - + /** * {@inheritDoc} */ @@ -74,7 +74,7 @@ public String getEncoderImplementation() { return wrapped.getEncoderImplementation(); } - + /** * {@inheritDoc} */ @@ -83,7 +83,7 @@ public String getAccessControlImplementation() { return wrapped.getAccessControlImplementation(); } - + /** * {@inheritDoc} */ @@ -92,7 +92,7 @@ public String getIntrusionDetectionImplementation() { return wrapped.getIntrusionDetectionImplementation(); } - + /** * {@inheritDoc} */ @@ -101,7 +101,7 @@ public String getRandomizerImplementation() { return wrapped.getRandomizerImplementation(); } - + /** * {@inheritDoc} */ @@ -110,7 +110,7 @@ public String getEncryptionImplementation() { return wrapped.getEncryptionImplementation(); } - + /** * {@inheritDoc} */ @@ -119,7 +119,7 @@ public String getValidationImplementation() { return wrapped.getValidationImplementation(); } - + /** * {@inheritDoc} */ @@ -128,7 +128,7 @@ public Pattern getValidationPattern( String typeName ) { return wrapped.getValidationPattern(typeName); } - + /** * {@inheritDoc} */ @@ -137,7 +137,7 @@ public String getExecutorImplementation() { return wrapped.getExecutorImplementation(); } - + /** * {@inheritDoc} */ @@ -146,7 +146,7 @@ public String getHTTPUtilitiesImplementation() { return wrapped.getHTTPUtilitiesImplementation(); } - + /** * {@inheritDoc} */ @@ -164,7 +164,7 @@ public File getUploadDirectory() { return wrapped.getUploadDirectory(); } - + /** * {@inheritDoc} */ @@ -182,7 +182,7 @@ public int getEncryptionKeyLength() { return wrapped.getEncryptionKeyLength(); } - + /** * {@inheritDoc} */ @@ -363,7 +363,7 @@ public int getDigitalSignatureKeyLength() { return wrapped.getDigitalSignatureKeyLength(); } - + /** * {@inheritDoc} */ @@ -408,12 +408,12 @@ public File getResourceFile( String filename ) { return wrapped.getResourceFile(filename); } - + /** * {@inheritDoc} */ // @Override - public boolean getForceHttpOnlySession() + public boolean getForceHttpOnlySession() { return wrapped.getForceHttpOnlySession(); } @@ -422,7 +422,7 @@ public boolean getForceHttpOnlySession() * {@inheritDoc} */ // @Override - public boolean getForceSecureSession() + public boolean getForceSecureSession() { return wrapped.getForceSecureSession(); } @@ -462,7 +462,7 @@ public InputStream getResourceStream( String filename ) throws IOException return wrapped.getResourceStream(filename); } - + /** * {@inheritDoc} */ @@ -471,7 +471,7 @@ public void setResourceDirectory(String dir) { wrapped.setResourceDirectory(dir); } - + /** * {@inheritDoc} */ @@ -488,7 +488,7 @@ public String getResponseContentType() public String getHttpSessionIdName() { return wrapped.getHttpSessionIdName(); } - + /** * {@inheritDoc} */ @@ -506,7 +506,7 @@ public int getSessionIdleTimeoutLength() { return wrapped.getSessionIdleTimeoutLength(); } - + /** * {@inheritDoc} */ @@ -515,7 +515,7 @@ public int getSessionAbsoluteTimeoutLength() { return wrapped.getSessionAbsoluteTimeoutLength(); } - + /** * {@inheritDoc} */ @@ -524,7 +524,7 @@ public boolean getLogEncodingRequired() { return wrapped.getLogEncodingRequired(); } - + /** * {@inheritDoc} */ diff --git a/src/test/java/org/owasp/esapi/StringUtilitiesTest.java b/src/test/java/org/owasp/esapi/StringUtilitiesTest.java index 6865459ce..c7f29d27a 100644 --- a/src/test/java/org/owasp/esapi/StringUtilitiesTest.java +++ b/src/test/java/org/owasp/esapi/StringUtilitiesTest.java @@ -12,14 +12,14 @@ public class StringUtilitiesTest extends TestCase { /** * Run all the test cases in this suite. * This is to allow running from {@code org.owasp.esapi.AllTests}. - * + * * @return the test */ public static Test suite() { TestSuite suite = new TestSuite(StringUtilitiesTest.class); return suite; } - + /** Test the getLevenshteinDistance() method. */ public void testGetLevenshteinDistance() { String src = "GUMBO"; @@ -52,7 +52,7 @@ public void testUnion() { char[] union = StringUtilities.union(a1, a2); assertTrue( Arrays.equals( union, new char[] {'a','b','c','d','e' } ) ); } - + /** Test the contains() method. */ public void contains() { StringBuilder sb = new StringBuilder( "abc" ); diff --git a/src/test/java/org/owasp/esapi/UserTest.java b/src/test/java/org/owasp/esapi/UserTest.java index 3292643b7..109a6251a 100644 --- a/src/test/java/org/owasp/esapi/UserTest.java +++ b/src/test/java/org/owasp/esapi/UserTest.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -40,18 +40,18 @@ public static Test suite() { TestSuite suite = new TestSuite(UserTest.class); return suite; } - + public void testAllMethods() throws Exception { // create a user to test Anonymous String accountName = ESAPI.randomizer().getRandomString(8, EncoderConstants.CHAR_ALPHANUMERICS); Authenticator instance = ESAPI.authenticator(); String password = instance.generateStrongPassword(); - + // Probably could skip the assignment here, but maybe someone had // future plans to use this. So will just suppress warning for now. @SuppressWarnings("unused") User user = instance.createUser(accountName, password, password); - + // test the rest of the Anonymous user try { User.ANONYMOUS.addRole(null); } catch( RuntimeException e ) {} try { User.ANONYMOUS.addRoles(null); } catch( RuntimeException e ) {} diff --git a/src/test/java/org/owasp/esapi/ValidationErrorListTest.java b/src/test/java/org/owasp/esapi/ValidationErrorListTest.java index 18c6450f4..42762d7f3 100644 --- a/src/test/java/org/owasp/esapi/ValidationErrorListTest.java +++ b/src/test/java/org/owasp/esapi/ValidationErrorListTest.java @@ -1,15 +1,15 @@ /** * 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 */ diff --git a/src/test/java/org/owasp/esapi/codecs/AbstractCodecTest.java b/src/test/java/org/owasp/esapi/codecs/AbstractCodecTest.java index a557796e4..f4f1b7b46 100644 --- a/src/test/java/org/owasp/esapi/codecs/AbstractCodecTest.java +++ b/src/test/java/org/owasp/esapi/codecs/AbstractCodecTest.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -44,7 +44,7 @@ public class AbstractCodecTest extends TestCase { /** * Instantiates a new access reference map test. - * + * * @param testName * the test name */ @@ -70,7 +70,7 @@ protected void tearDown() throws Exception { /** * Suite. - * + * * @return the test */ public static Test suite() { @@ -134,10 +134,10 @@ public void testWindowsEncode() assertEquals( "^<", windowsCodec.encode(EMPTY_CHAR_ARRAY, "<") ); } - + public void testHtmlEncodeChar() { - + assertEquals( "<", htmlCodec.encodeCharacter(EMPTY_CHAR_ARRAY, (int) LESS_THAN) ); } @@ -148,7 +148,7 @@ public void testHtmlEncodeChar0x100() String expected = "Ā"; String result; //The new default for HTMLEntityCodec is ints/Integers. Use Character/char at your own risk! - //Characters destroy non-BMP codepoints. This Codec is now supposed surpass that. + //Characters destroy non-BMP codepoints. This Codec is now supposed surpass that. result = htmlCodec.encodeCharacter(EMPTY_CHAR_ARRAY, (int) in); // this should be escaped assertFalse(inStr.equals(result)); @@ -233,7 +233,7 @@ public void testJavaScriptEncodeStr0x100() assertFalse(inStr.equals(result)); assertEquals(expected,result); } - + public void testVBScriptEncodeChar() { assertEquals( "chrw(60)", vbScriptCodec.encodeCharacter(EMPTY_CHAR_ARRAY, LESS_THAN) ); @@ -400,7 +400,7 @@ public void testWindowsEncodeStr0x100() assertFalse(inStr.equals(result)); assertEquals(expected,result); } - + public void testHtmlDecodeDecimalEntities() { assertEquals( "test!", htmlCodec.decode("test!") ); @@ -513,7 +513,7 @@ public void testJavaScriptDecodeBackSlashHex() { assertEquals( "<", javaScriptCodec.decode("\\x3c") ); } - + public void testVBScriptDecode() { assertEquals( "<", vbScriptCodec.decode("\"<") ); @@ -573,7 +573,7 @@ public void testWindowsDecode() { assertEquals( "<", windowsCodec.decode("^<") ); } - + public void testHtmlDecodeCharLessThan() { Integer value = htmlCodec.decodeCharacter(new PushBackSequenceImpl("<")); @@ -591,7 +591,7 @@ public void testJavaScriptDecodeCharBackSlashHex() { assertEquals( LESS_THAN, javaScriptCodec.decodeCharacter(new PushbackString("\\x3c") )); } - + public void testVBScriptDecodeChar() { assertEquals( LESS_THAN, vbScriptCodec.decodeCharacter(new PushbackString("\"<") )); diff --git a/src/test/java/org/owasp/esapi/codecs/CSSCodecTest.java b/src/test/java/org/owasp/esapi/codecs/CSSCodecTest.java index 8ca39ee05..ea04aaf7e 100644 --- a/src/test/java/org/owasp/esapi/codecs/CSSCodecTest.java +++ b/src/test/java/org/owasp/esapi/codecs/CSSCodecTest.java @@ -8,7 +8,7 @@ public class CSSCodecTest { private static final char[] IMMUNE_STUB = new char[0]; /** Unit In Test*/ private CSSCodec uit = new CSSCodec(); - + @Test public void testCSSTripletLeadString() { assertEquals("rgb(255,255,255)\\21 ", uit.encode(IMMUNE_STUB, "rgb(255,255,255)!")); diff --git a/src/test/java/org/owasp/esapi/codecs/CodecImmunityTest.java b/src/test/java/org/owasp/esapi/codecs/CodecImmunityTest.java index 9a3b8806f..ef7d9a00a 100644 --- a/src/test/java/org/owasp/esapi/codecs/CodecImmunityTest.java +++ b/src/test/java/org/owasp/esapi/codecs/CodecImmunityTest.java @@ -17,7 +17,7 @@ /** * Parameterized test to verify that the Immunity parameter for a codec * encode/decode event works as expected on a series of special characters. - * + * * @author jeremiah.j.stacey@gmail.com * @since 2.1.0.1 * @@ -100,7 +100,7 @@ private static Collection buildImmunitiyValidation(Codec codec, char[] } private static Collection fullCharacterCodecValidation(Collection codecs) { - char[] holyCowTesting = StringUtilities.union(EncoderConstants.CHAR_ALPHANUMERICS, EncoderConstants.CHAR_SPECIALS); + char[] holyCowTesting = StringUtilities.union(EncoderConstants.CHAR_ALPHANUMERICS, EncoderConstants.CHAR_SPECIALS); Collection params = new ArrayList(); for (Codec codec: codecs) { params.addAll(buildImmunitiyValidation(codec, holyCowTesting, "Full_ALPHA_AND_SPECIALS")); @@ -118,7 +118,7 @@ public CodecImmunityTest(String ignored, Codec codec, String toTest) { this.string = toTest; /** * The Immunity character array is every character in the String we're testing. - * + * */ this.immunityList = toTest.toCharArray(); } diff --git a/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java b/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java index 0757f604b..070e28a26 100644 --- a/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java +++ b/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java @@ -6,7 +6,7 @@ public class HTMLEntityCodecTest { Codec codec = new HTMLEntityCodec(); - + @Test public void testEntityDecoding(){ assertEquals("<", codec.decode("<")); @@ -14,7 +14,7 @@ public void testEntityDecoding(){ assertEquals( "<", codec.decode("<")); assertEquals( "<", codec.decode("<")); } - + @Test public void test32BitCJK(){ String s = "𡘾𦴩𥻂"; @@ -23,7 +23,7 @@ public void test32BitCJK(){ assertEquals(false, expected.equals(bad)); assertEquals(expected, codec.encode(new char[0], s)); } - + @Test public void test32BitCJKMixedWithBmp(){ String s = "𡘾𦴩<𥻂"; @@ -32,14 +32,14 @@ public void test32BitCJKMixedWithBmp(){ assertEquals(false, expected.equals(bad)); assertEquals(expected, codec.encode(new char[0], s)); } - + @Test public void testDecodeforChars(){ String s = "!@$%()=+{}[]"; String expected = "!@$%()=+{}[]"; assertEquals(expected, codec.decode(s)); } - + @Test public void testMixedBmpAndNonBmp(){ String nonBMP = new String(new int[]{0x2f804}, 0, 1); diff --git a/src/test/java/org/owasp/esapi/codecs/MySQLCodecTest.java b/src/test/java/org/owasp/esapi/codecs/MySQLCodecTest.java index 04e57850a..f6cca0645 100644 --- a/src/test/java/org/owasp/esapi/codecs/MySQLCodecTest.java +++ b/src/test/java/org/owasp/esapi/codecs/MySQLCodecTest.java @@ -17,7 +17,7 @@ /** * Tests to show {@link MySQLCodec} with {@link Mode#ANSI} * comply with the OWASP Escaping recommendations - * + * * https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#MySQL_Escaping * */ @@ -65,7 +65,7 @@ public static void createCodecEscapeMaps () { /** * ANSI * Test showing that for characters up to 256, the only encoded value is the single tick. - * + * * when the single tick is encoded, it is updated to be double tick. All other characters remain unchanged. */ @Test @@ -93,7 +93,7 @@ public void testAnsiEncodeTo256() { public void testAnsiEncodeWithImmuneSet() { //The only value that is encoded is single tick. The immunity list does not impact normal capability in ANSI mode char[] immuneChars = new char[] {15, 91,150, 255}; - + for (char refChar : immuneChars) { int ref = refChar; String charAsString = "" + refChar; @@ -165,12 +165,12 @@ public void testStandardEncodeNonAlphaNumeric() { } } - + @Test public void testStandardEncodeWithImmuneSet() { //These values normally fall under the encodeNonAlphaNumeric test content. char[] immuneChars = new char[] {15, 91,150, 255}; - + for (char refChar : immuneChars) { int ref = refChar; String charAsString = "" + refChar; @@ -199,7 +199,7 @@ public void testStandardEncodeEscapeSet() { Matcher encodeExpect = new IsEqual<>(expected); Matcher decodeExpect = new IsEqual<>(charAsString); errorCollector.checkThat(encodeMsg, uitMySqlStandard.encode(EMPTY_CHAR_ARRAY, charAsString), encodeExpect); - errorCollector.checkThat(decodeMsg, uitMySqlStandard.decode(expected), decodeExpect); + errorCollector.checkThat(decodeMsg, uitMySqlStandard.decode(expected), decodeExpect); } } @@ -210,16 +210,16 @@ public void testStandardEncodeEscapeSet() { public void testAnsiDecodePushbackSequenceNullFirstElementReturnsNull() { PushbackSequence mockPushback = Mockito.mock(PushbackSequence.class); Mockito.when(mockPushback.next()).thenReturn(null); - + Character decChar = uitAnsi.decodeCharacter(mockPushback); Assert.assertNull(decChar); - + Mockito.verify(mockPushback, Mockito.times(1)).mark(); Mockito.verify(mockPushback, Mockito.times(1)).next(); Mockito.verify(mockPushback, Mockito.times(1)).reset(); - + } - + /** * If the first character is a single tick, and the second character is null, null is expected */ @@ -227,16 +227,16 @@ public void testAnsiDecodePushbackSequenceNullFirstElementReturnsNull() { public void testAnsiDecodePushbackSequenceNullSecondElementReturnsNull() { PushbackSequence mockPushback = Mockito.mock(PushbackSequence.class); Mockito.when(mockPushback.next()).thenReturn('\'').thenReturn(null); - + Character decChar = uitAnsi.decodeCharacter(mockPushback); Assert.assertNull(decChar); - + Mockito.verify(mockPushback, Mockito.times(1)).mark(); Mockito.verify(mockPushback, Mockito.times(2)).next(); Mockito.verify(mockPushback, Mockito.times(1)).reset(); - + } - + /** * If the first character is a single tick and the second character is NOT a single tick (escaped tick), then null is expected. */ @@ -244,14 +244,14 @@ public void testAnsiDecodePushbackSequenceNullSecondElementReturnsNull() { public void testAnsiDecodePushbackSequenceNonTickSecondElmentReturnsNull() { PushbackSequence mockPushback = Mockito.mock(PushbackSequence.class); Mockito.when(mockPushback.next()).thenReturn('\'').thenReturn('A'); - + Character decChar = uitAnsi.decodeCharacter(mockPushback); Assert.assertNull(decChar); - + Mockito.verify(mockPushback, Mockito.times(1)).mark(); Mockito.verify(mockPushback, Mockito.times(2)).next(); Mockito.verify(mockPushback, Mockito.times(1)).reset(); - + } /** * If two single ticks are read in sequence, a single tick is expected. @@ -260,14 +260,14 @@ public void testAnsiDecodePushbackSequenceNonTickSecondElmentReturnsNull() { public void testAnsiDecodePushbackSequenceReturnsSingleTick() { PushbackSequence mockPushback = Mockito.mock(PushbackSequence.class); Mockito.when(mockPushback.next()).thenReturn('\'').thenReturn('\''); - + Character decChar = uitAnsi.decodeCharacter(mockPushback); Assert.assertEquals('\'', decChar.charValue()); - + Mockito.verify(mockPushback, Mockito.times(1)).mark(); Mockito.verify(mockPushback, Mockito.times(2)).next(); Mockito.verify(mockPushback, Mockito.times(0)).reset(); - + } /** @@ -277,16 +277,16 @@ public void testAnsiDecodePushbackSequenceReturnsSingleTick() { public void testAnsiDecodePushbackSequenceNonTickFirstElementReturnsNull() { PushbackSequence mockPushback = Mockito.mock(PushbackSequence.class); Mockito.when(mockPushback.next()).thenReturn('A'); - + Character decChar = uitAnsi.decodeCharacter(mockPushback); Assert.assertNull(decChar); - + Mockito.verify(mockPushback, Mockito.times(1)).mark(); Mockito.verify(mockPushback, Mockito.times(1)).next(); Mockito.verify(mockPushback, Mockito.times(1)).reset(); - + } - + /** * If the first character is null, null is expected */ @@ -294,14 +294,14 @@ public void testAnsiDecodePushbackSequenceNonTickFirstElementReturnsNull() { public void testStandardDecodePushbackSequenceNullFirstElementReturnsNull() { PushbackSequence mockPushback = Mockito.mock(PushbackSequence.class); Mockito.when(mockPushback.next()).thenReturn(null); - + Character decChar = uitMySqlStandard.decodeCharacter(mockPushback); Assert.assertNull(decChar); - + Mockito.verify(mockPushback, Mockito.times(1)).mark(); Mockito.verify(mockPushback, Mockito.times(1)).next(); Mockito.verify(mockPushback, Mockito.times(1)).reset(); - + } /** * If the first character is a backslash, and the second character is null, null is expected @@ -310,37 +310,37 @@ public void testStandardDecodePushbackSequenceNullFirstElementReturnsNull() { public void testStandardDecodePushbackSequenceNullSecondElementReturnsNull() { PushbackSequence mockPushback = Mockito.mock(PushbackSequence.class); Mockito.when(mockPushback.next()).thenReturn('\\').thenReturn(null); - + Character decChar = uitMySqlStandard.decodeCharacter(mockPushback); Assert.assertNull(decChar); - + Mockito.verify(mockPushback, Mockito.times(1)).mark(); Mockito.verify(mockPushback, Mockito.times(2)).next(); Mockito.verify(mockPushback, Mockito.times(1)).reset(); - + } - + @Test public void testCreateAnsiByInt() { MySQLCodec codec = new MySQLCodec(MySQLCodec.ANSI_MODE); Object configMode = Whitebox.getInternalState(codec, "mode"); Assert.assertEquals(Mode.ANSI, configMode); } - + @Test public void testCreateStandardByInt() { MySQLCodec codec = new MySQLCodec(MySQLCodec.MYSQL_MODE); Object configMode = Whitebox.getInternalState(codec, "mode"); Assert.assertEquals(Mode.STANDARD, configMode); } - + @Test public void testCreateUnsupportedModeByInt() { exEx.expect(IllegalArgumentException.class); String message = String.format("No Mode for %s. Valid references are MySQLStandard: %s or ANSI: %s", Integer.MIN_VALUE, MySQLCodec.MYSQL_MODE, MySQLCodec.ANSI_MODE); exEx.expectMessage(message); new MySQLCodec(Integer.MIN_VALUE); - + } private static class InclusiveRangePair { private final int upperInclusive; diff --git a/src/test/java/org/owasp/esapi/codecs/PercentCodecTest.java b/src/test/java/org/owasp/esapi/codecs/PercentCodecTest.java index 2946d54ed..5cc9f261b 100644 --- a/src/test/java/org/owasp/esapi/codecs/PercentCodecTest.java +++ b/src/test/java/org/owasp/esapi/codecs/PercentCodecTest.java @@ -5,11 +5,11 @@ import org.junit.Test; public class PercentCodecTest { - + @Test public void testPercentDecode(){ Codec codec = new PercentCodec(); - + String expected = " "; assertEquals(expected, codec.decode("%20")); } diff --git a/src/test/java/org/owasp/esapi/codecs/PushBackStringTest.java b/src/test/java/org/owasp/esapi/codecs/PushBackStringTest.java index 61e9bc59a..1f7ad61fd 100644 --- a/src/test/java/org/owasp/esapi/codecs/PushBackStringTest.java +++ b/src/test/java/org/owasp/esapi/codecs/PushBackStringTest.java @@ -9,33 +9,33 @@ public class PushBackStringTest { @Test public void testPushbackString() { PushbackSequence pbs = new PushbackString("012345"); - + pbs.mark(); assertEquals(0, pbs.index()); Character first = pbs.next(); - + System.out.println("0x" + Integer.toHexString(first)); - + assertEquals("0", new StringBuilder().appendCodePoint(first).toString()); } - + @Test public void testPushbackSequence() { AbstractPushbackSequence pbs = new PushBackSequenceImpl("12345"); - + pbs.mark(); assertEquals(0, pbs.index()); Integer first = pbs.next(); - + System.out.println("0x" + Integer.toHexString(first)); - + assertEquals("&", new StringBuilder().appendCodePoint(first).toString()); - + Integer second = pbs.next(); - + if(second == '#'){ System.out.printf("[%d]:[%d]\n", second, (int) '#'); - + } } } diff --git a/src/test/java/org/owasp/esapi/codecs/XMLEntityCodecTest.java b/src/test/java/org/owasp/esapi/codecs/XMLEntityCodecTest.java index 4b3dc56bf..801d33f3d 100644 --- a/src/test/java/org/owasp/esapi/codecs/XMLEntityCodecTest.java +++ b/src/test/java/org/owasp/esapi/codecs/XMLEntityCodecTest.java @@ -1,15 +1,15 @@ /** * 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) 2009 - 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. - * + * */ package org.owasp.esapi.codecs; diff --git a/src/test/java/org/owasp/esapi/codecs/abstraction/AbstractCodecCharacterTest.java b/src/test/java/org/owasp/esapi/codecs/abstraction/AbstractCodecCharacterTest.java index aa7208399..6e77f5a6d 100644 --- a/src/test/java/org/owasp/esapi/codecs/abstraction/AbstractCodecCharacterTest.java +++ b/src/test/java/org/owasp/esapi/codecs/abstraction/AbstractCodecCharacterTest.java @@ -35,7 +35,7 @@ */ @RunWith(Parameterized.class) public abstract class AbstractCodecCharacterTest { - + /** Test Data Tuple.*/ protected static class CodecCharacterTestTuple { /** Codec reference to be tested.*/ @@ -48,7 +48,7 @@ protected static class CodecCharacterTestTuple { public Character decodedValue; /** Optional field to override the toString value of this tuple. */ public String description; - + /**Default public constructor.*/ public CodecCharacterTestTuple() { /* No Op*/ } /** {@inheritDoc}*/ @@ -58,46 +58,46 @@ public String toString() { } } - + protected final Codec codec; protected final String input; protected final char[] encodeImmune; protected final Character decodedValue; - + public AbstractCodecCharacterTest(CodecCharacterTestTuple tuple) { this.codec = tuple.codec; this.input = tuple.input; this.decodedValue = tuple.decodedValue; this.encodeImmune = tuple.encodeImmune; } - + /** Checks that the input value matches the result of the codec encoding the decoded value. */ @Test public void testEncodeCharacter() { assertEquals(input, codec.encodeCharacter(encodeImmune, decodedValue)); } - + /** Checks encoding the character as a String. *
      * If the decoded value is in the immunity list, the the decoded value should be returned from the encode call. - * Otherwise, input is expected as the return. + * Otherwise, input is expected as the return. */ @Test public void testEncode() { String expected = Arrays.asList(encodeImmune).contains(decodedValue) ? decodedValue.toString() : input; assertEquals(expected, codec.encode(encodeImmune, decodedValue.toString())); } - + /** Checks that decoding the input value yields the decodedValue.*/ @Test public void testDecode() { assertEquals(decodedValue.toString(), codec.decode(input)); } - + /** Checks that the encoded input String is correctly decoded to the single decodedValue character reference.*/ @Test public void testDecodePushbackSequence() { assertEquals(decodedValue, codec.decodeCharacter(new PushbackString(input))); } - + } diff --git a/src/test/java/org/owasp/esapi/codecs/abstraction/AbstractCodecStringTest.java b/src/test/java/org/owasp/esapi/codecs/abstraction/AbstractCodecStringTest.java index cf48dcfff..b3a8b9a95 100644 --- a/src/test/java/org/owasp/esapi/codecs/abstraction/AbstractCodecStringTest.java +++ b/src/test/java/org/owasp/esapi/codecs/abstraction/AbstractCodecStringTest.java @@ -32,7 +32,7 @@ */ @RunWith(Parameterized.class) public abstract class AbstractCodecStringTest { - + protected static class CodecStringTestTuple { /** Codec reference to be tested.*/ public Codec codec; @@ -44,10 +44,10 @@ protected static class CodecStringTestTuple { public String decodedValue; /** Optional field to override the toString value of this tuple. */ public String description; - + /**Default public constructor.*/ public CodecStringTestTuple() { /* No Op*/ } - + /** {@inheritDoc}*/ @Override public String toString() { @@ -58,25 +58,25 @@ public String toString() { private final String input; private final char[] encodeImmune; private final String decodedValue; - + public AbstractCodecStringTest(CodecStringTestTuple tuple) { this.codec = tuple.codec; this.input = tuple.input; this.decodedValue = tuple.decodedValue; this.encodeImmune = tuple.encodeImmune; } - + /** Checks that when the input is decoded using the specified codec, that the return matches the expected decoded value.*/ @Test public void testDecode() { assertEquals(decodedValue, codec.decode(input)); } - + /** Checks that when the decoded value is encoded (using immunity), that the return matches the provided input.*/ @Test public void testEncode() { assertEquals(input, codec.encode(encodeImmune, decodedValue)); } - + } diff --git a/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecCharacterTest.java b/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecCharacterTest.java index 7d4425ddc..f80f771c0 100644 --- a/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecCharacterTest.java +++ b/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecCharacterTest.java @@ -29,7 +29,7 @@ /** * Codec validation focused on the PercentCodec Character-based api. - * + * */ public class PercentCodecCharacterTest extends AbstractCodecCharacterTest { @Parameters(name = "{0}") diff --git a/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecKnownIssuesTest.java b/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecKnownIssuesTest.java index ac8c6d6e2..215070837 100644 --- a/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecKnownIssuesTest.java +++ b/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecKnownIssuesTest.java @@ -26,7 +26,7 @@ * the author to move the test to an appropriate Test file and update the functionality to a working expectation. */ public class PercentCodecKnownIssuesTest { - + private PercentCodec codec = new PercentCodec(); /** @@ -39,18 +39,18 @@ public class PercentCodecKnownIssuesTest { public void failsUTF16Conversions() { //This should be 195 int incorrectDecodeExpect = 196; - + char[] encodeImmune = PERCENT_CODEC_IMMUNE; String decodedValue = ""+(char) 0x100; String input = "%C4%80"; String actualDecodeChar = codec.decode(input); int actualChar = (int)actualDecodeChar.charAt(0); - + assertEquals(incorrectDecodeExpect, actualChar); - + //This works as expected. assertEquals(input, codec.encode(encodeImmune, decodedValue)); } - + } diff --git a/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecStringTest.java b/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecStringTest.java index edec02321..57277b1d2 100644 --- a/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecStringTest.java +++ b/src/test/java/org/owasp/esapi/codecs/percent/PercentCodecStringTest.java @@ -24,7 +24,7 @@ /** * Codec validation focused on the PercentCodec String-based api. - * + * */ public class PercentCodecStringTest extends AbstractCodecStringTest { public static final char[] PERCENT_CODEC_IMMUNE; @@ -32,7 +32,7 @@ public class PercentCodecStringTest extends AbstractCodecStringTest { static { /* * The percent codec contains a unique immune character set which include letters and numbers that will not be transformed. - * + * * It is being replicated here to allow the test to reasonably expect the correct state back. */ List immune = new ArrayList<>(); @@ -45,9 +45,9 @@ public class PercentCodecStringTest extends AbstractCodecStringTest { for (int index = 65 ; index < 91; index ++) { Character capsChar = (char)index; immune.add(capsChar); - immune.add(Character.toLowerCase(capsChar)); + immune.add(Character.toLowerCase(capsChar)); } - + PERCENT_CODEC_IMMUNE = new char[immune.size()]; for (int index = 0; index < immune.size(); index++) { PERCENT_CODEC_IMMUNE[index] = immune.get(index).charValue(); @@ -58,7 +58,7 @@ public class PercentCodecStringTest extends AbstractCodecStringTest { public static Collection buildTests() { Collection tests = new ArrayList<>(); List tuples = new ArrayList<>(); - + tuples.add(newTuple("%3C", "<")); tuples.add(newTuple("%00", Character.MIN_VALUE)); tuples.add(newTuple("%3D", '=')); @@ -67,7 +67,7 @@ public static Collection buildTests() { for (char c : PERCENT_CODEC_IMMUNE) { tuples.add(newTuple(Character.toString(c), c)); } - + for (CodecStringTestTuple tuple : tuples) { tests.add(new Object[] { tuple }); } diff --git a/src/test/java/org/owasp/esapi/codecs/ref/EncodingPatternPreservationTest.java b/src/test/java/org/owasp/esapi/codecs/ref/EncodingPatternPreservationTest.java index 66f685e2e..59701c58f 100644 --- a/src/test/java/org/owasp/esapi/codecs/ref/EncodingPatternPreservationTest.java +++ b/src/test/java/org/owasp/esapi/codecs/ref/EncodingPatternPreservationTest.java @@ -7,48 +7,48 @@ import static org.junit.Assert.*; public class EncodingPatternPreservationTest { - + @Test public void testReplaceAndRestore() { Pattern numberRegex = Pattern.compile("(ABC)"); EncodingPatternPreservation epp = new EncodingPatternPreservation(numberRegex); String origStr = "12 ABC 34 DEF 56 G 7"; String replacedStr = epp.captureAndReplaceMatches(origStr); - + assertEquals("12 EncodingPatternPreservation 34 DEF 56 G 7", replacedStr); - + String restored = epp.restoreOriginalContent(replacedStr); assertEquals(origStr, restored); } - + @Test public void testReplaceMultipleAndRestore() { Pattern numberRegex = Pattern.compile("(ABC)"); EncodingPatternPreservation epp = new EncodingPatternPreservation(numberRegex); String origStr = "12 ABC 34 ABC 56 G 7 ABC8"; String replacedStr = epp.captureAndReplaceMatches(origStr); - + assertEquals("12 EncodingPatternPreservation 34 EncodingPatternPreservation 56 G 7 EncodingPatternPreservation8", replacedStr); - + String restored = epp.restoreOriginalContent(replacedStr); assertEquals(origStr, restored); } - + @Test public void testSetMarker() { Pattern numberRegex = Pattern.compile("(ABC)"); EncodingPatternPreservation epp = new EncodingPatternPreservation(numberRegex); epp.setReplacementMarker(EncodingPatternPreservationTest.class.getSimpleName()); - + String origStr = "12 ABC 34 DEF 56 G 7"; String replacedStr = epp.captureAndReplaceMatches(origStr); - + assertEquals("12 EncodingPatternPreservationTest 34 DEF 56 G 7", replacedStr); - + String restored = epp.restoreOriginalContent(replacedStr); assertEquals(origStr, restored); } - + @Test (expected = IllegalStateException.class) public void testSetMarkerExceptionNoReset() { Pattern numberRegex = Pattern.compile("(ABC)"); @@ -57,12 +57,12 @@ public void testSetMarkerExceptionNoReset() { epp.captureAndReplaceMatches(origStr); //This allows the + case to be illustrated epp.reset(); - + //And the exception case. epp.captureAndReplaceMatches(origStr); epp.setReplacementMarker(EncodingPatternPreservationTest.class.getSimpleName()); } - + @Test (expected = IllegalStateException.class) public void testReplaceExceptionNoReset() { Pattern numberRegex = Pattern.compile("(ABC)"); @@ -71,7 +71,7 @@ public void testReplaceExceptionNoReset() { epp.captureAndReplaceMatches(origStr); //This allows the + case to be illustrated epp.reset(); - + //And the exception case. epp.captureAndReplaceMatches(origStr); epp.captureAndReplaceMatches(origStr); diff --git a/src/test/java/org/owasp/esapi/configuration/EsapiPropertyManagerTest.java b/src/test/java/org/owasp/esapi/configuration/EsapiPropertyManagerTest.java index c4453627c..507f33ce1 100644 --- a/src/test/java/org/owasp/esapi/configuration/EsapiPropertyManagerTest.java +++ b/src/test/java/org/owasp/esapi/configuration/EsapiPropertyManagerTest.java @@ -34,14 +34,14 @@ public static void captureEsapiConfigurations() { DEVTEAM_CFG = System.getProperty(EsapiConfiguration.DEVTEAM_ESAPI_CFG.getConfigName(),""); OPSTEAM_CFG = System.getProperty(EsapiConfiguration.OPSTEAM_ESAPI_CFG.getConfigName(),""); } - + @AfterClass public static void restoreEsapiConfigurations() { System.setProperty(EsapiConfiguration.DEVTEAM_ESAPI_CFG.getConfigName(), DEVTEAM_CFG); System.setProperty(EsapiConfiguration.OPSTEAM_ESAPI_CFG.getConfigName(), OPSTEAM_CFG); } - + @Before public void init() { System.setProperty(EsapiConfiguration.DEVTEAM_ESAPI_CFG.getConfigName(), ""); diff --git a/src/test/java/org/owasp/esapi/configuration/StandardEsapiPropertyLoaderTest.java b/src/test/java/org/owasp/esapi/configuration/StandardEsapiPropertyLoaderTest.java index b3144b10a..080644642 100644 --- a/src/test/java/org/owasp/esapi/configuration/StandardEsapiPropertyLoaderTest.java +++ b/src/test/java/org/owasp/esapi/configuration/StandardEsapiPropertyLoaderTest.java @@ -29,14 +29,14 @@ public static void captureEsapiConfigurations() { DEVTEAM_CFG = System.getProperty(EsapiConfiguration.DEVTEAM_ESAPI_CFG.getConfigName(),""); OPSTEAM_CFG = System.getProperty(EsapiConfiguration.OPSTEAM_ESAPI_CFG.getConfigName(),""); } - + @AfterClass public static void restoreEsapiConfigurations() { System.setProperty(EsapiConfiguration.DEVTEAM_ESAPI_CFG.getConfigName(), DEVTEAM_CFG); System.setProperty(EsapiConfiguration.OPSTEAM_ESAPI_CFG.getConfigName(), OPSTEAM_CFG); } - + @Before public void init() { System.setProperty(EsapiConfiguration.DEVTEAM_ESAPI_CFG.getConfigName(), ""); @@ -139,7 +139,7 @@ public void testCompareWithOtherLoaderWithLowerPriority() { public void testGetIntProp() { // given String propertyKey = "int_property"; - + // when try { testPropertyLoader = new StandardEsapiPropertyLoader(filename, priority); @@ -156,7 +156,7 @@ public void testGetIntProp() { public void testIntPropertyNotFound() throws ConfigurationException { // given String propertyKey = "non-existing-key"; - + // when try { testPropertyLoader = new StandardEsapiPropertyLoader(filename, priority); @@ -189,7 +189,7 @@ public void testGetStringProp() { // given String propertyKey = "string_property"; String expectedValue = "test_string_property"; - + // when try { testPropertyLoader = new StandardEsapiPropertyLoader(filename, priority); @@ -197,7 +197,7 @@ public void testGetStringProp() { fail( e.getMessage() ); } String propertyValue = testPropertyLoader.getStringProp(propertyKey); - + // then assertEquals(expectedValue, propertyValue); } @@ -206,7 +206,7 @@ public void testGetStringProp() { public void testStringPropertyNotFound() throws ConfigurationException { // given String propertyKey = "non-existing-key"; - + // when try { testPropertyLoader = new StandardEsapiPropertyLoader(filename, priority); @@ -226,7 +226,7 @@ public void testGetBooleanProp() { int priority = 1; String propertyKey = "boolean_property"; boolean expectedValue = true; - + // when try { testPropertyLoader = new StandardEsapiPropertyLoader(filename, priority); @@ -234,7 +234,7 @@ public void testGetBooleanProp() { fail( e.getMessage() ); } boolean value = testPropertyLoader.getBooleanProp(propertyKey); - + // then assertEquals(expectedValue, value); } @@ -282,7 +282,7 @@ public void testBooleanPropertyNotFound() throws ConfigurationException { "esapi" + File.separator + "ESAPI-test.properties"; int priority = 1; String propertyKey = "non-existing-key"; - + // when try { testPropertyLoader = new StandardEsapiPropertyLoader(filename, priority); @@ -317,14 +317,14 @@ public void testGetByteArrayProp() { "esapi" + File.separator + "ESAPI-test.properties"; int priority = 1; String propertyKey = "string_property"; - + byte[] expectedValue = new byte[0]; try { expectedValue = ESAPI.encoder().decodeFromBase64("test_string_property"); } catch (IOException e) { fail(e.getMessage()); } - + // when try { testPropertyLoader = new StandardEsapiPropertyLoader(filename, priority); @@ -332,7 +332,7 @@ public void testGetByteArrayProp() { fail( e.getMessage() ); } byte[] value = testPropertyLoader.getByteArrayProp(propertyKey); - + // then assertEquals(expectedValue, value); } @@ -343,7 +343,7 @@ public void testByteArrayPropertyNotFound() throws ConfigurationException { String filename = "src" + File.separator + "test" + File.separator + "resources" + File.separator + "esapi" + File.separator + "ESAPI-test.properties"; int priority = 1; String propertyKey = "non-existing-key"; - + // when try { testPropertyLoader = new StandardEsapiPropertyLoader(filename, priority); diff --git a/src/test/java/org/owasp/esapi/configuration/XmlEsapiPropertyLoaderTest.java b/src/test/java/org/owasp/esapi/configuration/XmlEsapiPropertyLoaderTest.java index 2032ae088..6aecec533 100644 --- a/src/test/java/org/owasp/esapi/configuration/XmlEsapiPropertyLoaderTest.java +++ b/src/test/java/org/owasp/esapi/configuration/XmlEsapiPropertyLoaderTest.java @@ -28,7 +28,7 @@ public static void captureEsapiConfigurations() { DEVTEAM_CFG = System.getProperty(EsapiConfiguration.DEVTEAM_ESAPI_CFG.getConfigName(),""); OPSTEAM_CFG = System.getProperty(EsapiConfiguration.OPSTEAM_ESAPI_CFG.getConfigName(),""); } - + @AfterClass public static void restoreEsapiConfigurations() { System.setProperty(EsapiConfiguration.DEVTEAM_ESAPI_CFG.getConfigName(), DEVTEAM_CFG); diff --git a/src/test/java/org/owasp/esapi/crypto/CipherSpecTest.java b/src/test/java/org/owasp/esapi/crypto/CipherSpecTest.java index 9c04201ec..54c69a520 100644 --- a/src/test/java/org/owasp/esapi/crypto/CipherSpecTest.java +++ b/src/test/java/org/owasp/esapi/crypto/CipherSpecTest.java @@ -46,10 +46,10 @@ public class CipherSpecTest extends TestCase { @After public void tearDown() throws Exception { // none } - + /** Test CipherSpec(String cipherXform, int keySize, int blockSize, final byte[] iv) */ @Test public void testCipherSpecStringIntIntByteArray() { - + cipherSpec = new CipherSpec( "AES/CBC/NoPadding", 128, 8, myIV); assertTrue( cipherSpec != null ); cipherSpec = null; @@ -77,7 +77,7 @@ public class CipherSpecTest extends TestCase { assertTrue( cipherSpec != null ); assertTrue( cipherSpec.getCipherAlgorithm().equals("Blowfish")); assertTrue( cipherSpec.getCipherMode().equals("OFB8")); - + cipherSpec = new CipherSpec(dfltAESCipher, 256); assertTrue( cipherSpec != null ); assertTrue( cipherSpec.getCipherAlgorithm().equals("AES")); @@ -91,7 +91,7 @@ public class CipherSpecTest extends TestCase { assertTrue( myIV != null ); assertTrue( myIV.length > 0 ); cipherSpec = new CipherSpec(myIV); - assertTrue( cipherSpec.getKeySize() == + assertTrue( cipherSpec.getKeySize() == ESAPI.securityConfiguration().getEncryptionKeyLength() ); assertTrue( cipherSpec.getCipherTransformation().equals( ESAPI.securityConfiguration().getCipherTransformation() ) ); @@ -102,7 +102,7 @@ public class CipherSpecTest extends TestCase { cipherSpec = new CipherSpec( dfltECBCipher ); assertTrue( cipherSpec.getCipherTransformation().equals("AES/ECB/NoPadding") ); assertTrue( cipherSpec.getIV() == null ); - + cipherSpec = new CipherSpec(dfltOtherCipher); assertTrue( cipherSpec.getCipherMode().equals("OFB8") ); } @@ -112,7 +112,7 @@ public class CipherSpecTest extends TestCase { cipherSpec = new CipherSpec(); cipherSpec.setCipherTransformation("AlgName/Mode/Padding"); cipherSpec.getCipherAlgorithm().equals("AlgName/Mode/Padding"); - + try { // Don't use null here as compiling JUnit tests disables assertion // checking so we get a NullPointerException here instead. @@ -202,7 +202,7 @@ public class CipherSpecTest extends TestCase { assertTrue( cipherSpec.requiresIV() == false ); assertTrue( new CipherSpec(dfltOtherCipher).requiresIV() ); } - + /** Test serialization */ @Test public void testSerialization() { String filename = "cipherspec.ser"; @@ -217,7 +217,7 @@ public class CipherSpecTest extends TestCase { // Guess what? We don't care!!! serializedFile.delete(); - + cipherSpec = new CipherSpec( "AES/CBC/NoPadding", 128, 8, myIV); FileOutputStream fos = new FileOutputStream(filename); ObjectOutputStream out = new ObjectOutputStream(fos); @@ -235,7 +235,7 @@ public class CipherSpecTest extends TestCase { // compare them via their string representations. assertEquals("Serialized restored CipherSpec differs from saved CipherSpec", cipherSpec.toString(), restoredCipherSpec.toString() ); - + success = true; } catch(IOException ex) { ex.printStackTrace(System.err); @@ -258,7 +258,7 @@ public class CipherSpecTest extends TestCase { } } } - + /** * Run all the test cases in this suite. * This is to allow running from {@code org.owasp.esapi.AllTests}. diff --git a/src/test/java/org/owasp/esapi/crypto/CipherTextTest.java b/src/test/java/org/owasp/esapi/crypto/CipherTextTest.java index 8e58498d4..5e8b036a1 100644 --- a/src/test/java/org/owasp/esapi/crypto/CipherTextTest.java +++ b/src/test/java/org/owasp/esapi/crypto/CipherTextTest.java @@ -29,8 +29,8 @@ public class CipherTextTest { private IvParameterSpec ivSpec = null; @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); - - + + @Before public void setUp() throws Exception { encryptor = Cipher.getInstance("AES/CBC/PKCS5Padding"); @@ -114,7 +114,7 @@ public final void testDecryptionUsingCipherText() { String plaintext = new String( ptraw, "UTF-8"); assertTrue( plaintext.equals("Hello") ); assertArrayEquals( ct.getRawCipherText(), ctraw ); - + byte[] ivAndRaw = ESAPI.encoder().decodeFromBase64( ct.getEncodedIVCipherText() ); assertTrue( ivAndRaw.length > ctraw.length ); assertTrue( ct.getBlockSize() == ( ivAndRaw.length - ctraw.length ) ); @@ -147,7 +147,7 @@ public final void testMIC() { CipherText ct = new CipherText(cipherSpec, ctraw); assertTrue( ct.getIV() != null && ct.getIV().length > 0 ); SecretKey authKey = CryptoHelper.computeDerivedKey(key, key.getEncoded().length * 8, "authenticity"); - ct.computeAndStoreMAC( authKey ); + ct.computeAndStoreMAC( authKey ); try { ct.setIVandCiphertext(ivSpec.getIV(), ctraw); // Expected to log & throw. } catch( Exception ex ) { @@ -176,7 +176,7 @@ public final void testMIC() { System.out.println("CipherTextTest.testPortableSerialization()starting..."); String filename = "ciphertext-portable.ser"; File serializedFile = tempFolder.newFile(filename); - + int keySize = 128; if ( CryptoPolicy.isUnlimitedStrengthCryptoAvailable() ) { @@ -196,20 +196,20 @@ public final void testMIC() { ciphertext.computeAndStoreMAC( authKey ); // System.err.println("Original ciphertext being serialized: " + ciphertext); byte[] serializedBytes = ciphertext.asPortableSerializedByteArray(); - + FileOutputStream fos = new FileOutputStream(serializedFile); fos.write(serializedBytes); // Note: FindBugs complains that this test may fail to close // the fos output stream. We don't really care. fos.close(); - + // NOTE: FindBugs complains about this (OS_OPEN_STREAM). It apparently // is too lame to know that 'fis.read()' is a serious side-effect. FileInputStream fis = new FileInputStream(serializedFile); int avail = fis.available(); byte[] bytes = new byte[avail]; fis.read(bytes, 0, avail); - + // Sleep one second to prove that the timestamp on the original // CipherText object is the one that we use and not just the // current time. Only after that, do we restore the serialized bytes. @@ -217,7 +217,7 @@ public final void testMIC() { Thread.sleep(1000); } catch (InterruptedException e) { ; // Ignore - } + } CipherText restoredCipherText = CipherText.fromPortableSerializedBytes(bytes); // System.err.println("Restored ciphertext: " + restoredCipherText); assertTrue( ciphertext.equals(restoredCipherText)); @@ -234,7 +234,7 @@ public final void testMIC() { serializedFile.delete(); } } - + /** Test portable serialization for backward compatibility with ESAPI 2.0. */ @Test public final void testPortableSerializationBackwardCompatibility() { System.out.println("testPortableSerializationBackwardCompatibility()starting..."); @@ -243,7 +243,7 @@ public final void testMIC() { try { // String expectedMsg = "This is my secret message!!!"; - + // NOTE: FindBugs complains about this (OS_OPEN_STREAM). It apparently // is too lame to know that 'fis.read()' is a serious side-effect. FileInputStream fis = new FileInputStream(serializedFile); @@ -267,14 +267,14 @@ public final void testMIC() { ; // Do NOT delete the file. } } - + /** Test Java serialization. */ @Test public final void testJavaSerialization() { String filename = "ciphertext.ser"; - + try { File serializedFile = tempFolder.newFile(filename); - + CipherSpec cipherSpec = new CipherSpec(encryptor, 128); cipherSpec.setIV(ivSpec.getIV()); SecretKey key = @@ -305,7 +305,7 @@ public final void testMIC() { assertEquals("3: Serialized restored CipherText differs from saved CipherText", ciphertext.getBase64EncodedRawCipherText(), restoredCipherText.getBase64EncodedRawCipherText()); - + } catch(IOException ex) { ex.printStackTrace(System.err); fail("testJavaSerialization(): Unexpected IOException: " + ex); @@ -327,9 +327,9 @@ public final void testMIC() { } catch (InvalidAlgorithmParameterException ex) { ex.printStackTrace(System.err); fail("testJavaSerialization(): Unexpected InvalidAlgorithmParameterException: " + ex); - } + } } - + /** * Run all the test cases in this suite. * This is to allow running from {@code org.owasp.esapi.AllTests} which diff --git a/src/test/java/org/owasp/esapi/crypto/CryptoHelperTest.java b/src/test/java/org/owasp/esapi/crypto/CryptoHelperTest.java index 8a327ed76..b315867f5 100644 --- a/src/test/java/org/owasp/esapi/crypto/CryptoHelperTest.java +++ b/src/test/java/org/owasp/esapi/crypto/CryptoHelperTest.java @@ -91,7 +91,7 @@ public final void testArrayCompare() { * Unfortunately, can't rely no the nanosecond timer because as the * Javadoc for System.nanoTime() states, " No guarantees are made * about how frequently values change", so this is not very reliable. - * + * * However, on can uncomment the code and observe that elapsed times * are generally less than 10 millionth of a second. I suppose if we * declared a large enough epsilon, we could make it work, but it is @@ -99,7 +99,7 @@ public final void testArrayCompare() { * itself that it always goes through all the bits of the byte array * if it compares any bits at all. */ - + // long start, stop, diff; // start = System.nanoTime(); @@ -131,13 +131,13 @@ public final void testArrayCompare() { // stop = System.nanoTime(); // diff = stop - start; // System.out.println("diff: " + diff + " nanosec"); - + // start = System.nanoTime(); assertFalse(CryptoHelper.arrayCompare(null, ba1)); // stop = System.nanoTime(); // diff = stop - start; // System.out.println("diff: " + diff + " nanosec"); - + ba2 = ba1; // start = System.nanoTime(); assertTrue(CryptoHelper.arrayCompare(ba1, ba2)); @@ -169,7 +169,7 @@ public final void testIsValidKDFVersion() { assertTrue( e instanceof IllegalArgumentException); } } - + private void fillByteArray(byte[] ba, byte b) { for (int i = 0; i < ba.length; i++) { ba[i] = b; diff --git a/src/test/java/org/owasp/esapi/crypto/CryptoTokenTest.java b/src/test/java/org/owasp/esapi/crypto/CryptoTokenTest.java index 52c60c6ee..250cdd457 100644 --- a/src/test/java/org/owasp/esapi/crypto/CryptoTokenTest.java +++ b/src/test/java/org/owasp/esapi/crypto/CryptoTokenTest.java @@ -15,7 +15,7 @@ import org.owasp.esapi.errors.ValidationException; public class CryptoTokenTest { - + private SecretKey skey1 = null; private SecretKey skey2 = null; @@ -58,7 +58,7 @@ private void CTORtest(CryptoToken ctok, SecretKey sk) { assertEquals( ctok.getUserAccountName(), CryptoToken.ANONYMOUS_USER); assertFalse( ctok.isExpired() ); long expTime1 = ctok.getExpiration(); - + CryptoToken ctok2 = null; try { if ( sk == null ) { @@ -135,7 +135,7 @@ public final void testExpiration() { assertTrue( ctok.isExpired() ); assertTrue( ctok2.isExpired() ); - + try { ctok2.updateToken(2); } catch (EncryptionException e) { @@ -201,7 +201,7 @@ public final void testSetUserAccountName() { } catch (ValidationException e) { ; // Success } - + } @Test @@ -245,7 +245,7 @@ public final void testSetExpirationDate() { ; // Success } catch (Exception e) { fail("Caught unexpected exception: " + e); - } + } } @@ -262,7 +262,7 @@ public final void testSetAndGetAttribute() { } catch (Exception e) { fail("Caught unexpected exception: " + e); } - + // Test case where attr name does not match regex "[A-Za-z0-9_.-]+". // Expect ValidationException. try { @@ -273,7 +273,7 @@ public final void testSetAndGetAttribute() { } catch (Exception e) { fail("Caught unexpected exception: " + e); } - + // Test case where attr VALUE is not. Expect ValidationException. try { ctok.setAttribute("myAttr", null); @@ -293,7 +293,7 @@ public final void testSetAndGetAttribute() { ctok.setAttribute("complexAttr", complexValue); ctok.setAttribute("..--__", ""); // Ugly weird but legal attr name; empty is legal value. - + for ( int i = 0; i < attrValues.length; i++ ) { String attrName = "attr" + i; String attrVal = attrValues[i]; @@ -303,7 +303,7 @@ public final void testSetAndGetAttribute() { String tokenVal = ctok.getToken(); assertNotNull("tokenVal should not be null", tokenVal); - + CryptoToken ctok2 = new CryptoToken(tokenVal); String weirdAttr = ctok2.getAttribute("..--__"); @@ -337,7 +337,7 @@ public final void testSetAndGetAttribute() { // public Map getAttributes() @Test public final void testAddandGetAttributes() { - CryptoToken ctok = new CryptoToken(); + CryptoToken ctok = new CryptoToken(); Map origAttrs = null; try { @@ -348,7 +348,7 @@ public final void testAddandGetAttributes() { String val = ctok.getAttribute("attr2"); assertTrue("Attribute map not cloned; crypto token attr changed!", val.equals("value2") ); // Confirm original attr2 did not change - + origAttrs.put("attr3", "value3"); origAttrs.put("attr4", "value4"); ctok.addAttributes(origAttrs); @@ -361,11 +361,11 @@ public final void testAddandGetAttributes() { } catch (EncryptionException e) { fail("Caught unexpected EncryptionException: " + e); } - + Map extractedAttrs = ctok.getAttributes(); assertTrue("Expected extracted attrs to be equal to original attrs", origAttrs.equals(extractedAttrs)); - + origAttrs.put("/illegalAttrName/", "someValue"); try { ctok.addAttributes(origAttrs); @@ -376,7 +376,7 @@ public final void testAddandGetAttributes() { e.printStackTrace(System.err); fail("Caught unexpected exception: " + e); } - + origAttrs.clear(); CryptoToken ctok2 = null; try { @@ -385,7 +385,7 @@ public final void testAddandGetAttributes() { } catch (EncryptionException e) { fail("Unexpected EncryptionException"); } - + try { ctok2.addAttributes(origAttrs); // Add (empty) attribute map } catch (ValidationException e) { diff --git a/src/test/java/org/owasp/esapi/crypto/ESAPICryptoMACByPassTest.java b/src/test/java/org/owasp/esapi/crypto/ESAPICryptoMACByPassTest.java index 863c573e7..a93ce6cfb 100644 --- a/src/test/java/org/owasp/esapi/crypto/ESAPICryptoMACByPassTest.java +++ b/src/test/java/org/owasp/esapi/crypto/ESAPICryptoMACByPassTest.java @@ -1,7 +1,7 @@ /* * OWASP Enterprise Security API (ESAPI) - Google issue # 306. * (i.e., GitHub issue 312). - * + * * 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. @@ -10,14 +10,14 @@ * ESAPI is published by OWASP under the new BSD license. You should read * and accept the LICENSE before you use, modify, and/or redistribute this * software. - * + * * Full credit for this JUnit to illustrate what is now Google Issue # 306 * goes to Philippe Arteau . Originally * published 2013/08/21 to ESAPI-DEV mailing list. Shows that both * ESAPI 2.0 and 2.0.1 is vulnerable. Minor tweaks by Kevin W. Wall. * * Original class name: SignatureByPassTest. - * + * * NOTE: If this test fails, your version of ESAPI is vulnerable (or you have * it configured not to require a MAC which you should NOT do). */ diff --git a/src/test/java/org/owasp/esapi/crypto/PlainTextTest.java b/src/test/java/org/owasp/esapi/crypto/PlainTextTest.java index 4e40c3225..3f65b2647 100644 --- a/src/test/java/org/owasp/esapi/crypto/PlainTextTest.java +++ b/src/test/java/org/owasp/esapi/crypto/PlainTextTest.java @@ -10,10 +10,10 @@ import org.owasp.esapi.crypto.PlainText; public class PlainTextTest { - + private String unicodeStr = "A\u00ea\u00f1\u00fcC"; // I.e., "AêñüC" private String altString = "AêñüC"; // Same as above. - + /* NOTE: This test will not work on Windows unless executed under * Eclipse and the file is stored / treated as a UTF-8 encoded file * rather than the Windows native OS encoding of Windows-1252 (aka, @@ -44,21 +44,21 @@ public final void testUnicodeString() { byte[] utf8Bytes = unicodeStr.getBytes("UTF-8"); PlainText pt1 = new PlainText(unicodeStr); PlainText pt2 = new PlainText(altString); - + assertTrue( pt1.equals(pt1) ); // Equals self assertFalse( pt1.equals(null) ); assertTrue( pt1.equals(pt2) ); assertFalse( pt1.equals( unicodeStr ) ); assertTrue( pt1.length() == utf8Bytes.length ); - assertTrue( Arrays.equals(utf8Bytes, pt1.asBytes()) ); + assertTrue( Arrays.equals(utf8Bytes, pt1.asBytes()) ); assertTrue( pt1.hashCode() == unicodeStr.hashCode() ); - + } catch (UnsupportedEncodingException e) { fail("No UTF-8 byte encoding: " + e); e.printStackTrace(System.err); } } - + @Test public final void testNullCase() { int counter = 0; @@ -87,9 +87,9 @@ public final void testOverwrite() { byte[] origBytes = unicodeStr.getBytes("UTF-8"); PlainText pt = new PlainText(origBytes); assertTrue( pt.toString().equals(unicodeStr) ); - assertTrue( Arrays.equals(origBytes, pt.asBytes()) ); + assertTrue( Arrays.equals(origBytes, pt.asBytes()) ); assertTrue( pt.hashCode() == unicodeStr.hashCode() ); - + int origLen = origBytes.length; pt.overwrite(); diff --git a/src/test/java/org/owasp/esapi/crypto/SecurityProviderLoaderTest.java b/src/test/java/org/owasp/esapi/crypto/SecurityProviderLoaderTest.java index 5db8aeb82..441b07bd9 100644 --- a/src/test/java/org/owasp/esapi/crypto/SecurityProviderLoaderTest.java +++ b/src/test/java/org/owasp/esapi/crypto/SecurityProviderLoaderTest.java @@ -32,7 +32,7 @@ public class SecurityProviderLoaderTest { private static boolean HAS_BOUNCY_CASTLE = false; - + @BeforeClass public static void setUpBeforeClass() { try { @@ -76,7 +76,7 @@ public final void testLoadESAPIPreferredJCEProvider() { preferredProvider + "; exception was: " + e); } } - + @Test(expected=NoSuchProviderException.class) public final void testNoSuchProviderException() throws NoSuchProviderException { SecurityProviderLoader.insertProviderAt("DrBobsSecretSnakeOilElixirCryptoJCE", 5); @@ -86,7 +86,7 @@ public final void testNoSuchProviderException() throws NoSuchProviderException { public final void testBogusProviderWithFQCN() throws NoSuchProviderException { SecurityProviderLoader.insertProviderAt("com.snakeoil.DrBobsSecretSnakeOilElixirCryptoJCE", 5); } - + @Test public final void testWithBouncyCastle() { if ( ! HAS_BOUNCY_CASTLE ) { @@ -101,7 +101,7 @@ public final void testWithBouncyCastle() { } catch (NoSuchProviderException e) { fail("Caught NoSuchProviderException trying to load Bouncy Castle; exception was: " + e); } - + // First encrypt w/ preferred cipher transformation (AES/CBC/PKCS5Padding). try { PlainText clearMsg = new PlainText("This is top secret! We are all out of towels!"); @@ -114,7 +114,7 @@ public final void testWithBouncyCastle() { fail("Encryption w/ Bouncy Castle failed with EncryptionException for preferred " + "cipher transformation; exception was: " + e); } - + // Next, try a "combined mode" cipher mode available in Bouncy Castle. String origCipherXform = null; try { diff --git a/src/test/java/org/owasp/esapi/errors/EnterpriseSecurityExceptionTest.java b/src/test/java/org/owasp/esapi/errors/EnterpriseSecurityExceptionTest.java index e42780251..a5a6de707 100644 --- a/src/test/java/org/owasp/esapi/errors/EnterpriseSecurityExceptionTest.java +++ b/src/test/java/org/owasp/esapi/errors/EnterpriseSecurityExceptionTest.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -39,14 +39,14 @@ /** * The Class AccessReferenceMapTest. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class EnterpriseSecurityExceptionTest extends TestCase { - + /** * Instantiates a new access reference map test. - * + * * @param testName * the test name */ @@ -72,7 +72,7 @@ protected void tearDown() throws Exception { /** * Suite. - * + * * @return the test */ public static Test suite() { @@ -80,10 +80,10 @@ public static Test suite() { return suite; } - + /** * Test of update method, of class org.owasp.esapi.AccessReferenceMap. - * + * */ public void testExceptions() { System.out.println("exceptions"); @@ -119,7 +119,7 @@ public void testExceptions() { e = new ValidationException("m1","m2",new Throwable()); e = new ValidationException("m1","m2","context"); e = new ValidationException("m1","m2",new Throwable(),"context"); - + e = new IntegrityException(); e = new IntegrityException("m1","m2"); e = new IntegrityException("m1","m2",new Throwable()); @@ -153,5 +153,5 @@ public void testExceptions() { assertEquals( ex.getUserMessage(), "m1" ); assertEquals( ex.getLogMessage(), "m2" ); } - + } diff --git a/src/test/java/org/owasp/esapi/filters/ClickjackFilterTest.java b/src/test/java/org/owasp/esapi/filters/ClickjackFilterTest.java index d88031c8d..369e3f881 100644 --- a/src/test/java/org/owasp/esapi/filters/ClickjackFilterTest.java +++ b/src/test/java/org/owasp/esapi/filters/ClickjackFilterTest.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -32,11 +32,11 @@ /** * The Class ClickjackFilterTest. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class ClickjackFilterTest extends TestCase { - + /** * @param testName * the test name @@ -63,7 +63,7 @@ protected void tearDown() throws Exception { /** * Suite. - * + * * @return the test */ public static Test suite() { @@ -71,7 +71,7 @@ public static Test suite() { return suite; } - + /** * Test of update method, of class org.owasp.esapi.AccessReferenceMap. * @throws Exception @@ -81,10 +81,10 @@ public void testFilter() throws Exception { Map map = new HashMap(); FilterConfig mfc = new MockFilterConfig( map ); - ClickjackFilter filter = new ClickjackFilter(); + ClickjackFilter filter = new ClickjackFilter(); filter.init( mfc ); MockHttpServletRequest request = new MockHttpServletRequest(); - + // the mock filter chain writes the requested URI to the response body MockFilterChain chain = new MockFilterChain(); diff --git a/src/test/java/org/owasp/esapi/filters/SafeRequestTest.java b/src/test/java/org/owasp/esapi/filters/SafeRequestTest.java index 24db938c7..11e45b651 100644 --- a/src/test/java/org/owasp/esapi/filters/SafeRequestTest.java +++ b/src/test/java/org/owasp/esapi/filters/SafeRequestTest.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -24,14 +24,14 @@ /** * The Class SafeRequestTest. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class SafeRequestTest extends TestCase { /** * Instantiates a new access controller test. - * + * * @param testName * the test name * @throws Exception @@ -59,7 +59,7 @@ protected void tearDown() throws Exception { /** * Suite. - * + * * @return the test */ public static Test suite() { @@ -98,7 +98,7 @@ public void testGetQueryStringNull() public void testGetParameterValuesReturnsNullWhenParameterDoesNotExistInRequest() { MockHttpServletRequest request = new MockHttpServletRequest(); request.clearParameters(); - + final String paramName = "nonExistentParameter"; assertNull(request.getParameterValues(paramName)); diff --git a/src/test/java/org/owasp/esapi/filters/SecurityWrapperRequestTest.java b/src/test/java/org/owasp/esapi/filters/SecurityWrapperRequestTest.java index e7ee596e0..40c9d36da 100644 --- a/src/test/java/org/owasp/esapi/filters/SecurityWrapperRequestTest.java +++ b/src/test/java/org/owasp/esapi/filters/SecurityWrapperRequestTest.java @@ -66,7 +66,7 @@ public class SecurityWrapperRequestTest { protected static final String SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME = "HttpUtilities.httpQueryParamValueLength"; private static final String SECURITY_CONFIGURATION_HEADER_NAME_LENGTH_KEY_NAME = "HttpUtilities.MaxHeaderNameSize"; private static final String SECURITY_CONFIGURATION_HEADER_VALUE_LENGTH_KEY_NAME = "HttpUtilities.MaxHeaderValueSize"; - + protected static final int SECURITY_CONFIGURATION_TEST_LENGTH = 255; private static final String QUERY_STRING_CANONCALIZE_TYPE_KEY = "HTTPQueryString"; @@ -75,7 +75,7 @@ public class SecurityWrapperRequestTest { private static final String COOKIE_VALUE_TYPE_KEY = "HTTPCookieValue"; private static final String COOKIE_DOMAIN_TYPE_KEY = "HTTPHeaderValue"; private static final String COOKIE_PATH_TYPE_KEY = "HTTPHeaderValue"; - + @Rule public TestName testName = new TestName(); @@ -87,7 +87,7 @@ public class SecurityWrapperRequestTest { private SecurityConfiguration mockSecConfig; @Mock private Logger mockLogger; - + private String testQueryValue; private String testParameterName; private String testParameterValue; @@ -101,19 +101,19 @@ public void setup() throws Exception { PowerMockito.when(ESAPI.class, ESAPI_VALIDATOR_GETTER_METHOD_NAME).thenReturn(mockValidator); PowerMockito.when(ESAPI.class, ESAPI_GET_LOGGER_METHOD_NAME, "SecurityWrapperRequest").thenReturn(mockLogger); PowerMockito.when(ESAPI.class, ESAPY_SECURITY_CONFIGURATION_GETTER_METHOD_NAME).thenReturn(mockSecConfig); - //Is intrusion detection disabled? A: Yes, it is off. + //Is intrusion detection disabled? A: Yes, it is off. //This logic is confusing: True, the value is False... Mockito.when( mockSecConfig.getBooleanProp( DISABLE_INTRUSION_DETECTION ) ).thenReturn(true); - + testQueryValue = testName.getMethodName() + "_query_value"; - + testParameterName = testName.getMethodName() + "_parameter_name"; - testParameterValue = testName.getMethodName() + "_parameter_value"; + testParameterValue = testName.getMethodName() + "_parameter_value"; testValueCanonical = testName.getMethodName() + "_value_canonical"; testValidatorType = testName.getMethodName() + "_validator_type"; testMaximumLength = testName.getMethodName().length(); } - + /** * Workflow test for happy-path getQueryString. Asserts delegation calls and parameters to delegate * behaviors. @@ -139,7 +139,7 @@ public void testGetQueryString() throws Exception { } /** - * Test for getQueryString when validation throws an Exception. + * Test for getQueryString when validation throws an Exception. *
      * Asserts delegation calls and parameters to delegate behaviors. */ @@ -160,7 +160,7 @@ public void testGetQueryStringCanonicalizeException() throws Exception { .isEmpty()); validatorTester.verify(testQueryValue, QUERY_STRING_CANONCALIZE_TYPE_KEY, SECURITY_CONFIGURATION_TEST_LENGTH, true); - + verify(mockSecConfig, times(1)).getIntProp(SECURITY_CONFIGURATION_QUERY_STRING_LENGTH_KEY_NAME); verify(mockRequest, times(1)).getQueryString(); } @@ -168,7 +168,7 @@ public void testGetQueryStringCanonicalizeException() throws Exception { public void testGetParameterString() throws Exception{ ValidatorTestContainer validatorTester = new ValidatorTestContainer(mockValidator); validatorTester.getValidInputReturns(testValueCanonical); - + PowerMockito.when(mockSecConfig.getIntProp(SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME)).thenReturn( SECURITY_CONFIGURATION_TEST_LENGTH); @@ -177,9 +177,9 @@ public void testGetParameterString() throws Exception{ SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); String rval = request.getParameter(testParameterName); assertEquals(testValueCanonical, rval); - + validatorTester.verify(testParameterValue, PARAMETER_STRING_CANONCALIZE_TYPE_KEY, SECURITY_CONFIGURATION_TEST_LENGTH, true); - + verify(mockSecConfig, times(1)).getIntProp(SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME); verify(mockRequest, times(1)).getParameter(testParameterName); } @@ -196,18 +196,18 @@ public void testGetParameterStringBoolean() throws Exception{ SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); String rval = request.getParameter(testParameterName, false); assertEquals(testValueCanonical, rval); - + validatorTester.verify(testParameterValue, PARAMETER_STRING_CANONCALIZE_TYPE_KEY, SECURITY_CONFIGURATION_TEST_LENGTH, false); - + verify(mockSecConfig, times(1)).getIntProp(SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME); verify(mockRequest, times(1)).getParameter(testParameterName); } - + @Test public void testGetParameterStringBooleanInt() throws Exception{ ValidatorTestContainer validatorTester = new ValidatorTestContainer(mockValidator); validatorTester.getValidInputReturns(testValueCanonical); - + PowerMockito.when(mockRequest.getParameter(testParameterName)).thenReturn(testParameterValue); SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); @@ -218,13 +218,13 @@ public void testGetParameterStringBooleanInt() throws Exception{ verify(mockRequest, times(1)).getParameter(testParameterName); } - + @Test public void testGetParameterStringBooleanIntString() throws Exception{ ValidatorTestContainer validatorTester = new ValidatorTestContainer(mockValidator); validatorTester.getValidInputReturns(testValueCanonical); - - + + PowerMockito.when(mockRequest.getParameter(testParameterName)).thenReturn(testParameterValue); SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); @@ -232,16 +232,16 @@ public void testGetParameterStringBooleanIntString() throws Exception{ assertEquals(testValueCanonical, rval); validatorTester.verify(testParameterValue, testValidatorType, testMaximumLength, false); - + verify(mockRequest, times(1)).getParameter(testParameterName); } - + @Test public void testGetParameterStringNullEvalPassthrough() throws Exception{ ValidatorTestContainer validatorTester = new ValidatorTestContainer(mockValidator); validatorTester.getValidInputReturns(null); - + PowerMockito.when(mockSecConfig.getIntProp(SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME)).thenReturn( SECURITY_CONFIGURATION_TEST_LENGTH); @@ -250,7 +250,7 @@ public void testGetParameterStringNullEvalPassthrough() throws Exception{ SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); String rval = request.getParameter(testParameterName); assertNull(rval); - + validatorTester.verify(testParameterValue, PARAMETER_STRING_CANONCALIZE_TYPE_KEY, SECURITY_CONFIGURATION_TEST_LENGTH, true); verify(mockSecConfig, times(1)).getIntProp(SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME); @@ -261,7 +261,7 @@ public void testGetParameterStringNullEvalPassthrough() throws Exception{ public void testGetParameterStringBooleanNullEvalPassthrough() throws Exception{ ValidatorTestContainer validatorTester = new ValidatorTestContainer(mockValidator); validatorTester.getValidInputReturns(null); - + PowerMockito.when(mockSecConfig.getIntProp(SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME)).thenReturn( SECURITY_CONFIGURATION_TEST_LENGTH); @@ -270,34 +270,34 @@ public void testGetParameterStringBooleanNullEvalPassthrough() throws Exception{ SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); String rval = request.getParameter(testParameterName, false); assertNull(rval); - + validatorTester.verify(testParameterValue, PARAMETER_STRING_CANONCALIZE_TYPE_KEY, SECURITY_CONFIGURATION_TEST_LENGTH, false); verify(mockSecConfig, times(1)).getIntProp(SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME); verify(mockRequest, times(1)).getParameter(testParameterName); } - + @Test public void testGetParameterStringBooleanIntNullEvalPassthrough() throws Exception{ ValidatorTestContainer validatorTester = new ValidatorTestContainer(mockValidator); validatorTester.getValidInputReturns(null); - + PowerMockito.when(mockRequest.getParameter(testParameterName)).thenReturn(testParameterValue); SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); String rval = request.getParameter(testParameterName, false, testMaximumLength); assertNull(rval); - + validatorTester.verify(testParameterValue, PARAMETER_STRING_CANONCALIZE_TYPE_KEY, testMaximumLength, false); verify(mockRequest, times(1)).getParameter(testParameterName); } - + @Test public void testGetParameterStringBooleanIntStringNullEvalPassthrough() throws Exception{ ValidatorTestContainer validatorTester = new ValidatorTestContainer(mockValidator); validatorTester.getValidInputReturns(null); - + PowerMockito.when(mockRequest.getParameter(testParameterName)).thenReturn(testParameterValue); SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); @@ -307,12 +307,12 @@ public void testGetParameterStringBooleanIntStringNullEvalPassthrough() throws E verify(mockRequest, times(1)).getParameter(testParameterName); } - + @Test public void testGetParameterStringNullOnException() throws Exception{ ValidatorTestContainer validatorTester = new ValidatorTestContainer(mockValidator); validatorTester.getValidInputThrows(); - + PowerMockito.when(mockSecConfig.getIntProp(SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME)).thenReturn( SECURITY_CONFIGURATION_TEST_LENGTH); @@ -323,18 +323,18 @@ public void testGetParameterStringNullOnException() throws Exception{ assertNull(rval); validatorTester.verify(testParameterValue, PARAMETER_STRING_CANONCALIZE_TYPE_KEY, SECURITY_CONFIGURATION_TEST_LENGTH, true); - + verify(mockSecConfig, times(1)).getIntProp(SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME); verify(mockRequest, times(1)).getParameter(testParameterName); } - - + + @Test public void testGetParameterStringBooleanNullOnException() throws Exception{ ValidatorTestContainer validatorTester = new ValidatorTestContainer(mockValidator); validatorTester.getValidInputThrows(); - + PowerMockito.when(mockSecConfig.getIntProp(SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME)).thenReturn( SECURITY_CONFIGURATION_TEST_LENGTH); @@ -343,28 +343,28 @@ public void testGetParameterStringBooleanNullOnException() throws Exception{ SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); String rval = request.getParameter(testParameterName, false); assertNull(rval); - + validatorTester.verify(testParameterValue, PARAMETER_STRING_CANONCALIZE_TYPE_KEY, SECURITY_CONFIGURATION_TEST_LENGTH, false); - + verify(mockSecConfig, times(1)).getIntProp(SECURITY_CONFIGURATION_PARAMETER_STRING_LENGTH_KEY_NAME); verify(mockRequest, times(1)).getParameter(testParameterName); } - + @Test public void testGetParameterStringBooleanIntNullOnException() throws Exception{ ValidatorTestContainer validatorTester = new ValidatorTestContainer(mockValidator); validatorTester.getValidInputThrows(); - + PowerMockito.when(mockRequest.getParameter(testParameterName)).thenReturn(testParameterValue); SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); String rval = request.getParameter(testParameterName, false, testMaximumLength); assertNull(rval); - + validatorTester.verify(testParameterValue, PARAMETER_STRING_CANONCALIZE_TYPE_KEY, testMaximumLength, false); verify(mockRequest, times(1)).getParameter(testParameterName); } - + @Test public void testGetParameterStringBooleanIntStringNullOnException() throws Exception{ ValidatorTestContainer validatorTester = new ValidatorTestContainer(mockValidator); @@ -375,12 +375,12 @@ public void testGetParameterStringBooleanIntStringNullOnException() throws Excep SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); String rval = request.getParameter(testParameterName, false, testMaximumLength, testValidatorType); assertNull(rval); - + validatorTester.verify(testParameterValue, testValidatorType, testMaximumLength, false); - + verify(mockRequest, times(1)).getParameter(testParameterName); } - + @Test public void testGetCookie() throws Exception { PowerMockito.when(mockSecConfig.getIntProp(SECURITY_CONFIGURATION_HEADER_NAME_LENGTH_KEY_NAME)).thenReturn( @@ -418,7 +418,7 @@ public void testGetCookie() throws Exception { Mockito.verify(mockValidator, times(1)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getDomain()), ArgumentMatchers.eq(COOKIE_DOMAIN_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); Mockito.verify(mockValidator, times(1)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getPath()), ArgumentMatchers.eq(COOKIE_PATH_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); } - + @Test public void testGetCookieNullDomainPath() throws Exception { PowerMockito.when(mockSecConfig.getIntProp(SECURITY_CONFIGURATION_HEADER_NAME_LENGTH_KEY_NAME)).thenReturn( @@ -441,7 +441,7 @@ public void testGetCookieNullDomainPath() throws Exception { assertNotEquals(stubCookies, cookies); assertEquals(1, cookies.length); Cookie resultCookie1 = cookies[0]; - + assertNotEquals(ck1, resultCookie1); assertEquals(ck1.getName(), resultCookie1.getName()); assertEquals(ck1.getValue(), resultCookie1.getValue()); @@ -454,7 +454,7 @@ public void testGetCookieNullDomainPath() throws Exception { Mockito.verify(mockValidator, times(0)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getDomain()), ArgumentMatchers.eq(COOKIE_DOMAIN_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); Mockito.verify(mockValidator, times(0)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getPath()), ArgumentMatchers.eq(COOKIE_PATH_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); } - + @Test public void testGetCookieNullRequestCookies() { PowerMockito.when(mockRequest.getParameter(testParameterName)).thenReturn(testParameterValue); @@ -463,7 +463,7 @@ public void testGetCookieNullRequestCookies() { Cookie[] cookies = request.getCookies(); assertEquals(0, cookies.length); } - + @Test public void testGetCookieSkipOnBadName() throws Exception { PowerMockito.when(mockSecConfig.getIntProp(SECURITY_CONFIGURATION_HEADER_NAME_LENGTH_KEY_NAME)).thenReturn( @@ -472,7 +472,7 @@ public void testGetCookieSkipOnBadName() throws Exception { SECURITY_CONFIGURATION_TEST_LENGTH); Answer exceptionAnswer = new ValidatorTestContainer(mockValidator).throwException(); - + Cookie ck1 = new Cookie(testName.getMethodName(), testName.getMethodName()+ "-VALUE"); ck1.setMaxAge(999); ck1.setDomain(testName.getMethodName() + "-DOMAIN"); @@ -480,7 +480,7 @@ public void testGetCookieSkipOnBadName() throws Exception { Cookie[] stubCookies = new Cookie[] {ck1}; PowerMockito.when(mockRequest.getCookies()).thenReturn(stubCookies); - + PowerMockito.when(mockValidator.getValidInput(anyString(), eq(ck1.getName()), eq(COOKIE_NAME_TYPE_KEY), eq(SECURITY_CONFIGURATION_TEST_LENGTH), eq(false))).thenAnswer(exceptionAnswer); SecurityWrapperRequest request = new SecurityWrapperRequest(mockRequest); @@ -492,10 +492,10 @@ public void testGetCookieSkipOnBadName() throws Exception { Mockito.verify(mockValidator, times(0)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getValue()), ArgumentMatchers.eq(COOKIE_VALUE_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(true)); Mockito.verify(mockValidator, times(0)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getDomain()), ArgumentMatchers.eq(COOKIE_DOMAIN_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); Mockito.verify(mockValidator, times(0)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getPath()), ArgumentMatchers.eq(COOKIE_PATH_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); - + //I would have liked to verify the logging occurred, but it's giving me trouble at this time. } - + @Test public void testGetCookieSkipOnBadValue() throws Exception { PowerMockito.when(mockSecConfig.getIntProp(SECURITY_CONFIGURATION_HEADER_NAME_LENGTH_KEY_NAME)).thenReturn( @@ -512,7 +512,7 @@ public void testGetCookieSkipOnBadValue() throws Exception { Cookie[] stubCookies = new Cookie[] {ck1}; PowerMockito.when(mockRequest.getCookies()).thenReturn(stubCookies); - + PowerMockito.when(mockValidator.getValidInput(anyString(), eq(ck1.getName()), eq(COOKIE_NAME_TYPE_KEY), eq(SECURITY_CONFIGURATION_TEST_LENGTH), eq(true))).thenReturn(ck1.getName()); PowerMockito.when(mockValidator.getValidInput(anyString(), eq(ck1.getValue()),eq(COOKIE_VALUE_TYPE_KEY), eq(SECURITY_CONFIGURATION_TEST_LENGTH), eq(true))).thenAnswer(exceptionAnswer); @@ -525,7 +525,7 @@ public void testGetCookieSkipOnBadValue() throws Exception { Mockito.verify(mockValidator, times(1)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getValue()), ArgumentMatchers.eq(COOKIE_VALUE_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(true)); Mockito.verify(mockValidator, times(0)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getDomain()), ArgumentMatchers.eq(COOKIE_DOMAIN_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); Mockito.verify(mockValidator, times(0)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getPath()), ArgumentMatchers.eq(COOKIE_PATH_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); - + //I would have liked to verify the logging occurred, but it's giving me trouble at this time. } @@ -537,7 +537,7 @@ public void testGetCookieSkipOnBadDomain() throws Exception { SECURITY_CONFIGURATION_TEST_LENGTH); Answer exceptionAnswer = new ValidatorTestContainer(mockValidator).throwException(); - + Cookie ck1 = new Cookie(testName.getMethodName(), testName.getMethodName()+ "-VALUE"); ck1.setMaxAge(999); ck1.setDomain(testName.getMethodName() + "-DOMAIN"); @@ -545,7 +545,7 @@ public void testGetCookieSkipOnBadDomain() throws Exception { Cookie[] stubCookies = new Cookie[] {ck1}; PowerMockito.when(mockRequest.getCookies()).thenReturn(stubCookies); - + PowerMockito.when(mockValidator.getValidInput(anyString(), eq(ck1.getName()), eq(COOKIE_NAME_TYPE_KEY), eq(SECURITY_CONFIGURATION_TEST_LENGTH), eq(false))).thenReturn(ck1.getName()); PowerMockito.when(mockValidator.getValidInput(anyString(), eq(ck1.getValue()),eq(COOKIE_VALUE_TYPE_KEY), eq(SECURITY_CONFIGURATION_TEST_LENGTH), eq(true))).thenReturn(ck1.getValue()); PowerMockito.when(mockValidator.getValidInput(anyString(), eq(ck1.getDomain()),eq(COOKIE_DOMAIN_TYPE_KEY), eq(SECURITY_CONFIGURATION_TEST_LENGTH), eq(false))).thenAnswer(exceptionAnswer); @@ -559,10 +559,10 @@ public void testGetCookieSkipOnBadDomain() throws Exception { Mockito.verify(mockValidator, times(1)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getValue()), ArgumentMatchers.eq(COOKIE_VALUE_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(true)); Mockito.verify(mockValidator, times(1)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getDomain()), ArgumentMatchers.eq(COOKIE_DOMAIN_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); Mockito.verify(mockValidator, times(0)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getPath()), ArgumentMatchers.eq(COOKIE_PATH_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); - + //I would have liked to verify the logging occurred, but it's giving me trouble at this time. } - + @Test public void testGetCookieSkipOnBadPath() throws Exception { @@ -572,7 +572,7 @@ public void testGetCookieSkipOnBadPath() throws Exception { SECURITY_CONFIGURATION_TEST_LENGTH); Answer exceptionAnswer = new ValidatorTestContainer(mockValidator).throwException(); - + Cookie ck1 = new Cookie(testName.getMethodName(), testName.getMethodName()+ "-VALUE"); ck1.setMaxAge(999); ck1.setDomain(testName.getMethodName() + "-DOMAIN"); @@ -580,7 +580,7 @@ public void testGetCookieSkipOnBadPath() throws Exception { Cookie[] stubCookies = new Cookie[] {ck1}; PowerMockito.when(mockRequest.getCookies()).thenReturn(stubCookies); - + PowerMockito.when(mockValidator.getValidInput(anyString(), eq(ck1.getName()), eq(COOKIE_NAME_TYPE_KEY), eq(SECURITY_CONFIGURATION_TEST_LENGTH), eq(false))).thenReturn(ck1.getName()); PowerMockito.when(mockValidator.getValidInput(anyString(), eq(ck1.getValue()),eq(COOKIE_VALUE_TYPE_KEY), eq(SECURITY_CONFIGURATION_TEST_LENGTH), eq(true))).thenReturn(ck1.getValue()); PowerMockito.when(mockValidator.getValidInput(anyString(), eq(ck1.getDomain()),eq(COOKIE_DOMAIN_TYPE_KEY), eq(SECURITY_CONFIGURATION_TEST_LENGTH), eq(false))).thenReturn(ck1.getDomain()); @@ -595,7 +595,7 @@ public void testGetCookieSkipOnBadPath() throws Exception { Mockito.verify(mockValidator, times(1)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getValue()), ArgumentMatchers.eq(COOKIE_VALUE_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(true)); Mockito.verify(mockValidator, times(1)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getDomain()), ArgumentMatchers.eq(COOKIE_DOMAIN_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); Mockito.verify(mockValidator, times(1)).getValidInput(anyString(), ArgumentMatchers.eq(ck1.getPath()), ArgumentMatchers.eq(COOKIE_PATH_TYPE_KEY), ArgumentMatchers.eq(SECURITY_CONFIGURATION_TEST_LENGTH), ArgumentMatchers.eq(false)); - + //I would have liked to verify the logging occurred, but it's giving me trouble at this time. } @@ -610,8 +610,8 @@ private class ValidatorTestContainer { private ArgumentCaptor lengthCapture = ArgumentCaptor.forClass(Integer.class); private ArgumentCaptor allowNullCapture = ArgumentCaptor.forClass(Boolean.class); private Validator validator; - - + + public ValidatorTestContainer(Validator validatorRef) { this.validator = validatorRef; } @@ -623,7 +623,7 @@ public String answer(InvocationOnMock invocation) throws Throwable { } }; } - + public Answer returnResult(final String result) { return new Answer() { @Override @@ -635,11 +635,11 @@ public String answer(InvocationOnMock invocation) throws Throwable { public void getValidInputReturns(String response) throws Exception { setupFor(returnResult(response)); } - + public void getValidInputThrows() throws Exception { setupFor(throwException()); } - + public void setupFor(Answer answer) throws Exception { String context = anyString(); String input = inputCapture.capture(); @@ -649,7 +649,7 @@ public void setupFor(Answer answer) throws Exception { PowerMockito.when(validator.getValidInput(context, input, type, length, allowNull)).thenAnswer(answer); } - + public void verify(String input, String type, int maxLen, boolean allowNull) throws Exception { String actualInput = inputCapture.getValue(); String actualType = typeCapture.getValue(); @@ -660,7 +660,7 @@ public void verify(String input, String type, int maxLen, boolean allowNull) thr assertEquals(type, actualType); assertTrue(maxLen == actualLength); assertEquals(allowNull, actualAllowNull); - + Mockito.verify(validator, times(1)).getValidInput(anyString(), ArgumentMatchers.eq(input), ArgumentMatchers.eq(type), ArgumentMatchers.eq(maxLen), ArgumentMatchers.eq(allowNull)); } } diff --git a/src/test/java/org/owasp/esapi/filters/SecurityWrapperResponseTest.java b/src/test/java/org/owasp/esapi/filters/SecurityWrapperResponseTest.java index 951a57e5b..f7b74c6f1 100644 --- a/src/test/java/org/owasp/esapi/filters/SecurityWrapperResponseTest.java +++ b/src/test/java/org/owasp/esapi/filters/SecurityWrapperResponseTest.java @@ -66,7 +66,7 @@ public void setup() throws Exception { PowerMockito.when(ESAPI.class, SecurityWrapperRequestTest.ESAPI_VALIDATOR_GETTER_METHOD_NAME).thenReturn(mockValidator); PowerMockito.when(ESAPI.class, SecurityWrapperRequestTest.ESAPI_GET_LOGGER_METHOD_NAME, "SecurityWrapperResponse").thenReturn(mockLogger); PowerMockito.when(ESAPI.class, SecurityWrapperRequestTest.ESAPY_SECURITY_CONFIGURATION_GETTER_METHOD_NAME).thenReturn(mockSecConfig); - //Is intrusion detection disabled? A: Yes, it is off. + //Is intrusion detection disabled? A: Yes, it is off. //This logic is confusing: True, the value is False... Mockito.when( mockSecConfig.getBooleanProp( DISABLE_INTRUSION_DETECTION ) ).thenReturn(true); @@ -104,7 +104,7 @@ public void testSetHeaderHappyPath() throws Exception { verify(mockSecConfig, times(1)).getIntProp(SEC_CTX_MAX_HEADER_NAME_SIZE_ATTR); verify(mockSecConfig, times(1)).getIntProp(SEC_CTX_MAX_HEADER_VALUE_SIZE_ATTR); verify(mockResponse, times(1)).setHeader(validateNameResponse, validateValueResponse); - verify(mockLogger,times(0)).warning(ArgumentMatchers.any(org.owasp.esapi.Logger.EventType.class), anyString(), ArgumentMatchers.any(Exception.class)); + verify(mockLogger,times(0)).warning(ArgumentMatchers.any(org.owasp.esapi.Logger.EventType.class), anyString(), ArgumentMatchers.any(Exception.class)); } @Test @@ -261,7 +261,7 @@ public void testSetHeaderValueNull() throws Exception { verify(mockSecConfig, times(1)).getIntProp(SEC_CTX_MAX_HEADER_VALUE_SIZE_ATTR); verify(mockResponse, times(0)).setHeader(anyString(), anyString()); verify(mockLogger, times(0)).warning(ArgumentMatchers.any(org.owasp.esapi.Logger.EventType.class),anyString(), - ArgumentMatchers.any(Exception.class)); + ArgumentMatchers.any(Exception.class)); } @Test @@ -300,7 +300,7 @@ public void testSetHeaderValueEmpty() throws Exception { verify(mockSecConfig, times(1)).getIntProp(SEC_CTX_MAX_HEADER_VALUE_SIZE_ATTR); verify(mockResponse, times(0)).setHeader(anyString(), anyString()); verify(mockLogger, times(0)).warning(ArgumentMatchers.any(org.owasp.esapi.Logger.EventType.class),anyString(), - ArgumentMatchers.any(Exception.class)); + ArgumentMatchers.any(Exception.class)); } @Test @@ -372,7 +372,7 @@ public void testAddHeaderHappyPath() throws Exception { verify(mockSecConfig, times(1)).getIntProp(SEC_CTX_MAX_HEADER_NAME_SIZE_ATTR); verify(mockSecConfig, times(1)).getIntProp(SEC_CTX_MAX_HEADER_VALUE_SIZE_ATTR); verify(mockResponse, times(1)).addHeader(validateNameResponse, validateValueResponse); - verify(mockLogger,times(0)).warning(ArgumentMatchers.any(org.owasp.esapi.Logger.EventType.class), anyString(), ArgumentMatchers.any(Exception.class)); + verify(mockLogger,times(0)).warning(ArgumentMatchers.any(org.owasp.esapi.Logger.EventType.class), anyString(), ArgumentMatchers.any(Exception.class)); } @Test @@ -529,7 +529,7 @@ public void testAddHeaderValueNull() throws Exception { verify(mockSecConfig, times(1)).getIntProp(SEC_CTX_MAX_HEADER_VALUE_SIZE_ATTR); verify(mockResponse, times(0)).addHeader(anyString(), anyString()); verify(mockLogger, times(0)).warning(ArgumentMatchers.any(org.owasp.esapi.Logger.EventType.class),anyString(), - ArgumentMatchers.any(Exception.class)); + ArgumentMatchers.any(Exception.class)); } @Test @@ -568,7 +568,7 @@ public void testAddHeaderValueEmpty() throws Exception { verify(mockSecConfig, times(1)).getIntProp(SEC_CTX_MAX_HEADER_VALUE_SIZE_ATTR); verify(mockResponse, times(0)).addHeader(anyString(), anyString()); verify(mockLogger, times(0)).warning(ArgumentMatchers.any(org.owasp.esapi.Logger.EventType.class),anyString(), - ArgumentMatchers.any(Exception.class)); + ArgumentMatchers.any(Exception.class)); } @Test @@ -665,7 +665,7 @@ public void testInvalidDateHeader(){ @Test public void testAddHeaderInvalidValueLength(){ - //refactor this to use a spy. + //refactor this to use a spy. HttpServletResponse servResp = mock(HttpServletResponse.class); SecurityWrapperResponse resp = new SecurityWrapperResponse(servResp); SecurityWrapperResponse spyResp = spy(resp); @@ -722,9 +722,9 @@ public void testAddValidCookie(){ /* * We're indirectly testing our class. Since it ultimately - * delegates to HttpServletResponse.addHeader, we're actually + * delegates to HttpServletResponse.addHeader, we're actually * validating that our test method constructs a header with the - * expected properties. This implicitly tests the + * expected properties. This implicitly tests the * createCookieHeader method as well. */ verify(servResp, times(1)).addHeader("Set-Cookie", "Foo=aaaaaaaaaa; Max-Age=5000; Secure; HttpOnly"); diff --git a/src/test/java/org/owasp/esapi/http/MockFilterChain.java b/src/test/java/org/owasp/esapi/http/MockFilterChain.java index d9427a471..c00927e35 100644 --- a/src/test/java/org/owasp/esapi/http/MockFilterChain.java +++ b/src/test/java/org/owasp/esapi/http/MockFilterChain.java @@ -1,15 +1,15 @@ /** * 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 */ diff --git a/src/test/java/org/owasp/esapi/http/MockFilterConfig.java b/src/test/java/org/owasp/esapi/http/MockFilterConfig.java index 77ef982f2..7f350f977 100644 --- a/src/test/java/org/owasp/esapi/http/MockFilterConfig.java +++ b/src/test/java/org/owasp/esapi/http/MockFilterConfig.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -32,7 +32,7 @@ public class MockFilterConfig implements FilterConfig { public MockFilterConfig( Map map ) { this.map = map; } - + public String getFilterName() { return "mock"; } diff --git a/src/test/java/org/owasp/esapi/http/MockHttpServletRequest.java b/src/test/java/org/owasp/esapi/http/MockHttpServletRequest.java index a7128e661..d64b00598 100644 --- a/src/test/java/org/owasp/esapi/http/MockHttpServletRequest.java +++ b/src/test/java/org/owasp/esapi/http/MockHttpServletRequest.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -51,7 +51,7 @@ /** * The Class MockHttpServletRequest. - * + * * @author jwilliams */ public class MockHttpServletRequest implements HttpServletRequest @@ -114,7 +114,7 @@ public String getContextPath() { /** * Adds the parameter. - * + * * @param name the name * @param value the value */ @@ -131,7 +131,7 @@ public void addParameter(String name, String value) { /** * removeParameter removes the parameter name from the parameters map if it exists - * + * * @param name * parameter name to be removed */ @@ -141,7 +141,7 @@ public void removeParameter( String name ) { /** * Adds the header. - * + * * @param name the name * @param value the value */ @@ -172,7 +172,7 @@ public void setHeader(String name, String value) /** * Sets the cookies. - * + * * @param list the new cookies */ public void setCookies(ArrayList list) { @@ -214,7 +214,7 @@ public long getDateHeader(String name) { /** * {@inheritDoc} - * @param name + * @param name * @return The requested header value. */ public String getHeader(String name) { diff --git a/src/test/java/org/owasp/esapi/http/MockHttpServletResponse.java b/src/test/java/org/owasp/esapi/http/MockHttpServletResponse.java index 884c272ea..fadfe13f6 100644 --- a/src/test/java/org/owasp/esapi/http/MockHttpServletResponse.java +++ b/src/test/java/org/owasp/esapi/http/MockHttpServletResponse.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -32,7 +32,7 @@ /** * The Class MockHttpServletResponse. - * + * * @author jwilliams */ public class MockHttpServletResponse implements HttpServletResponse { @@ -56,7 +56,7 @@ public class MockHttpServletResponse implements HttpServletResponse { public String getBody() { return body.toString(); } - + /** * {@inheritDoc} */ @@ -123,7 +123,7 @@ public String getHeader(String name) { /** * Gets the header names. - * + * * @return the header names */ public List getHeaderNames() { @@ -220,7 +220,7 @@ public void setStatus(int sc) { /** * Gets the status. - * + * * @return the status */ public int getStatus() { @@ -329,7 +329,7 @@ public void resetBuffer() { public void setBody( String value ) { body = new StringBuffer( value ); } - + /** * {@inheritDoc} */ @@ -385,5 +385,5 @@ public Collection getHeaders(String string) { public void setContentLengthLong(long len) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } - + } diff --git a/src/test/java/org/owasp/esapi/http/MockHttpSession.java b/src/test/java/org/owasp/esapi/http/MockHttpSession.java index ab3af4247..ef716fee2 100644 --- a/src/test/java/org/owasp/esapi/http/MockHttpSession.java +++ b/src/test/java/org/owasp/esapi/http/MockHttpSession.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -26,39 +26,39 @@ /** * The Class MockHttpSession. - * + * * @author jwilliams */ public class MockHttpSession implements HttpSession { /** The invalidated. */ boolean invalidated = false; - + /** The creation time. */ private long creationTime=new Date().getTime(); - + /** The accessed time. */ private long accessedTime=new Date().getTime(); - + /** The count. */ private static int count = 1; - + /** The sessionid. */ private int sessionid=count++; - + /** The attributes. */ private Map attributes = new HashMap(); - + /** * Instantiates a new test HTTP session. */ public MockHttpSession() { // to replace synthetic accessor method } - + /** * Instantiates a new test http session. - * + * * @param creationTime * the creation time * @param accessedTime @@ -100,7 +100,7 @@ public String getId() { /** * Gets the invalidated. - * + * * @return the invalidated */ public boolean getInvalidated() { @@ -163,7 +163,7 @@ public String[] getValueNames() { public void invalidate() { invalidated = true; } - + /** * {@inheritDoc} */ @@ -209,7 +209,7 @@ public void setAttribute(String string, Object object) { public void setMaxInactiveInterval(int i) { // stub } - + /** * * @param time @@ -218,7 +218,7 @@ public void setAccessedTime( long time ) { this.accessedTime = time; } - + /** * * @param time diff --git a/src/test/java/org/owasp/esapi/http/MockRequestDispatcher.java b/src/test/java/org/owasp/esapi/http/MockRequestDispatcher.java index 66f53cc58..d0117ce8d 100644 --- a/src/test/java/org/owasp/esapi/http/MockRequestDispatcher.java +++ b/src/test/java/org/owasp/esapi/http/MockRequestDispatcher.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -38,7 +38,7 @@ public class MockRequestDispatcher implements RequestDispatcher { public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException { System.out.println( "Forwarding" ); } - + /** * * @param request diff --git a/src/test/java/org/owasp/esapi/http/MockServletContext.java b/src/test/java/org/owasp/esapi/http/MockServletContext.java index f230f77f2..062577090 100644 --- a/src/test/java/org/owasp/esapi/http/MockServletContext.java +++ b/src/test/java/org/owasp/esapi/http/MockServletContext.java @@ -1,15 +1,15 @@ /** * 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 */ diff --git a/src/test/java/org/owasp/esapi/http/MockServletInputStream.java b/src/test/java/org/owasp/esapi/http/MockServletInputStream.java index ea6e6fa14..f54b49144 100644 --- a/src/test/java/org/owasp/esapi/http/MockServletInputStream.java +++ b/src/test/java/org/owasp/esapi/http/MockServletInputStream.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -40,7 +40,7 @@ public MockServletInputStream(byte[] body) { /** * read - * @return the next char from this InputStream + * @return the next char from this InputStream * @throws IOException */ public int read() throws IOException { diff --git a/src/test/java/org/owasp/esapi/logging/appender/ClientInfoSupplierTest.java b/src/test/java/org/owasp/esapi/logging/appender/ClientInfoSupplierTest.java index 53c622b0d..e3dcd76a5 100644 --- a/src/test/java/org/owasp/esapi/logging/appender/ClientInfoSupplierTest.java +++ b/src/test/java/org/owasp/esapi/logging/appender/ClientInfoSupplierTest.java @@ -31,138 +31,138 @@ @PowerMockIgnore("javax.security.*") //Required since User extends javax.security.Principal public class ClientInfoSupplierTest { private static final String ESAPI_SESSION_ATTR = "ESAPI_SESSION"; - + @Rule public TestName testName = new TestName(); - + private HttpServletRequest mockRequest; private HttpSession mockSession; private Authenticator mockAuth; private Randomizer mockRand; private User mockUser; - + @Before public void before() throws Exception { - mockAuth =mock(Authenticator.class); - mockRand =mock(Randomizer.class); + mockAuth =mock(Authenticator.class); + mockRand =mock(Randomizer.class); mockRequest =mock(HttpServletRequest.class); mockSession =mock(HttpSession.class); mockUser =mock(User.class); - + mockStatic(ESAPI.class); when(ESAPI.class, "currentRequest").thenReturn(mockRequest); when(ESAPI.class, "authenticator").thenReturn(mockAuth); when(ESAPI.class, "randomizer").thenReturn(mockRand); - + when(mockRequest.getSession(false)).thenReturn(mockSession); when(mockSession.getAttribute(ESAPI_SESSION_ATTR)).thenReturn(testName.getMethodName()+ "-SESSION"); - + //Session value generation when(mockRand.getRandomInteger(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())).thenReturn(55555); - + when(mockUser.getLastHostAddress()).thenReturn(testName.getMethodName() + "-HOST_ADDR"); - - + + when(mockAuth.getCurrentUser()).thenReturn(mockUser); } - + @Test public void testHappyPath() throws Exception { ClientInfoSupplier cis = new ClientInfoSupplier(); cis.setLogClientInfo(true); String result = cis.get(); - + assertEquals(testName.getMethodName() + "-SESSION@"+testName.getMethodName() + "-HOST_ADDR", result); - + verify(mockAuth,times(1)).getCurrentUser(); verify(mockRequest,times(1)).getSession(false); verify(mockSession,times(1)).getAttribute(ESAPI_SESSION_ATTR); verify(mockUser,times(1)).getLastHostAddress(); - + verifyNoMoreInteractions(mockAuth, mockRand, mockRequest, mockSession, mockUser); } - + @Test public void testLogUserOff() { ClientInfoSupplier cis = new ClientInfoSupplier(); cis.setLogClientInfo(false); String result = cis.get(); - + assertTrue(result.isEmpty()); - + verifyNoMoreInteractions(mockAuth, mockRand, mockRequest, mockSession, mockUser); } - + @Test public void testLogUserNull() { when(mockAuth.getCurrentUser()).thenReturn(null); ClientInfoSupplier cis = new ClientInfoSupplier(); cis.setLogClientInfo(true); String result = cis.get(); - + assertEquals(testName.getMethodName()+ "-SESSION@#UNKNOWN_HOST#", result); - + verify(mockAuth,times(1)).getCurrentUser(); verify(mockRequest,times(1)).getSession(false); verify(mockSession,times(1)).getAttribute(ESAPI_SESSION_ATTR); - + verifyNoMoreInteractions(mockAuth, mockRand, mockRequest, mockSession, mockUser); } - + @Test public void testNullRequest() throws Exception { when(ESAPI.class, "currentRequest").thenReturn(null); ClientInfoSupplier cis = new ClientInfoSupplier(); cis.setLogClientInfo(true); String result = cis.get(); - - //sid is empty when request is null + + //sid is empty when request is null assertEquals("@"+testName.getMethodName() + "-HOST_ADDR", result); - + verify(mockAuth,times(1)).getCurrentUser(); verify(mockUser,times(1)).getLastHostAddress(); - + verifyNoMoreInteractions(mockAuth, mockRand, mockRequest, mockSession, mockUser); } - + @Test public void testNullSession() throws Exception { when(mockRequest.getSession(false)).thenReturn(null); ClientInfoSupplier cis = new ClientInfoSupplier(); cis.setLogClientInfo(true); String result = cis.get(); - - //sid is empty when session is null + + //sid is empty when session is null assertEquals("@"+testName.getMethodName() + "-HOST_ADDR", result); - - + + verify(mockAuth,times(1)).getCurrentUser(); verify(mockRequest,times(1)).getSession(false); verify(mockUser,times(1)).getLastHostAddress(); - - + + verifyNoMoreInteractions(mockAuth, mockRand, mockRequest, mockSession, mockUser); } - - - + + + @Test public void testNullEsapiSession() throws Exception { when(mockSession.getAttribute(ESAPI_SESSION_ATTR)).thenReturn(null); ClientInfoSupplier cis = new ClientInfoSupplier(); cis.setLogClientInfo(true); String result = cis.get(); - - //sid is empty when session is null + + //sid is empty when session is null assertEquals("55555@"+testName.getMethodName() + "-HOST_ADDR", result); - + verify(mockAuth,times(1)).getCurrentUser(); verify(mockRequest,times(1)).getSession(false); verify(mockSession,times(1)).getAttribute(ESAPI_SESSION_ATTR); verify(mockSession, times(1)).setAttribute(ESAPI_SESSION_ATTR, (""+55555)); verify(mockRand, times(1)).getRandomInteger(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()); verify(mockUser,times(1)).getLastHostAddress(); - + verifyNoMoreInteractions(mockAuth, mockRand, mockRequest, mockSession, mockUser); } } \ No newline at end of file diff --git a/src/test/java/org/owasp/esapi/logging/appender/EventTypeLogSupplierTest.java b/src/test/java/org/owasp/esapi/logging/appender/EventTypeLogSupplierTest.java index 44aeaff70..f547ce61c 100644 --- a/src/test/java/org/owasp/esapi/logging/appender/EventTypeLogSupplierTest.java +++ b/src/test/java/org/owasp/esapi/logging/appender/EventTypeLogSupplierTest.java @@ -26,13 +26,13 @@ public static Collection assembleTests() { paramSets.add(new Object[] {Logger.SECURITY_FAILURE,Logger.SECURITY_FAILURE.toString()}); paramSets.add(new Object[] {Logger.SECURITY_SUCCESS,Logger.SECURITY_SUCCESS.toString()}); paramSets.add(new Object[] {null, Logger.EVENT_UNSPECIFIED.toString()}); - + return paramSets; } - + private final EventType eventType; private final String expectedResult; - + public EventTypeLogSupplierTest(EventType eventType, String result) { this.eventType = eventType; this.expectedResult = result; @@ -42,5 +42,5 @@ public void testEventTypeLog() { EventTypeLogSupplier supplier = new EventTypeLogSupplier(eventType); assertEquals(expectedResult, supplier.get()); } - + } diff --git a/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java b/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java index 186d69648..bc733ec2e 100644 --- a/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java +++ b/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java @@ -29,7 +29,7 @@ public class LogPrefixAppenderTest { @Rule public TestName testName = new TestName(); - + private String testLoggerName = testName.getMethodName() + "-LOGGER"; private String testLogMessage = testName.getMethodName() + "-MESSAGE"; private String testApplicationName = testName.getMethodName() + "-APPLICATION_NAME"; @@ -46,7 +46,7 @@ public void buildSupplierSpies() { uisSpy = spy(new UserInfoSupplier()); cisSpy = spy(new ClientInfoSupplier()); sisSpy = spy(new ServerInfoSupplier(testName.getMethodName())); - + testLoggerName = testName.getMethodName() + "-LOGGER"; testLogMessage = testName.getMethodName() + "-MESSAGE"; testApplicationName = testName.getMethodName() + "-APPLICATION_NAME"; @@ -71,7 +71,7 @@ public void testCtrArgTruePassthroughToDelegates() throws Exception { verify(sisSpy, times(1)).setLogServerIp(true); verify(sisSpy, times(1)).setLogApplicationName(true, testApplicationName); } - + @Test public void testCtrArgFalsePassthroughToDelegates() throws Exception { when(etlsSpy.get()).thenReturn(ETL_RESULT); @@ -92,7 +92,7 @@ public void testCtrArgFalsePassthroughToDelegates() throws Exception { verify(sisSpy, times(1)).setLogServerIp(false); verify(sisSpy, times(1)).setLogApplicationName(false, null); } - + @Test public void testDelegateCtrArgs() throws Exception { ArgumentCaptor eventTypeCapture = ArgumentCaptor.forClass(EventType.class); @@ -119,7 +119,7 @@ public void testLogContentWhenClientInfoEmpty() throws Exception { public void testLogContentWhenUserInfoEmpty() throws Exception { runTest(ETL_RESULT, EMPTY_RESULT, CIS_RESULT,SIS_RESULT, "[EVENT_TYPE CLIENT_INFO -> SERVER_INFO]"); } - + @Test public void testLogContentWhenClientInfoEmptyAndServerInfoEmpty() throws Exception { runTest(ETL_RESULT, UIS_RESULT, EMPTY_RESULT,EMPTY_RESULT, "[EVENT_TYPE USER_INFO]"); @@ -139,7 +139,7 @@ public void testLogContentWhenUserInfoAndClientInfoEmpty() throws Exception { public void testLogContentWhenServerInfoEmpty() throws Exception { runTest(ETL_RESULT, UIS_RESULT, CIS_RESULT, EMPTY_RESULT, "[EVENT_TYPE USER_INFO:CLIENT_INFO]"); } - + @Test public void testLogContentWhenUserInfoEmptyAndClientInfoEmptyAndServerInfoEmpty() throws Exception { runTest(ETL_RESULT, EMPTY_RESULT, EMPTY_RESULT, EMPTY_RESULT, "[EVENT_TYPE]"); @@ -160,7 +160,7 @@ private void runTest(String typeResult, String userResult, String clientResult, //Since everything is mocked these booleans don't much matter aside from the later verifies LogPrefixAppender lpa = new LogPrefixAppender(false, false, false, false, null); String result = lpa.appendTo(testLoggerName, testEventType, testLogMessage); - + assertEquals(exResult + " " + testName.getMethodName() + "-MESSAGE", result); } } diff --git a/src/test/java/org/owasp/esapi/logging/appender/UserInfoSupplierTest.java b/src/test/java/org/owasp/esapi/logging/appender/UserInfoSupplierTest.java index db86bb0ff..f873816f0 100644 --- a/src/test/java/org/owasp/esapi/logging/appender/UserInfoSupplierTest.java +++ b/src/test/java/org/owasp/esapi/logging/appender/UserInfoSupplierTest.java @@ -31,65 +31,65 @@ @PowerMockIgnore("javax.security.*") //Required since User extends javax.security.Principal public class UserInfoSupplierTest { private static final String ESAPI_SESSION_ATTR = "ESAPI_SESSION"; - + @Rule public TestName testName = new TestName(); - + private Authenticator mockAuth; private User mockUser; - + @Before public void before() throws Exception { - mockAuth =mock(Authenticator.class); + mockAuth =mock(Authenticator.class); mockUser =mock(User.class); - + mockStatic(ESAPI.class); when(ESAPI.class, "authenticator").thenReturn(mockAuth); - + when(mockUser.getAccountName()).thenReturn(testName.getMethodName() + "-USER"); - - + + when(mockAuth.getCurrentUser()).thenReturn(mockUser); } - + @Test public void testHappyPath() throws Exception { UserInfoSupplier uis = new UserInfoSupplier(); uis.setLogUserInfo(true); String result = uis.get(); - + assertEquals(testName.getMethodName() + "-USER", result); - + verify(mockAuth,times(1)).getCurrentUser(); verify(mockUser,times(1)).getAccountName(); - + verifyNoMoreInteractions(mockAuth, mockUser); } - + @Test public void testLogUserOff() { UserInfoSupplier uis = new UserInfoSupplier(); uis.setLogUserInfo(false); String result = uis.get(); - + assertTrue(result.isEmpty()); verify(mockAuth,times(1)).getCurrentUser(); - + verifyNoMoreInteractions(mockAuth, mockUser); } - + @Test public void testLogUserNull() { when(mockAuth.getCurrentUser()).thenReturn(null); UserInfoSupplier uis = new UserInfoSupplier(); uis.setLogUserInfo(true); String result = uis.get(); - + assertEquals("#ANONYMOUS#", result); - + verify(mockAuth,times(1)).getCurrentUser(); - + verifyNoMoreInteractions(mockAuth, mockUser); } - + } \ No newline at end of file diff --git a/src/test/java/org/owasp/esapi/logging/cleaning/CodecLogScrubberTest.java b/src/test/java/org/owasp/esapi/logging/cleaning/CodecLogScrubberTest.java index 684bab71a..8ca742673 100644 --- a/src/test/java/org/owasp/esapi/logging/cleaning/CodecLogScrubberTest.java +++ b/src/test/java/org/owasp/esapi/logging/cleaning/CodecLogScrubberTest.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.cleaning; diff --git a/src/test/java/org/owasp/esapi/logging/cleaning/CompositeLogScrubberTest.java b/src/test/java/org/owasp/esapi/logging/cleaning/CompositeLogScrubberTest.java index bd694d2d3..fa11554b4 100644 --- a/src/test/java/org/owasp/esapi/logging/cleaning/CompositeLogScrubberTest.java +++ b/src/test/java/org/owasp/esapi/logging/cleaning/CompositeLogScrubberTest.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.cleaning; diff --git a/src/test/java/org/owasp/esapi/logging/cleaning/NewlineLogScrubberTest.java b/src/test/java/org/owasp/esapi/logging/cleaning/NewlineLogScrubberTest.java index b4c600dfc..810f3f210 100644 --- a/src/test/java/org/owasp/esapi/logging/cleaning/NewlineLogScrubberTest.java +++ b/src/test/java/org/owasp/esapi/logging/cleaning/NewlineLogScrubberTest.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.cleaning; diff --git a/src/test/java/org/owasp/esapi/logging/java/JavaLogBridgeImplTest.java b/src/test/java/org/owasp/esapi/logging/java/JavaLogBridgeImplTest.java index 3b7e4ebc5..1cce4bdb9 100644 --- a/src/test/java/org/owasp/esapi/logging/java/JavaLogBridgeImplTest.java +++ b/src/test/java/org/owasp/esapi/logging/java/JavaLogBridgeImplTest.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ package org.owasp.esapi.logging.java; diff --git a/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java b/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java index 2cdcdcc43..01319f377 100644 --- a/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java +++ b/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ package org.owasp.esapi.logging.java; @@ -44,7 +44,7 @@ public class JavaLogFactoryTest { @Rule public TestName testName = new TestName(); - + @Rule public ExpectedException exEx = ExpectedException.none(); @@ -61,7 +61,7 @@ public void readConfiguration(InputStream ins) throws IOException, SecurityExcep exEx.expectMessage("Failed to load esapi-java-logging.properties"); exEx.expect(ConfigurationException.class); - + exEx.expectCause(new CustomMatcher("Check for IOException") { @Override public boolean matches(Object item) { @@ -134,7 +134,7 @@ public void checkPassthroughAppenderConstruct() throws Exception { Assert.assertTrue(clientInfoCapture.getValue()); Assert.assertFalse(serverInfoCapture.getValue()); Assert.assertTrue(logAppNameCapture.getValue()); - Assert.assertEquals(testName.getMethodName(), appNameCapture.getValue()); + Assert.assertEquals(testName.getMethodName(), appNameCapture.getValue()); } diff --git a/src/test/java/org/owasp/esapi/logging/java/JavaLogLevelHandlersTest.java b/src/test/java/org/owasp/esapi/logging/java/JavaLogLevelHandlersTest.java index a65e3bf4f..62c5a1d9a 100644 --- a/src/test/java/org/owasp/esapi/logging/java/JavaLogLevelHandlersTest.java +++ b/src/test/java/org/owasp/esapi/logging/java/JavaLogLevelHandlersTest.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ package org.owasp.esapi.logging.java; @@ -57,7 +57,7 @@ public void testAlwaysDelegation() { Mockito.verify(mockLogger, Mockito.times(1)).log(expectedJavaLevel, testName.getMethodName(), testException); Mockito.verifyNoMoreInteractions(mockLogger); } - + @Test public void testWarnDelegation() { JavaLogLevelHandlers.WARNING.isEnabled(mockLogger); diff --git a/src/test/java/org/owasp/esapi/logging/java/JavaLoggerTest.java b/src/test/java/org/owasp/esapi/logging/java/JavaLoggerTest.java index c7258a8ba..906bb6434 100644 --- a/src/test/java/org/owasp/esapi/logging/java/JavaLoggerTest.java +++ b/src/test/java/org/owasp/esapi/logging/java/JavaLoggerTest.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2019 */ diff --git a/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridgeImplTest.java b/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridgeImplTest.java index b5674b3e8..efbb6ed0c 100644 --- a/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridgeImplTest.java +++ b/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogBridgeImplTest.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.slf4j; @@ -62,7 +62,7 @@ public void testLogMessageWithUnmappedEsapiLevelThrowsException() { Map emptyMap = Collections.emptyMap(); new Slf4JLogBridgeImpl(mockAppender, mockScrubber, emptyMap).log(mockSlf4JLogger, 0, Logger.EVENT_UNSPECIFIED, "This Should fail"); } - + @Test public void testLogMessageAndExceptionWithUnmappedEsapiLevelThrowsException() { exEx.expect(IllegalArgumentException.class); @@ -70,7 +70,7 @@ public void testLogMessageAndExceptionWithUnmappedEsapiLevelThrowsException() { Map emptyMap = Collections.emptyMap(); new Slf4JLogBridgeImpl(mockAppender, mockScrubber, emptyMap).log(mockSlf4JLogger, 0, Logger.EVENT_UNSPECIFIED, "This Should fail", testEx); } - + @Test public void testLogMessage() { EventType eventType = Logger.EVENT_UNSPECIFIED; @@ -96,7 +96,7 @@ public void testLogMessage() { Mockito.verify(mockHandler, Mockito.times(1)).isEnabled(mockSlf4JLogger); Mockito.verify(mockHandler, Mockito.times(0)).log(ArgumentMatchers.any(org.slf4j.Logger.class), ArgumentMatchers.any(Marker.class), ArgumentMatchers.any(String.class), ArgumentMatchers.any(Throwable.class)); Mockito.verify(mockHandler, Mockito.times(1)).log(ArgumentMatchers.same(mockSlf4JLogger), markerCapture.capture(), ArgumentMatchers.eq(cleanMsg)); - + Assert.assertEquals(Logger.EVENT_UNSPECIFIED.toString(), markerCapture.getValue().getName()); Mockito.verifyNoMoreInteractions(mockSlf4JLogger, mockAppender, mockScrubber,mockHandler); } @@ -127,7 +127,7 @@ public void testLogErrorMessageWithException() { Mockito.verify(mockHandler, Mockito.times(0)).log(ArgumentMatchers.any(org.slf4j.Logger.class), ArgumentMatchers.any(Marker.class), ArgumentMatchers.any(String.class)); Mockito.verify(mockHandler, Mockito.times(1)).log(ArgumentMatchers.same(mockSlf4JLogger), markerCapture.capture(), ArgumentMatchers.eq(cleanMsg), ArgumentMatchers.same(testEx)); - + Assert.assertEquals(Logger.EVENT_UNSPECIFIED.toString(), markerCapture.getValue().getName()); Mockito.verifyNoMoreInteractions(mockSlf4JLogger, mockAppender, mockScrubber,mockHandler); } diff --git a/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactoryTest.java b/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactoryTest.java index f7e4b13fe..12a16af4c 100644 --- a/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactoryTest.java +++ b/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactoryTest.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.slf4j; @@ -38,45 +38,45 @@ public class Slf4JLogFactoryTest { @Rule public TestName testName = new TestName(); - + @Test public void testCreateLoggerByString() { Logger logger = new Slf4JLogFactory().getLogger("test"); Assert.assertTrue(logger instanceof Slf4JLogger); } - + @Test public void testCreateLoggerByClass() { Logger logger = new Slf4JLogFactory().getLogger(Slf4JLogBridgeImplTest.class); Assert.assertTrue(logger instanceof Slf4JLogger); } - + @Test public void checkScrubberWithEncoding() throws Exception { ArgumentCaptor delegates = ArgumentCaptor.forClass(List.class); PowerMockito.whenNew(CompositeLogScrubber.class).withArguments(delegates.capture()).thenReturn(null); - + //Call to invoke the constructor capture Slf4JLogFactory.createLogScrubber(true); - + List scrubbers = delegates.getValue(); Assert.assertEquals(2, scrubbers.size()); Assert.assertTrue(scrubbers.get(0) instanceof NewlineLogScrubber); Assert.assertTrue(scrubbers.get(1) instanceof CodecLogScrubber); } - + @Test public void checkScrubberWithoutEncoding() throws Exception { ArgumentCaptor delegates = ArgumentCaptor.forClass(List.class); PowerMockito.whenNew(CompositeLogScrubber.class).withArguments(delegates.capture()).thenReturn(null); - + //Call to invoke the constructor capture Slf4JLogFactory.createLogScrubber(false); - + List scrubbers = delegates.getValue(); Assert.assertEquals(1, scrubbers.size()); Assert.assertTrue(scrubbers.get(0) instanceof NewlineLogScrubber); } - + /** * At this time there are no special considerations or handling for the appender * creation in this scope. It is expected that the arguments to the internal @@ -95,14 +95,14 @@ public void checkPassthroughAppenderConstruct() throws Exception { PowerMockito.whenNew(LogPrefixAppender.class).withArguments(userInfoCapture.capture(), clientInfoCapture.capture(), serverInfoCapture.capture(), logAppNameCapture.capture(), appNameCapture.capture()).thenReturn(stubAppender); LogAppender appender = Slf4JLogFactory.createLogAppender(true, true, false, true, testName.getMethodName()); - + Assert.assertEquals(stubAppender, appender); Assert.assertTrue(userInfoCapture.getValue()); Assert.assertTrue(clientInfoCapture.getValue()); Assert.assertFalse(serverInfoCapture.getValue()); Assert.assertTrue(logAppNameCapture.getValue()); - Assert.assertEquals(testName.getMethodName(), appNameCapture.getValue()); + Assert.assertEquals(testName.getMethodName(), appNameCapture.getValue()); } - - + + } diff --git a/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandlersTest.java b/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandlersTest.java index e5607c435..73e4833ba 100644 --- a/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandlersTest.java +++ b/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLogLevelHandlersTest.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ package org.owasp.esapi.logging.slf4j; diff --git a/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLoggerTest.java b/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLoggerTest.java index 70687f4f2..77e718d34 100644 --- a/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLoggerTest.java +++ b/src/test/java/org/owasp/esapi/logging/slf4j/Slf4JLoggerTest.java @@ -1,15 +1,15 @@ /** * 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. - * + * * @created 2018 */ @@ -21,33 +21,33 @@ import org.owasp.esapi.Logger; public class Slf4JLoggerTest { - + private static final String MSG = Slf4JLoggerTest.class.getSimpleName(); - + private Slf4JLogBridge mockBridge = Mockito.mock(Slf4JLogBridge.class); private org.slf4j.Logger mockLogDelegate = Mockito.mock(org.slf4j.Logger.class); - + private Throwable testEx = new Throwable(MSG + "_Exception"); private Logger testLogger = new Slf4JLogger(mockLogDelegate, mockBridge, Logger.ALL); @Test public void testLevelEnablement() { testLogger.setLevel(Logger.INFO); - + Assert.assertTrue(testLogger.isFatalEnabled()); Assert.assertTrue(testLogger.isErrorEnabled()); Assert.assertTrue(testLogger.isWarningEnabled()); Assert.assertTrue(testLogger.isInfoEnabled()); Assert.assertFalse(testLogger.isDebugEnabled()); Assert.assertFalse(testLogger.isTraceEnabled()); - + Assert.assertEquals(Logger.INFO, testLogger.getESAPILevel()); } - + @Test public void testAllLevelEnablement() { testLogger.setLevel(Logger.ALL); - + Assert.assertTrue(testLogger.isFatalEnabled()); Assert.assertTrue(testLogger.isErrorEnabled()); Assert.assertTrue(testLogger.isWarningEnabled()); @@ -59,7 +59,7 @@ public void testAllLevelEnablement() { @Test public void testOffLevelEnablement() { testLogger.setLevel(Logger.OFF); - + Assert.assertFalse(testLogger.isFatalEnabled()); Assert.assertFalse(testLogger.isErrorEnabled()); Assert.assertFalse(testLogger.isWarningEnabled()); @@ -70,23 +70,23 @@ public void testOffLevelEnablement() { @Test public void testFatalWithMessage() { testLogger.fatal(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.FATAL, Logger.EVENT_UNSPECIFIED, MSG); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @Test public void testFatalWithMessageAndThrowable() { testLogger.fatal(Logger.EVENT_UNSPECIFIED, MSG, testEx); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.FATAL, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testFatalWithMessageDisabled() { testLogger.setLevel(Logger.OFF); testLogger.fatal(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.FATAL, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @@ -97,27 +97,27 @@ public void testFatalWithMessageAndThrowableDisabled() { Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.FATAL, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testErrorWithMessage() { testLogger.error(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.ERROR, Logger.EVENT_UNSPECIFIED, MSG); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @Test public void testErrorWithMessageAndThrowable() { testLogger.error(Logger.EVENT_UNSPECIFIED, MSG, testEx); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.ERROR, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testErrorWithMessageDisabled() { testLogger.setLevel(Logger.OFF); testLogger.error(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.ERROR, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @@ -128,27 +128,27 @@ public void testErrorWithMessageAndThrowableDisabled() { Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.ERROR, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testWarnWithMessage() { testLogger.warning(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.WARNING, Logger.EVENT_UNSPECIFIED, MSG); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @Test public void testWarnWithMessageAndThrowable() { testLogger.warning(Logger.EVENT_UNSPECIFIED, MSG, testEx); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.WARNING, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testWarnWithMessageDisabled() { testLogger.setLevel(Logger.OFF); testLogger.warning(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.WARNING, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @@ -159,27 +159,27 @@ public void testWarnWithMessageAndThrowableDisabled() { Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.WARNING, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testInfoWithMessage() { testLogger.info(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.INFO, Logger.EVENT_UNSPECIFIED, MSG); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @Test public void testInfoWithMessageAndThrowable() { testLogger.info(Logger.EVENT_UNSPECIFIED, MSG, testEx); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.INFO, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testInfoWithMessageDisabled() { testLogger.setLevel(Logger.OFF); testLogger.info(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.INFO, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @@ -193,23 +193,23 @@ public void testInfoWithMessageAndThrowableDisabled() { @Test public void testDebugWithMessage() { testLogger.debug(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.DEBUG, Logger.EVENT_UNSPECIFIED, MSG); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @Test public void testDebugWithMessageAndThrowable() { testLogger.debug(Logger.EVENT_UNSPECIFIED, MSG, testEx); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.DEBUG, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testDebugWithMessageDisabled() { testLogger.setLevel(Logger.OFF); testLogger.debug(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.DEBUG, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @@ -220,27 +220,27 @@ public void testDebugWithMessageAndThrowableDisabled() { Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.DEBUG, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testTraceWithMessage() { testLogger.trace(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.TRACE, Logger.EVENT_UNSPECIFIED, MSG); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @Test public void testTraceWithMessageAndThrowable() { testLogger.trace(Logger.EVENT_UNSPECIFIED, MSG, testEx); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.TRACE, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testTraceWithMessageDisabled() { testLogger.setLevel(Logger.OFF); testLogger.trace(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.TRACE, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @@ -251,27 +251,27 @@ public void testTraceWithMessageAndThrowableDisabled() { Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.TRACE, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testAlwaysWithMessage() { testLogger.always(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.ALL, Logger.EVENT_UNSPECIFIED, MSG); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } @Test public void testAlwaysWithMessageAndThrowable() { testLogger.always(Logger.EVENT_UNSPECIFIED, MSG, testEx); - + Mockito.verify(mockBridge, Mockito.times(1)).log(mockLogDelegate, Logger.ALL, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } - + @Test public void testAlwaysWithMessageDisabled() { testLogger.setLevel(Logger.OFF); testLogger.always(Logger.EVENT_UNSPECIFIED, MSG); - + Mockito.verify(mockBridge, Mockito.times(0)).log(mockLogDelegate, Logger.ALL, Logger.EVENT_UNSPECIFIED, MSG, testEx); Mockito.verifyNoMoreInteractions(mockBridge, mockLogDelegate); } diff --git a/src/test/java/org/owasp/esapi/reference/AbstractAccessReferenceMapTest.java b/src/test/java/org/owasp/esapi/reference/AbstractAccessReferenceMapTest.java index 810a2bf15..3d7836210 100644 --- a/src/test/java/org/owasp/esapi/reference/AbstractAccessReferenceMapTest.java +++ b/src/test/java/org/owasp/esapi/reference/AbstractAccessReferenceMapTest.java @@ -48,7 +48,7 @@ public void run() { e.printStackTrace(); } - } + } } }; @@ -65,7 +65,7 @@ public void run() { Mockito.verify(map,Mockito.times(1)).getUniqueReference(); } - + @Test public void verifyNoDuplicateKeysOnUpdateReplace() { @SuppressWarnings("unchecked") @@ -74,26 +74,26 @@ public void verifyNoDuplicateKeysOnUpdateReplace() { ); Object indirectObj1 = new Object(); Object indirectObj2 = new Object(); - Mockito.when(map.getUniqueReference()).thenReturn(indirectObj1); - + Mockito.when(map.getUniqueReference()).thenReturn(indirectObj1); + Object direct1 = new Object(); Object direct2 = new Object(); - + map.addDirectReference(direct1); - + Mockito.reset(map); - + Set newDirectElements = new HashSet<>(); newDirectElements.add(direct2); newDirectElements.add(direct1); - - Mockito.when(map.getUniqueReference()).thenReturn(indirectObj1).thenReturn(indirectObj2); - + + Mockito.when(map.getUniqueReference()).thenReturn(indirectObj1).thenReturn(indirectObj2); + map.update(newDirectElements); - + //Needs to be called 2 times to get past the first duplicate key. This verifies that we're inserting unique pairs. Mockito.verify(map, Mockito.times(2)).getUniqueReference(); - + Assert.assertEquals(indirectObj1, map.getIndirectReference(direct1)); Assert.assertEquals(indirectObj2, map.getIndirectReference(direct2)); } diff --git a/src/test/java/org/owasp/esapi/reference/AccessControllerTest.java b/src/test/java/org/owasp/esapi/reference/AccessControllerTest.java index abee34afa..a2c20c2e5 100644 --- a/src/test/java/org/owasp/esapi/reference/AccessControllerTest.java +++ b/src/test/java/org/owasp/esapi/reference/AccessControllerTest.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -28,21 +28,21 @@ /** * The Class AccessControllerTest. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class AccessControllerTest extends TestCase { /** * Instantiates a new access controller test. - * + * * @param testName * the test name * @throws Exception */ public AccessControllerTest(String testName) throws Exception { super(testName); - + Authenticator authenticator = ESAPI.authenticator(); String password = authenticator.generateStrongPassword(); @@ -51,7 +51,7 @@ public AccessControllerTest(String testName) throws Exception { if ( alice == null ) { alice = authenticator.createUser( "testuser1", password, password); } - alice.addRole("user"); + alice.addRole("user"); // create a user with the "admin" role for this test User bob = authenticator.getUser("testuser2"); @@ -59,7 +59,7 @@ public AccessControllerTest(String testName) throws Exception { bob = authenticator.createUser( "testuser2", password, password); } bob.addRole("admin"); - + // create a user with the "user" and "admin" roles for this test User mitch = authenticator.getUser("testuser3"); if ( mitch == null ) { @@ -88,7 +88,7 @@ protected void tearDown() throws Exception { /** * Suite. - * + * * @return the test */ public static Test suite() { @@ -103,7 +103,7 @@ public void testMatchRule() { ESAPI.authenticator().setCurrentUser(null); assertFalse(ESAPI.accessController().isAuthorizedForURL("/nobody")); } - + /** * Test of isAuthorizedForURL method, of class * org.owasp.esapi.AccessController. @@ -114,7 +114,7 @@ public void testIsAuthorizedForURL() throws Exception { System.out.println("isAuthorizedForURL"); AccessController instance = ESAPI.accessController(); Authenticator auth = ESAPI.authenticator(); - + auth.setCurrentUser( auth.getUser("testuser1") ); assertFalse(instance.isAuthorizedForURL("/nobody")); assertFalse(instance.isAuthorizedForURL("/test/admin")); @@ -138,7 +138,7 @@ public void testIsAuthorizedForURL() throws Exception { assertFalse(instance.isAuthorizedForURL("/test/moderator")); assertTrue(instance.isAuthorizedForURL("/test/profile")); assertFalse(instance.isAuthorizedForURL("/upload")); - + auth.setCurrentUser( auth.getUser("testuser3") ); assertFalse(instance.isAuthorizedForURL("/nobody")); assertTrue(instance.isAuthorizedForURL("/test/admin")); @@ -149,7 +149,7 @@ public void testIsAuthorizedForURL() throws Exception { assertFalse(instance.isAuthorizedForURL("/test/moderator")); assertTrue(instance.isAuthorizedForURL("/test/profile")); assertFalse(instance.isAuthorizedForURL("/upload")); - + try { instance.assertAuthorizedForURL("/test/admin"); instance.assertAuthorizedForURL( "/nobody" ); @@ -167,7 +167,7 @@ public void testIsAuthorizedForFunction() { System.out.println("isAuthorizedForFunction"); AccessController instance = ESAPI.accessController(); Authenticator auth = ESAPI.authenticator(); - + auth.setCurrentUser( auth.getUser("testuser1") ); assertTrue(instance.isAuthorizedForFunction("/FunctionA")); assertFalse(instance.isAuthorizedForFunction("/FunctionAdeny")); @@ -209,7 +209,7 @@ public void testIsAuthorizedForData() { System.out.println("isAuthorizedForData"); AccessController instance = ESAPI.accessController(); Authenticator auth = ESAPI.authenticator(); - + Class adminR = null; Class adminRW = null; Class userW = null; @@ -218,7 +218,7 @@ public void testIsAuthorizedForData() { Class userAdminR = null; Class userAdminRW = null; Class undefined = null; - + try{ adminR = Class.forName("java.util.ArrayList"); adminRW = Class.forName("java.lang.Math"); @@ -228,7 +228,7 @@ public void testIsAuthorizedForData() { userAdminR = Class.forName("java.util.Random"); userAdminRW = Class.forName("javax.crypto.Cipher"); undefined = Class.forName("java.io.FileWriter"); - + }catch(ClassNotFoundException cnf){ System.out.println("CLASS NOT FOUND."); cnf.printStackTrace(); @@ -246,7 +246,7 @@ public void testIsAuthorizedForData() { assertTrue(instance.isAuthorizedForData("read", anyR)); assertTrue(instance.isAuthorizedForData("read", userAdminR)); assertTrue(instance.isAuthorizedForData("write", userAdminRW)); - + //test Admin auth.setCurrentUser( auth.getUser("testuser2") ); assertTrue(instance.isAuthorizedForData("read", adminRW)); @@ -258,7 +258,7 @@ public void testIsAuthorizedForData() { assertTrue(instance.isAuthorizedForData("read", anyR)); assertTrue(instance.isAuthorizedForData("read", userAdminR)); assertTrue(instance.isAuthorizedForData("write", userAdminRW)); - + //test User/Admin auth.setCurrentUser( auth.getUser("testuser3") ); assertTrue(instance.isAuthorizedForData("read", userRW)); @@ -279,7 +279,7 @@ public void testIsAuthorizedForData() { } catch ( AccessControlException e ) { // expected } - + } /** @@ -290,7 +290,7 @@ public void testIsAuthorizedForFile() { System.out.println("isAuthorizedForFile"); AccessController instance = ESAPI.accessController(); Authenticator auth = ESAPI.authenticator(); - + auth.setCurrentUser( auth.getUser("testuser1") ); assertTrue(instance.isAuthorizedForFile("/Dir/File1")); assertFalse(instance.isAuthorizedForFile("/Dir/File2")); @@ -326,12 +326,12 @@ public void testIsAuthorizedForService() { System.out.println("isAuthorizedForService"); AccessController instance = ESAPI.accessController(); Authenticator auth = ESAPI.authenticator(); - + auth.setCurrentUser( auth.getUser("testuser1") ); assertTrue(instance.isAuthorizedForService("/services/ServiceA")); assertFalse(instance.isAuthorizedForService("/services/ServiceB")); assertTrue(instance.isAuthorizedForService("/services/ServiceC")); - + assertFalse(instance.isAuthorizedForService("/test/ridiculous")); auth.setCurrentUser( auth.getUser("testuser2") ); diff --git a/src/test/java/org/owasp/esapi/reference/AccessReferenceMapTest.java b/src/test/java/org/owasp/esapi/reference/AccessReferenceMapTest.java index 8c479b813..f04655fb3 100644 --- a/src/test/java/org/owasp/esapi/reference/AccessReferenceMapTest.java +++ b/src/test/java/org/owasp/esapi/reference/AccessReferenceMapTest.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -33,14 +33,14 @@ /** * The Class AccessReferenceMapTest. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class AccessReferenceMapTest extends TestCase { - + /** * Instantiates a new access reference map test. - * + * * @param testName * the test name */ @@ -66,7 +66,7 @@ protected void tearDown() throws Exception { /** * Suite. - * + * * @return the test */ public static Test suite() { @@ -74,10 +74,10 @@ public static Test suite() { return suite; } - + /** * Test of update method, of class org.owasp.esapi.AccessReferenceMap. - * + * * @throws AuthenticationException * the authentication exception * @throws EncryptionException @@ -86,28 +86,28 @@ public void testUpdate() throws AuthenticationException, EncryptionException { System.out.println("update"); RandomAccessReferenceMap arm = new RandomAccessReferenceMap(); Authenticator auth = ESAPI.authenticator(); - + String pass = auth.generateStrongPassword(); User u = auth.createUser( "armUpdate", pass, pass ); - + // test to make sure update returns something arm.update(auth.getUserNames()); String indirect = arm.getIndirectReference( u.getAccountName() ); if ( indirect == null ) fail(); - + // test to make sure update removes items that are no longer in the list auth.removeUser( u.getAccountName() ); arm.update(auth.getUserNames()); indirect = arm.getIndirectReference( u.getAccountName() ); if ( indirect != null ) fail(); - + // test to make sure old indirect reference is maintained after an update arm.update(auth.getUserNames()); String newIndirect = arm.getIndirectReference( u.getAccountName() ); assertEquals(indirect, newIndirect); } - - + + /** * Test of iterator method, of class org.owasp.esapi.AccessReferenceMap. */ @@ -115,7 +115,7 @@ public void testIterator() { System.out.println("iterator"); RandomAccessReferenceMap arm = new RandomAccessReferenceMap(); Authenticator auth = ESAPI.authenticator(); - + arm.update(auth.getUserNames()); Iterator i = arm.iterator(); @@ -125,43 +125,43 @@ public void testIterator() { if ( u == null ) fail(); } } - + /** * Test of getIndirectReference method, of class * org.owasp.esapi.AccessReferenceMap. */ public void testGetIndirectReference() { System.out.println("getIndirectReference"); - + String directReference = "234"; Set list = new HashSet(); list.add( "123" ); list.add( directReference ); list.add( "345" ); RandomAccessReferenceMap instance = new RandomAccessReferenceMap( list ); - + String expResult = directReference; String result = instance.getIndirectReference(directReference); - assertNotSame(expResult, result); + assertNotSame(expResult, result); } /** * Test of getDirectReference method, of class * org.owasp.esapi.AccessReferenceMap. - * + * * @throws AccessControlException * the access control exception */ public void testGetDirectReference() throws AccessControlException { System.out.println("getDirectReference"); - + String directReference = "234"; Set list = new HashSet(); list.add( "123" ); list.add( directReference ); list.add( "345" ); RandomAccessReferenceMap instance = new RandomAccessReferenceMap( list ); - + String ind = instance.getIndirectReference(directReference); String dir = (String)instance.getDirectReference(ind); assertEquals(directReference, dir); @@ -172,21 +172,21 @@ public void testGetDirectReference() throws AccessControlException { // success } } - + /** * * @throws org.owasp.esapi.errors.AccessControlException */ public void testAddDirectReference() throws AccessControlException { System.out.println("addDirectReference"); - + String directReference = "234"; Set list = new HashSet(); list.add( "123" ); list.add( directReference ); list.add( "345" ); RandomAccessReferenceMap instance = new RandomAccessReferenceMap( list ); - + String newDirect = instance.addDirectReference("newDirect"); assertNotNull( newDirect ); String ind = instance.addDirectReference(directReference); @@ -202,14 +202,14 @@ public void testAddDirectReference() throws AccessControlException { */ public void testRemoveDirectReference() throws AccessControlException { System.out.println("removeDirectReference"); - + String directReference = "234"; Set list = new HashSet(); list.add( "123" ); list.add( directReference ); list.add( "345" ); RandomAccessReferenceMap instance = new RandomAccessReferenceMap( list ); - + String indirect = instance.getIndirectReference(directReference); assertNotNull(indirect); String deleted = instance.removeDirectReference(directReference); @@ -217,7 +217,7 @@ public void testRemoveDirectReference() throws AccessControlException { deleted = instance.removeDirectReference("ridiculous"); assertNull(deleted); } - - - + + + } diff --git a/src/test/java/org/owasp/esapi/reference/AuthenticatorTest.java b/src/test/java/org/owasp/esapi/reference/AuthenticatorTest.java index dcde90dc3..5df1b5c5b 100644 --- a/src/test/java/org/owasp/esapi/reference/AuthenticatorTest.java +++ b/src/test/java/org/owasp/esapi/reference/AuthenticatorTest.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -55,12 +55,12 @@ /** * The Class AuthenticatorTest. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class AuthenticatorTest { private static Authenticator instance; - /** + /** * User session information is stored on a per-thread basis. So long as this has potential to run single threaded then we'll maintain a synchronous nature execution. * This is done to prevent tests corrupting each others states since all will be executed on a limited set of Threads within the JVM. */ @@ -82,7 +82,7 @@ public static void setUpStatic() { public void setup() throws InterruptedException { while (!threadIsolation.tryAcquire(500, TimeUnit.MILLISECONDS)) { //Spurious Interrupt Guard - } + } } @After @@ -102,10 +102,10 @@ public void cleanup() { } } - + /** * Test of createAccount method, of class org.owasp.esapi.Authenticator. - * + * * @throws AuthenticationException * the authentication exception * @throws EncryptionException @@ -158,12 +158,12 @@ public void cleanup() { /** * Test of generateStrongPassword method, of class * org.owasp.esapi.Authenticator. - * + * * @throws AuthenticationException * the authentication exception */ @Test public void testGenerateStrongPassword() throws AuthenticationException { - System.out.println("generateStrongPassword"); + System.out.println("generateStrongPassword"); String oldPassword = "iiiiiiiiii"; // i is not allowed in passwords - this prevents failures from containing pieces of old password String newPassword = null; String username = "FictionalEsapiUser"; @@ -187,7 +187,7 @@ public void cleanup() { /** * Test of getCurrentUser method, of class org.owasp.esapi.Authenticator. - * + * * * @throws Exception */ @@ -196,7 +196,7 @@ public void cleanup() { String username1 = ESAPI.randomizer().getRandomString(8, EncoderConstants.CHAR_ALPHANUMERICS); String username2 = ESAPI.randomizer().getRandomString(8, EncoderConstants.CHAR_ALPHANUMERICS); User user1 = instance.createUser(username1, "getCurrentUser", "getCurrentUser"); - User user2 = instance.createUser(username2, "getCurrentUser", "getCurrentUser"); + User user2 = instance.createUser(username2, "getCurrentUser", "getCurrentUser"); user1.enable(); MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -206,7 +206,7 @@ public void cleanup() { assertEquals( currentUser, user1 ); instance.setCurrentUser( user2 ); assertFalse( currentUser.getAccountName().equals( user2.getAccountName() ) ); - + Runnable echo = new Runnable() { public void run() { User a = null; @@ -239,7 +239,7 @@ public void run() { /** * Test of getUser method, of class org.owasp.esapi.Authenticator. - * + * * @throws AuthenticationException * the authentication exception */ @@ -251,7 +251,7 @@ public void run() { assertNotNull(instance.getUser( accountName )); assertNull(instance.getUser( ESAPI.randomizer().getRandomString(8, EncoderConstants.CHAR_ALPHANUMERICS) )); } - + /** * * @throws org.owasp.esapi.errors.AuthenticationException @@ -265,7 +265,7 @@ public void run() { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); ESAPI.httpUtilities().setCurrentHTTP(request, response); - + System.out.println("getUserFromRememberToken - expecting failure"); request.setCookie( HTTPUtilities.REMEMBER_TOKEN_COOKIE_NAME, "ridiculous" ); try { @@ -285,12 +285,12 @@ public void run() { User test2 = instance.login( request, response ); assertSame( user, test2 ); } - - + + /** * Test get user from session. - * + * * @throws AuthenticationException * the authentication exception */ @@ -313,7 +313,7 @@ public void run() { /** * Test get user names. - * + * * @throws AuthenticationException * the authentication exception */ @@ -332,7 +332,7 @@ public void run() { assertTrue(names.contains(testnames[i].toLowerCase())); } } - + /** * Test of hashPassword method, of class org.owasp.esapi.Authenticator. * @@ -349,7 +349,7 @@ public void run() { /** * Test of login method, of class org.owasp.esapi.Authenticator. - * + * * @throws AuthenticationException * the authentication exception */ @@ -368,10 +368,10 @@ public void run() { assertTrue( test.isLoggedIn() ); assertSame(user, test); } - + /** * Test of removeAccount method, of class org.owasp.esapi.Authenticator. - * + * * @throws Exception * the exception */ @@ -387,7 +387,7 @@ public void run() { /** * Test of saveUsers method, of class org.owasp.esapi.Authenticator. - * + * * @throws Exception * the exception */ @@ -403,10 +403,10 @@ public void run() { assertNull( instance.getUser(accountName) ); } - + /** * Test of setCurrentUser method, of class org.owasp.esapi.Authenticator. - * + * * @throws AuthenticationException * the authentication exception * @throws InterruptedException Thrown if test is interrupted while awaiting completion of child threads. @@ -423,7 +423,7 @@ public void run() { userOne.loginWithPassword("getCurrentUser"); User currentUser = instance.getCurrentUser(); assertEquals( currentUser, userOne ); - User userTwo = instance.createUser(user2, "getCurrentUser", "getCurrentUser"); + User userTwo = instance.createUser(user2, "getCurrentUser", "getCurrentUser"); instance.setCurrentUser( userTwo ); assertFalse( currentUser.getAccountName().equals( userTwo.getAccountName() ) ); final CountDownLatch latch = new CountDownLatch(10); @@ -450,15 +450,15 @@ public void run() { new Thread( echo ).start(); } while(!latch.await(500, TimeUnit.MILLISECONDS)) { - //Spurious Interrupt Guard. + //Spurious Interrupt Guard. } } - + /** * Test of setCurrentUser method, of class org.owasp.esapi.Authenticator. - * + * * @throws AuthenticationException * the authentication exception */ @@ -482,7 +482,7 @@ public void run() { /** * Test of setCurrentUser method, of class org.owasp.esapi.Authenticator. - * + * * @throws AuthenticationException * the authentication exception */ @@ -505,10 +505,10 @@ public void run() { // expected } } - + /** * Test of setCurrentUser method, of class org.owasp.esapi.Authenticator. - * + * * @throws AuthenticationException * the authentication exception */ @@ -533,7 +533,7 @@ public void run() { } /** * Test of setCurrentUser method, of class org.owasp.esapi.Authenticator. - * + * * @throws AuthenticationException * the authentication exception */ @@ -559,19 +559,19 @@ public void run() { // expected } } - - - + + + /** * Test of validatePasswordStrength method, of class * org.owasp.esapi.Authenticator. - * + * * @throws AuthenticationException * the authentication exception */ @Test public void testValidatePasswordStrength() throws AuthenticationException { System.out.println("validatePasswordStrength"); - + String username = "FictionalEsapiUser"; User user = new DefaultUser(username); @@ -650,7 +650,7 @@ public void run() { /** * Test of exists method, of class org.owasp.esapi.Authenticator. - * + * * @throws Exception * the exception */ @@ -673,7 +673,7 @@ public void run() { String accountName = ESAPI.randomizer().getRandomString(8, EncoderConstants.CHAR_ALPHANUMERICS); String password = instance.generateStrongPassword(); String role = "test"; - + // test wrong parameters - missing role parameter String[] badargs = { accountName, password }; FileBasedAuthenticator.main( badargs ); @@ -692,6 +692,6 @@ public void run() { assertTrue( u2.isInRole(role)); assertEquals( instance.hashPassword(password, accountName), ((FileBasedAuthenticator)instance).getHashedPassword(u2) ); } - - + + } diff --git a/src/test/java/org/owasp/esapi/reference/DefaultSecurityConfigurationTest.java b/src/test/java/org/owasp/esapi/reference/DefaultSecurityConfigurationTest.java index 225a8b117..9a801614c 100644 --- a/src/test/java/org/owasp/esapi/reference/DefaultSecurityConfigurationTest.java +++ b/src/test/java/org/owasp/esapi/reference/DefaultSecurityConfigurationTest.java @@ -27,146 +27,146 @@ private DefaultSecurityConfiguration createWithProperty(String key, String val) properties.setProperty(key, val); return new DefaultSecurityConfiguration(properties); } - + @Test public void testGetApplicationName() { final String expected = "ESAPI_UnitTests"; DefaultSecurityConfiguration secConf = this.createWithProperty(APPLICATION_NAME, expected); assertEquals(expected, secConf.getApplicationName()); } - + @Test public void testGetLogImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals(DEFAULT_LOG_IMPLEMENTATION, secConf.getLogImplementation()); - + final String expected = "TestLogger"; secConf = this.createWithProperty(LOG_IMPLEMENTATION, expected); assertEquals(expected, secConf.getLogImplementation()); } - + @Test public void testAuthenticationImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals(DEFAULT_AUTHENTICATION_IMPLEMENTATION, secConf.getAuthenticationImplementation()); - + final String expected = "TestAuthentication"; secConf = this.createWithProperty(AUTHENTICATION_IMPLEMENTATION, expected); assertEquals(expected, secConf.getAuthenticationImplementation()); } - + @Test public void testEncoderImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals(DEFAULT_ENCODER_IMPLEMENTATION, secConf.getEncoderImplementation()); - + final String expected = "TestEncoder"; secConf = this.createWithProperty(ENCODER_IMPLEMENTATION, expected); assertEquals(expected, secConf.getEncoderImplementation()); } - + @Test public void testAccessControlImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals(DEFAULT_ACCESS_CONTROL_IMPLEMENTATION, secConf.getAccessControlImplementation()); - + final String expected = "TestAccessControl"; secConf = this.createWithProperty(ACCESS_CONTROL_IMPLEMENTATION, expected); assertEquals(expected, secConf.getAccessControlImplementation()); } - + @Test public void testEncryptionImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals(DEFAULT_ENCRYPTION_IMPLEMENTATION, secConf.getEncryptionImplementation()); - + final String expected = "TestEncryption"; secConf = this.createWithProperty(ENCRYPTION_IMPLEMENTATION, expected); assertEquals(expected, secConf.getEncryptionImplementation()); } - + @Test public void testIntrusionDetectionImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals(DEFAULT_INTRUSION_DETECTION_IMPLEMENTATION, secConf.getIntrusionDetectionImplementation()); - + final String expected = "TestIntrusionDetection"; secConf = this.createWithProperty(INTRUSION_DETECTION_IMPLEMENTATION, expected); assertEquals(expected, secConf.getIntrusionDetectionImplementation()); } - + @Test public void testRandomizerImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals(DEFAULT_RANDOMIZER_IMPLEMENTATION, secConf.getRandomizerImplementation()); - + final String expected = "TestRandomizer"; secConf = this.createWithProperty(RANDOMIZER_IMPLEMENTATION, expected); assertEquals(expected, secConf.getRandomizerImplementation()); } - + @Test public void testExecutorImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals(DEFAULT_EXECUTOR_IMPLEMENTATION, secConf.getExecutorImplementation()); - + final String expected = "TestExecutor"; secConf = this.createWithProperty(EXECUTOR_IMPLEMENTATION, expected); assertEquals(expected, secConf.getExecutorImplementation()); } - + @Test public void testHTTPUtilitiesImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals(DEFAULT_HTTP_UTILITIES_IMPLEMENTATION, secConf.getHTTPUtilitiesImplementation()); - + final String expected = "TestHTTPUtilities"; secConf = this.createWithProperty(HTTP_UTILITIES_IMPLEMENTATION, expected); assertEquals(expected, secConf.getHTTPUtilitiesImplementation()); } - + @Test public void testValidationImplementation() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals(DEFAULT_VALIDATOR_IMPLEMENTATION, secConf.getValidationImplementation()); - + final String expected = "TestValidation"; secConf = this.createWithProperty(VALIDATOR_IMPLEMENTATION, expected); assertEquals(expected, secConf.getValidationImplementation()); } - + @Test public void testGetEncryptionKeyLength() { // test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals(128, secConf.getEncryptionKeyLength()); - + final int expected = 256; secConf = this.createWithProperty(KEY_LENGTH, String.valueOf(expected)); assertEquals(expected, secConf.getEncryptionKeyLength()); } - + @Test public void testGetKDFPseudoRandomFunction() { // test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals("HmacSHA256", secConf.getKDFPseudoRandomFunction()); - + final String expected = "HmacSHA1"; secConf = this.createWithProperty(KDF_PRF_ALG, expected); assertEquals(expected, secConf.getKDFPseudoRandomFunction()); } - + @Test public void testGetMasterSalt() { try { @@ -177,7 +177,7 @@ public void testGetMasterSalt() { catch (ConfigurationException ce) { assertNotNull(ce.getMessage()); } - + final String salt = "53081"; final String property = ESAPI.encoder().encodeForBase64(salt.getBytes(), false); Properties properties = new Properties(); @@ -185,17 +185,17 @@ public void testGetMasterSalt() { DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(properties); assertEquals(salt, new String(secConf.getMasterSalt())); } - + @Test public void testGetAllowedExecutables() { DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); java.util.List allowedExecutables = secConf.getAllowedExecutables(); - + //is this really what should be returned? what about an empty list? assertEquals(1, allowedExecutables.size()); assertEquals("", allowedExecutables.get(0)); - - + + Properties properties = new Properties(); properties.setProperty(APPROVED_EXECUTABLES, String.valueOf("/bin/bzip2,/bin/diff, /bin/cvs")); secConf = new DefaultSecurityConfiguration(properties); @@ -203,20 +203,20 @@ public void testGetAllowedExecutables() { assertEquals(3, allowedExecutables.size()); assertEquals("/bin/bzip2", allowedExecutables.get(0)); assertEquals("/bin/diff", allowedExecutables.get(1)); - + //this seems less than optimal, maybe each value should have a trim() done to it //at least we know that this behavior exists, the property should'nt have spaces between values assertEquals(" /bin/cvs", allowedExecutables.get(2)); } - + @Test public void testGetAllowedFileExtensions() { - + DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); java.util.List allowedFileExtensions = secConf.getAllowedFileExtensions(); assertFalse(allowedFileExtensions.isEmpty()); - - + + Properties properties = new Properties(); properties.setProperty(APPROVED_UPLOAD_EXTENSIONS, String.valueOf(".txt,.xml,.html,.png")); secConf = new DefaultSecurityConfiguration(properties); @@ -224,25 +224,25 @@ public void testGetAllowedFileExtensions() { assertEquals(4, allowedFileExtensions.size()); assertEquals(".html", allowedFileExtensions.get(2)); } - + @Test public void testGetAllowedFileUploadSize() { DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); //assert that the default is of some reasonable size assertTrue(secConf.getAllowedFileUploadSize() > (1024 * 100)); - + final int expected = (1024 * 1000); secConf = this.createWithProperty(MAX_UPLOAD_FILE_BYTES, String.valueOf(expected)); assertEquals(expected, secConf.getAllowedFileUploadSize()); } - + @Test public void testGetParameterNames() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals("password", secConf.getPasswordParameterName()); assertEquals("username", secConf.getUsernameParameterName()); - + Properties properties = new Properties(); properties.setProperty(PASSWORD_PARAMETER_NAME, "j_password"); properties.setProperty(USERNAME_PARAMETER_NAME, "j_username"); @@ -250,31 +250,31 @@ public void testGetParameterNames() { assertEquals("j_password", secConf.getPasswordParameterName()); assertEquals("j_username", secConf.getUsernameParameterName()); } - + @Test public void testGetEncryptionAlgorithm() { //test the default DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals("AES", secConf.getEncryptionAlgorithm()); - + secConf = this.createWithProperty(ENCRYPTION_ALGORITHM, "3DES"); assertEquals("3DES", secConf.getEncryptionAlgorithm()); } - + @Test public void testGetCipherXProperties() { DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertEquals("AES/CBC/PKCS5Padding", secConf.getCipherTransformation()); //assertEquals("AES/CBC/PKCS5Padding", secConf.getC); - + Properties properties = new Properties(); properties.setProperty(CIPHER_TRANSFORMATION_IMPLEMENTATION, "Blowfish/CFB/ISO10126Padding"); secConf = new DefaultSecurityConfiguration(properties); assertEquals("Blowfish/CFB/ISO10126Padding", secConf.getCipherTransformation()); - + secConf.setCipherTransformation("DESede/PCBC/PKCS5Padding"); assertEquals("DESede/PCBC/PKCS5Padding", secConf.getCipherTransformation()); - + secConf.setCipherTransformation(null);//sets it back to default assertEquals("Blowfish/CFB/ISO10126Padding", secConf.getCipherTransformation()); } @@ -297,53 +297,53 @@ public void testIV() { catch (ConfigurationException ce) { assertNotNull(ce.getMessage()); } - + props.setProperty(IV_TYPE, "illegal"); // This will just result in a logSpecial message & "random" is returned. secConf = new DefaultSecurityConfiguration(props); ivType = secConf.getIVType(); assertEquals(ivType, "random"); } - + @Test public void testGetAllowMultipleEncoding() { DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertFalse(secConf.getAllowMultipleEncoding()); - + secConf = this.createWithProperty(ALLOW_MULTIPLE_ENCODING, "yes"); assertTrue(secConf.getAllowMultipleEncoding()); - + secConf = this.createWithProperty(ALLOW_MULTIPLE_ENCODING, "true"); assertTrue(secConf.getAllowMultipleEncoding()); - + secConf = this.createWithProperty(ALLOW_MULTIPLE_ENCODING, "no"); assertFalse(secConf.getAllowMultipleEncoding()); } - + @Test public void testGetDefaultCanonicalizationCodecs() { DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertFalse(secConf.getDefaultCanonicalizationCodecs().isEmpty()); - + String property = "org.owasp.esapi.codecs.TestCodec1,org.owasp.esapi.codecs.TestCodec2"; secConf = this.createWithProperty(CANONICALIZATION_CODECS, property); assertTrue(secConf.getDefaultCanonicalizationCodecs().contains("org.owasp.esapi.codecs.TestCodec1")); } - + @Test public void testGetDisableIntrusionDetection() { DefaultSecurityConfiguration secConf = new DefaultSecurityConfiguration(new Properties()); assertFalse(secConf.getDisableIntrusionDetection()); - + secConf = this.createWithProperty(DISABLE_INTRUSION_DETECTION, "TRUE"); assertTrue(secConf.getDisableIntrusionDetection()); - + secConf = this.createWithProperty(DISABLE_INTRUSION_DETECTION, "true"); assertTrue(secConf.getDisableIntrusionDetection()); - + secConf = this.createWithProperty(DISABLE_INTRUSION_DETECTION, "false"); assertFalse(secConf.getDisableIntrusionDetection()); } - + @Test public void testNoSuchPropFile(){ try { @@ -359,7 +359,7 @@ public void testNoSuchPropFile(){ } } - + private String patternOrNull(Pattern p){ return null==p?null:p.pattern(); } @@ -402,7 +402,7 @@ public void testValidationsPropertiesFileOptions(){ assertEquals(patternOrNull(secConf.getValidationPattern("Test1")), "ValueFromFile1"); assertNull(secConf.getValidationPattern("Test2")); assertNull(secConf.getValidationPattern("TestC")); - + secConf = new DefaultSecurityConfiguration("ESAPI-DualValidatorFileChecker.properties"); assertEquals(patternOrNull(secConf.getValidationPattern("Test1")), "ValueFromFile1"); assertEquals(patternOrNull(secConf.getValidationPattern("Test2")), "ValueFromFile2"); @@ -418,8 +418,8 @@ public void testValidationsPropertiesFileOptions(){ assertEquals(patternOrNull(secConf.getValidationPattern("Test2")), "ValueFromFile2"); assertEquals(patternOrNull(secConf.getValidationPattern("TestC")), "ValueFromCommaFile"); } - - @Test + + @Test public void DefaultSearchPathTest(){ assertEquals("", DefaultSearchPath.ROOT.value()); assertEquals("resourceDirectory/", DefaultSearchPath.RESOURCE_DIRECTORY.value()); @@ -428,18 +428,18 @@ public void DefaultSearchPathTest(){ assertEquals("resources/", DefaultSearchPath.RESOURCES.value()); assertEquals("src/main/resources/", DefaultSearchPath.SRC_MAIN_RESOURCES.value()); } - + @Test public void DefaultSearchPathEnumChanges(){ int expected = 6; int testValue = DefaultSearchPath.values().length; assertEquals(expected, testValue); } - + @Test public void defaultPropertiesTest(){ SecurityConfiguration sc = ESAPI.securityConfiguration(); -// # Maximum size of JSESSIONID for the application--the validator regex may have additional values. +// # Maximum size of JSESSIONID for the application--the validator regex may have additional values. // HttpUtilities.HTTPJSESSIONIDLENGTH=50 assertEquals(50, sc.getIntProp("HttpUtilities.HTTPJSESSIONIDLENGTH")); // # Maximum length of a URL (see https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers) @@ -454,10 +454,10 @@ public void defaultPropertiesTest(){ // # Maximum length for an http path // HttpUtilities.HTTPPATHLENGTH=150 assertEquals(150, sc.getIntProp("HttpUtilities.HTTPPATHLENGTH")); -// #Maximum length for a context path +// #Maximum length for a context path // HttpUtilities.contextPathLength=150 assertEquals(150, sc.getIntProp("HttpUtilities.contextPathLength")); -// #Maximum length for an httpServletPath +// #Maximum length for an httpServletPath // HttpUtilities.HTTPSERVLETPATHLENGTH=100 assertEquals(100, sc.getIntProp("HttpUtilities.HTTPSERVLETPATHLENGTH")); // #Maximum length for an http query parameter name @@ -466,13 +466,13 @@ public void defaultPropertiesTest(){ // #Maximum length for an http query parameter -- old default was 2000, but that's the max length for a URL... // HttpUtilities.httpQueryParamValueLength=500 assertEquals(500, sc.getIntProp("HttpUtilities.httpQueryParamValueLength")); -// # Maximum size of HTTP header key--the validator regex may have additional values. +// # Maximum size of HTTP header key--the validator regex may have additional values. // HttpUtilities.MaxHeaderNameSize=256 assertEquals(256, sc.getIntProp("HttpUtilities.MaxHeaderNameSize")); -// # Maximum size of HTTP header value--the validator regex may have additional values. +// # Maximum size of HTTP header value--the validator regex may have additional values. // HttpUtilities.MaxHeaderValueSize=4096 assertEquals(4096, sc.getIntProp("HttpUtilities.MaxHeaderValueSize")); -// # Maximum length of a redirect +// # Maximum length of a redirect // HttpUtilities.maxRedirectLength=512 assertEquals(512, sc.getIntProp("HttpUtilities.maxRedirectLength")); } diff --git a/src/test/java/org/owasp/esapi/reference/DefaultValidaterDateAPITest.java b/src/test/java/org/owasp/esapi/reference/DefaultValidaterDateAPITest.java index 5e552c5b4..3322633f6 100644 --- a/src/test/java/org/owasp/esapi/reference/DefaultValidaterDateAPITest.java +++ b/src/test/java/org/owasp/esapi/reference/DefaultValidaterDateAPITest.java @@ -36,9 +36,9 @@ import org.powermock.modules.junit4.PowerMockRunner; /** - * This class contains a subsection of tests of the DefaultValidator class + * This class contains a subsection of tests of the DefaultValidator class * SPECIFIC TO THE DATE VALIDATION API. - * + * */ @RunWith(PowerMockRunner.class) @PrepareForTest(DefaultValidator.class) @@ -48,7 +48,7 @@ public class DefaultValidaterDateAPITest { @Rule public TestName testName = new TestName(); private String dateString="Input Does not matter in this context"; - + private ValidationException validationEx; private Date testDate = new Date(); private String contextStr; @@ -56,109 +56,109 @@ public class DefaultValidaterDateAPITest { private DateFormat testFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US); private DateValidationRule spyDateRule; private ValidationErrorList errors = new ValidationErrorList(); - + private DefaultValidator uit; - - + + @Before public void setup() throws Exception { contextStr = testName.getMethodName(); - + validationEx = new ValidationException(contextStr, contextStr); - + mockEncoder = mock(Encoder.class); uit = new DefaultValidator(mockEncoder); - + spyDateRule = new DateValidationRule(contextStr, mockEncoder, testFormat); spyDateRule = spy(spyDateRule); whenNew(DateValidationRule.class).withArguments(anyString(), eq(mockEncoder), eq(testFormat)).thenReturn(spyDateRule); - + errors = spy(errors); whenNew(ValidationErrorList.class).withNoArguments().thenReturn(errors); } - + @After public void tearDown() { verifyNoMoreInteractions(spyDateRule, errors); } - + @Test public void testIsValidDate() { doReturn(testDate).when(spyDateRule).sanitize(eq(contextStr), eq(dateString), isA(ValidationErrorList.class)); - + boolean isValid = uit.isValidDate(contextStr, dateString, testFormat, true); Assert.assertTrue("Mock is configured to return a valid date, return should be equally valid.", isValid); - + verify(errors, atLeastOnce()).isEmpty(); verify(errors, times(0)).errors(); verify(spyDateRule, times(1)).setAllowNull(true); verify(spyDateRule, times(1)).sanitize(eq(contextStr), eq(dateString), isA(ValidationErrorList.class)); } - + @Test public void testIsValidDateErrorList() { doReturn(testDate).when(spyDateRule).sanitize(eq(contextStr), eq(dateString), isA(ValidationErrorList.class)); - + boolean isValid = uit.isValidDate(contextStr, dateString, testFormat, true, errors); Assert.assertTrue("Mock is configured to return a valid date, return should be equally valid.", isValid); - + verify(errors, atLeastOnce()).isEmpty(); verify(errors, times(0)).errors(); verify(spyDateRule, times(1)).setAllowNull(true); verify(spyDateRule, times(1)).sanitize(eq(contextStr), eq(dateString), eq(errors)); } - + @Test public void testGetValidDate() throws IntrusionException, ValidationException { doReturn(testDate).when(spyDateRule).sanitize(eq(contextStr), eq(dateString), isA(ValidationErrorList.class)); Date validDate = uit.getValidDate(contextStr, dateString, testFormat, true); Assert.assertEquals("ValidDate should match the mock's configured return value", testDate, validDate); - + verify(errors, atLeastOnce()).isEmpty(); verify(errors, times(0)).errors(); verify(spyDateRule, times(1)).setAllowNull(true); verify(spyDateRule, times(1)).sanitize(eq(contextStr), eq(dateString), isA(ValidationErrorList.class)); } - + @Test public void testGetValidDateErrorList() { doReturn(testDate).when(spyDateRule).sanitize(eq(contextStr), eq(dateString), isA(ValidationErrorList.class)); Date validDate = uit.getValidDate(contextStr, dateString, testFormat, true, errors); Assert.assertEquals("ValidDate should match the mock's configured return value", testDate, validDate); - + verify(errors, atLeastOnce()).isEmpty(); verify(errors, times(0)).errors(); verify(spyDateRule, times(1)).setAllowNull(true); verify(spyDateRule, times(1)).sanitize(eq(contextStr), eq(dateString), eq(errors)); } - - + + @Test public void testIsValidDateOnValidationError() { doReturn(false).when(errors).isEmpty(); doReturn(Arrays.asList(validationEx)).when(errors).errors(); - + doReturn(testDate).when(spyDateRule).sanitize(eq(contextStr), eq(dateString), isA(ValidationErrorList.class)); - + boolean isValid = uit.isValidDate(contextStr, dateString, testFormat, true); Assert.assertFalse("On ValidationException input should be invalid", isValid); - + verify(errors, atLeastOnce()).isEmpty(); verify(errors, times(1)).errors(); verify(spyDateRule, times(1)).setAllowNull(true); verify(spyDateRule, times(1)).sanitize(eq(contextStr), eq(dateString), isA(ValidationErrorList.class)); } - + @Test public void testIsValidDateErrorListOnValidationError() { doReturn(false).when(errors).isEmpty(); doReturn(Arrays.asList(validationEx)).when(errors).errors(); - + doReturn(testDate).when(spyDateRule).sanitize(eq(contextStr), eq(dateString), isA(ValidationErrorList.class)); - + boolean isValid = uit.isValidDate(contextStr, dateString, testFormat, true, errors); Assert.assertFalse("On ValidationException input should be invalid", isValid); - + verify(errors, times(2)).isEmpty(); verify(errors, times(0)).errors(); verify(spyDateRule, times(1)).setAllowNull(true); @@ -180,7 +180,7 @@ public void testGetValidDateOnValidationError() throws IntrusionException, Valid verify(spyDateRule, times(1)).sanitize(eq(contextStr), eq(dateString), isA(ValidationErrorList.class)); } } - + @Test public void testGetValidDateErrorListOnValidationError() { doReturn(false).when(errors).isEmpty(); diff --git a/src/test/java/org/owasp/esapi/reference/DefaultValidatorInputStringAPITest.java b/src/test/java/org/owasp/esapi/reference/DefaultValidatorInputStringAPITest.java index 99e25c493..d62907c07 100644 --- a/src/test/java/org/owasp/esapi/reference/DefaultValidatorInputStringAPITest.java +++ b/src/test/java/org/owasp/esapi/reference/DefaultValidatorInputStringAPITest.java @@ -37,9 +37,9 @@ import org.powermock.modules.junit4.PowerMockRunner; /** - * This class contains a subsection of tests of the DefaultValidator class + * This class contains a subsection of tests of the DefaultValidator class * SPECIFIC TO THE INPUT 'STRING' VALIDATION API. - * + * */ @RunWith(PowerMockRunner.class) @PrepareForTest({DefaultValidator.class, ESAPI.class}) @@ -59,52 +59,52 @@ public class DefaultValidatorInputStringAPITest { private String contextStr; private StringValidationRule spyStringRule; private ValidationErrorList errors = new ValidationErrorList(); - + private DefaultValidator uit; private String testValidatorType; private String validatorResultString; private int testMaximumLength; - + @Before public void setup() throws Exception { contextStr = testName.getMethodName(); testValidatorType = testName.getMethodName() + "_validator_type"; validatorResultString = testName.getMethodName() + "_validator_result"; testMaximumLength = testName.getMethodName().length(); - + validationEx = new ValidationException(contextStr, contextStr); - + mockEncoder = mock(Encoder.class); uit = new DefaultValidator(mockEncoder); - + //Don't care how the StringValidationRule works, we just care that we forwarded the information as expected. - spyStringRule = new StringValidationRule(testValidatorType, mockEncoder); + spyStringRule = new StringValidationRule(testValidatorType, mockEncoder); spyStringRule = spy(spyStringRule); doNothing().when(spyStringRule).addWhitelistPattern(ArgumentMatchers.any()); doNothing().when(spyStringRule).setAllowNull(ArgumentMatchers.anyBoolean()); doNothing().when(spyStringRule).setMaximumLength(ArgumentMatchers.anyInt()); doReturn(validatorResultString).when(spyStringRule).getValid(ArgumentMatchers.anyString(), ArgumentMatchers.anyString()); whenNew(StringValidationRule.class).withArguments(eq(testValidatorType), eq(mockEncoder)).thenReturn(spyStringRule); - + errors = spy(errors); whenNew(ValidationErrorList.class).withNoArguments().thenReturn(errors); - - + + PowerMockito.mockStatic(ESAPI.class); PowerMockito.when(ESAPI.class, ESAPY_SECURITY_CONFIGURATION_GETTER_METHOD_NAME).thenReturn(mockSecConfig); - - + + when(mockSecConfig.getValidationPattern(testValidatorType)).thenReturn(TEST_PATTERN); - + } - + @After public void verifyDelegateCalls() { verify(mockSecConfig, times(1)).getValidationPattern(testValidatorType); - + PowerMockito.verifyNoMoreInteractions(spyStringRule, mockSecConfig, mockEncoder); } - + @Test public void getValidInputNullAllowedPassthrough() throws Exception { String safeValue = uit.getValidInput(contextStr, testName.getMethodName(), testValidatorType, testMaximumLength, true); @@ -116,7 +116,7 @@ public void getValidInputNullAllowedPassthrough() throws Exception { verify(spyStringRule, times(1)).setCanonicalize(true); verify(spyStringRule, times(1)).getValid(contextStr, testName.getMethodName()); } - + @Test public void getValidInputNullNotAllowedPassthrough() throws Exception { String safeValue = uit.getValidInput(contextStr, testName.getMethodName(), testValidatorType, testMaximumLength, false); @@ -128,16 +128,16 @@ public void getValidInputNullNotAllowedPassthrough() throws Exception { verify(spyStringRule, times(1)).setCanonicalize(true); verify(spyStringRule, times(1)).getValid(contextStr, testName.getMethodName()); } - + @Test public void getValidInputNullPatternThrows() throws Exception { exEx.expect(IllegalArgumentException.class); exEx.expectMessage(testValidatorType + "] was not set via the ESAPI validation configuration"); when(mockSecConfig.getValidationPattern(testValidatorType)).thenReturn(null); - + uit.getValidInput(contextStr, testName.getMethodName(), testValidatorType, testMaximumLength, true); } - + @Test public void getValidInputValidationExceptionPropagates() throws Exception { exEx.expect(Is.is(validationEx)); @@ -154,7 +154,7 @@ public void getValidInputValidationExceptionPropagates() throws Exception { verify(spyStringRule, times(1)).getValid(contextStr, testName.getMethodName()); } } - + @Test public void getValidInputValidationExceptionErrorList() throws Exception { ValidationErrorList errorList = new ValidationErrorList(); @@ -171,13 +171,13 @@ public void getValidInputValidationExceptionErrorList() throws Exception { verify(spyStringRule, times(1)).setCanonicalize(true); verify(spyStringRule, times(1)).getValid(contextStr, testName.getMethodName()); } - - + + @Test public void isValidInputNullAllowedPassthrough() throws Exception { boolean isValid= uit.isValidInput(contextStr, testName.getMethodName(), testValidatorType, testMaximumLength, true); assertTrue(isValid); - + verify(spyStringRule, times(1)).addWhitelistPattern(TEST_PATTERN); verify(spyStringRule, times(1)).setAllowNull(true); verify(spyStringRule, times(0)).setAllowNull(false); @@ -185,7 +185,7 @@ public void isValidInputNullAllowedPassthrough() throws Exception { verify(spyStringRule, times(1)).setCanonicalize(true); verify(spyStringRule, times(1)).getValid(contextStr, testName.getMethodName()); } - + @Test public void isValidInputValidationExceptionReturnsFalse() throws Exception { doThrow(validationEx).when(spyStringRule).getValid(ArgumentMatchers.anyString(), ArgumentMatchers.anyString()); @@ -198,7 +198,7 @@ public void isValidInputValidationExceptionReturnsFalse() throws Exception { verify(spyStringRule, times(1)).setCanonicalize(true); verify(spyStringRule, times(1)).getValid(contextStr, testName.getMethodName()); } - + @Test public void isValidInputValidationExceptionErrorListReturnsFalse() throws Exception { ValidationErrorList errorList = new ValidationErrorList(); @@ -216,7 +216,7 @@ public void isValidInputValidationExceptionErrorListReturnsFalse() throws Except verify(spyStringRule, times(1)).setCanonicalize(true); verify(spyStringRule, times(1)).getValid(contextStr, testName.getMethodName()); } - + @Test public void canonicalizeSettingPassedThrough() throws Exception { String safeValue = uit.getValidInput(contextStr, testName.getMethodName(), testValidatorType, testMaximumLength, false,false); diff --git a/src/test/java/org/owasp/esapi/reference/EncoderTest.java b/src/test/java/org/owasp/esapi/reference/EncoderTest.java index 261e51fa9..ff340088d 100644 --- a/src/test/java/org/owasp/esapi/reference/EncoderTest.java +++ b/src/test/java/org/owasp/esapi/reference/EncoderTest.java @@ -1,15 +1,15 @@ /** * 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 */ @@ -52,11 +52,11 @@ /** * The Class EncoderTest. - * + * * @author Jeff Williams (jeff.williams@aspectsecurity.com) */ public class EncoderTest extends TestCase { - + private static class Conf extends SecurityConfigurationWrapper { private final List codecList; @@ -79,25 +79,25 @@ public List getDefaultCanonicalizationCodecs() } } private static final String PREFERRED_ENCODING = "UTF-8"; - + /** * Instantiates a new encoder test. - * + * * @param testName * the test name */ public EncoderTest(String testName) { super(testName); } - + /** * {@inheritDoc} - * @throws Exception + * @throws Exception */ protected void setUp() throws Exception { // none } - + /** * {@inheritDoc}s * @throws Exception @@ -105,20 +105,20 @@ protected void setUp() throws Exception { protected void tearDown() throws Exception { ESAPI.override(null); // Restore } - + /** * Suite. - * + * * @return the test */ public static Test suite() { - TestSuite suite = new TestSuite(EncoderTest.class); + TestSuite suite = new TestSuite(EncoderTest.class); return suite; } - + /** * Test of canonicalize method, of class org.owasp.esapi.Encoder. - * + * * @throws EncodingException */ public void testCanonicalize() throws EncodingException { @@ -128,7 +128,7 @@ public void testCanonicalize() throws EncodingException { list.add( "HTMLEntityCodec" ); list.add( "PercentCodec" ); Encoder instance = new DefaultEncoder( list ); - + // Test null paths assertEquals( null, instance.canonicalize(null)); assertEquals( null, instance.canonicalize(null, true)); @@ -137,7 +137,7 @@ public void testCanonicalize() throws EncodingException { assertEquals( null, instance.canonicalize(null, true, false)); assertEquals( null, instance.canonicalize(null, false, true)); assertEquals( null, instance.canonicalize(null, false, false)); - + // test exception paths assertEquals( "%", instance.canonicalize("%25", true)); assertEquals( "%", instance.canonicalize("%25", false)); @@ -152,7 +152,7 @@ public void testCanonicalize() throws EncodingException { assertEquals( "<", instance.canonicalize("<")); assertEquals( "<", instance.canonicalize("<")); assertEquals( "<", instance.canonicalize("<")); - + assertEquals( "%", instance.canonicalize("%")); assertEquals( "%", instance.canonicalize("%")); assertEquals( "%b", instance.canonicalize("%b")); @@ -239,10 +239,10 @@ public void testCanonicalize() throws EncodingException { assertEquals( "<", instance.canonicalize("<")); assertEquals( "&", instance.canonicalize("&")); assertEquals( "〈", instance.canonicalize("&lang")); - + assertEquals( "", instance.canonicalize("%3Cscript%3Ealert%28%22hello%22%29%3B%3C%2Fscript%3E") ); assertEquals( "", instance.canonicalize("%3Cscript>alert%28%22hello"%29%3B%3C%2Fscript%3E", false) ); - + // javascript escape syntax ArrayList js = new ArrayList(); js.add( "JavaScriptCodec" ); @@ -260,7 +260,7 @@ public void testCanonicalize() throws EncodingException { assertEquals( "\"", instance.canonicalize("\\\"")); assertEquals( "\\", instance.canonicalize("\\\\")); assertEquals( "\\<", instance.canonicalize("\\<")); - + assertEquals( "<", instance.canonicalize("\\u003c")); assertEquals( "<", instance.canonicalize("\\U003c")); assertEquals( "<", instance.canonicalize("\\u003C")); @@ -288,10 +288,10 @@ public void testCanonicalize() throws EncodingException { assertEquals( "<", instance.canonicalize("\\00003C")); } - + /** * Test of canonicalize method, of class org.owasp.esapi.Encoder. - * + * * @throws EncodingException */ public void testDoubleEncodingCanonicalization() throws EncodingException { @@ -301,12 +301,12 @@ public void testDoubleEncodingCanonicalization() throws EncodingException { // note these examples use the strict=false flag on canonicalize to allow // full decoding without throwing an IntrusionException. Generally, you // should use strict mode as allowing double-encoding is an abomination. - + // double encoding examples assertEquals( "<", instance.canonicalize("&lt;", false )); //double entity assertEquals( "\\", instance.canonicalize("%255c", false)); //double percent assertEquals( "%", instance.canonicalize("%2525", false)); //double percent - + // double encoding with multiple schemes example assertEquals( "<", instance.canonicalize("%26lt%3b", false)); //first entity, then percent assertEquals( "&", instance.canonicalize("%26", false)); //first percent, then entity @@ -319,19 +319,19 @@ public void testDoubleEncodingCanonicalization() throws EncodingException { //enforce multiple but not mixed encoding detection try { - instance.canonicalize("%252525253C", true, false); + instance.canonicalize("%252525253C", true, false); fail("Multiple encoding not detected"); } catch (IntrusionException ie) {} //enforce mixed but not multiple encoding detection try { - instance.canonicalize("%25 %2526 %26#X3c;script> %3Cscript%25252525253e", false, true); + instance.canonicalize("%25 %2526 %26#X3c;script> %3Cscript%25252525253e", false, true); fail("Mixed encoding not detected"); } catch (IntrusionException ie) {} //enforce niether mixed nor multiple encoding detection -should canonicalize but not throw an error - assertEquals( "< < < < < < <", instance.canonicalize("%26lt; %26lt; %3c %3c %2526lt%253B %2526lt%253B %2526lt%253B", - false, false)); + assertEquals( "< < < < < < <", instance.canonicalize("%26lt; %26lt; %3c %3c %2526lt%253B %2526lt%253B %2526lt%253B", + false, false)); // nested encoding examples assertEquals( "<", instance.canonicalize("%253c", false)); //nested encode % with percent @@ -340,11 +340,11 @@ public void testDoubleEncodingCanonicalization() throws EncodingException { assertEquals( "<", instance.canonicalize("%3%63", false)); //nested encode second nibble with percent assertEquals( "<", instance.canonicalize("&lt;", false)); //nested encode l with entity assertEquals( "<", instance.canonicalize("%253c", false)); //triple percent, percent, 5 with entity - + // nested encoding with multiple schemes examples assertEquals( "<", instance.canonicalize("&%6ct;", false)); // nested encode l with percent - assertEquals( "<", instance.canonicalize("%3c", false)); //nested encode 3 with entity - + assertEquals( "<", instance.canonicalize("%3c", false)); //nested encode 3 with entity + // multiple encoding tests assertEquals( "% & load=alert()", "Test. ", @@ -165,6 +177,12 @@ public void testGetValidSafeHTML() throws Exception { } } + /** + * @deprecated because Validator.isValidSafeHTML is deprecated. + * @see org.owasp.esapi.Validator#isValidSafeHTML(String,String,int,boolean) + * @see org.owasp.esapi.Validator#isValidSafeHTML(String,String,int,boolean,org.owasp.esapi.ValidationErrorList) + */ + @Deprecated @Test public void testIsValidSafeHTML() { System.out.println("isValidSafeHTML"); diff --git a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java index 279573727..b5d516456 100644 --- a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java +++ b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java @@ -34,7 +34,17 @@ import org.junit.After; import org.junit.Rule; import org.junit.rules.ExpectedException; -import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.both; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * The Class HTMLValidationRuleCleanTest. @@ -49,11 +59,14 @@ * Validator.HtmlValidationAction * is set to "clean", which causes certain calls to * ESAPI.validator().getValidSafeHTML() or ESAPI.validator().isValidSafeHTML() - * to simply log a warning and return the cleansed (sanitizied) output rather + * to simply log a warning and return the cleansed (sanitized) output rather * than throwing a ValidationException when certain unsafe input is * encountered. + * + * @author kevin.w.wall@gmail.com */ public class HTMLValidationRuleCleanTest { + private static SecurityConfiguration origConfig = ESAPI.securityConfiguration(); private static class ConfOverride extends SecurityConfigurationWrapper { private String desiredReturn = "clean"; @@ -76,7 +89,7 @@ public String getStringProp(String propName) { /** - * Default construstor that instantiates a new {@code HTMLValidationRule} test. + * Default constructor that instantiates a new {@code HTMLValidationRule} test. */ public HTMLValidationRuleCleanTest() { } @@ -89,14 +102,14 @@ public void tearDown() throws Exception { @Before public void setUp() throws Exception { ESAPI.override( - new ConfOverride( ESAPI.securityConfiguration(), "clean" ) + new ConfOverride( origConfig, "clean" ) ); } @Test public void testGetValidSafeHTML() throws Exception { - System.out.println("getValidSafeHTML"); + System.out.println("testGetValidSafeHTML"); Validator instance = ESAPI.validator(); ValidationErrorList errors = new ValidationErrorList(); @@ -121,27 +134,20 @@ public void testGetValidSafeHTML() throws Exception { assertEquals("Test. alert(document.cookie)", rule.getSafe("test", "Test. alert(document.cookie)")); assertEquals("Test. alert(document.cookie)", rule.getSafe("test", "Test. alert(document.cookie)")); assertEquals("Test. alert(document.cookie)", rule.getSafe("test", "Test. alert(document.cookie)")); - // TODO: ENHANCE waiting for a way to validate text headed for an attribute for scripts - // This would be nice to catch, but just looks like text to AntiSamy - // assertFalse(instance.isValidSafeHTML("test", "\" onload=\"alert(document.cookie)\" ")); - // String result4 = instance.getValidSafeHTML("test", test4); - // assertEquals("", result4); } - // FIXME: Change the method name to reflect the CVE once we have a number for this. - // Test to confirm that CVE-2022-xxxxx (TBD) is fixed. The cause of this was - // from a subtle botched regex for 'onsiteURL' in all the versions of + // Test to confirm that CVE-2022-24891 is fixed in ESAPI. The cause of this was + // from a subtly botched regex for 'onsiteURL' in all the versions of // antsamy-esapi.xml that had been there as far back as ESAPI 1.4! // - // This TBD CVE should arguably get the same CVSSv3 store as the AntiSamy - // CVE-2021-35043 as the are very similar. + // This CVE should arguably get the same CVSSv3 score as the AntiSamy + // CVE-2021-35043 as they are very similar. // - // Updated: Requested CVE from GitHub CNA on 4/23/2022. See + // Updated: Requested CVE from GitHub CNA on 4/23/2022. See also // https://github.com/ESAPI/esapi-java-legacy/security/advisories/GHSA-q77q-vx4q-xx6q - // (Which may not be published yet, but is remediated. Waiting on CVE ID to publish.) @Test - public void testJavaScriptURL() throws Exception { - System.out.println("testJavaScriptURL"); + public void testESAPI_CVE_2022_24891() throws Exception { + System.out.println("testESAPI_CVE_2022_24891"); String expectedSafeText = "This is safe from XSS. Trust us!"; String badVoodoo = "" + expectedSafeText + ""; @@ -155,26 +161,129 @@ public void testJavaScriptURL() throws Exception { // it was never really "broken" in ESAPI's "default configuration" because it is // triggers an Intrusion Detection when it is checking the canonicalization // and the ':' trips it up, that that's pretty much irrelevant given - // the (TBD) CVE mented in the previous test case. + // the CVE mentioned in the previous test case. // // Note: This test assumes a standard default ESAPI.properties file. In // particular, the normal canonicalization has to be enabled. - public void testAntiSamyCVE_2021_35043Fixed() { - System.out.println("testAntiSamyCVE_2021_35043Fixed"); + // + public void testAntiSamy_CVE_2021_35043Fixed() throws Exception { + System.out.println("testAntiSamy_CVE_2021_35043Fixed"); String expectedSafeText = "This is safe from XSS. Trust us!"; // Translates to '" + expectedSafeText + ""; Validator instance = ESAPI.validator(); - // ValidationErrorList errorList = new ValidationErrorList(); - boolean result = instance.isValidSafeHTML("CVE-2021-35043", badVoodoo, 200, false); - assertTrue( result ); + String cleansed = instance.getValidSafeHTML("CVE-2021-35043", badVoodoo, 200, false); + assertEquals( "", cleansed ); + } + + ////////// New AntiSamy tests added to ESAPI 2.5.3.0 ////////// + // Some of these were with the new XSS discoveries in AntiSamy. + // Sebastian doesn't think thta ESAPI should be vulnerable to these 2. (They weren't.) + @Test + public void testQuotesInsideStyles() throws Exception { + System.out.println("testQuotesInsideStyles"); + Validator instance = ESAPI.validator(); + ValidationErrorList errors = new ValidationErrorList(); + + // Added this test because of a fix to AntiSamy that doesn't seem to have affected ESAPI because of our + // very restrictive default AntiSamy policy file. However, with some of AntiSamy policy files, this used + // to cause any quoted (double or single) string identifier in CSS was being enclosed in quotes. + // That resulted in quotes enclosed by more quotes in some cases without any kind of escape or + // transformation. It never did that for ESAPI, but it seemed like a good test to add. + String input = + "Safe Text"; + String expected = "Safe Text"; // We expect the span tag to be completely filtered out & only the tag contents to remain. + String output = instance.getValidSafeHTML("testQuotesInsideStyles-1", input, 250, false); + assertEquals(expected, output); + + input = "Safe Text"; // Slight variation + output = instance.getValidSafeHTML("testQuotesInsideStyle-2", input, 250, false); + assertEquals(expected, output); + + assertTrue(errors.size() == 0); } + @Test + public void testSmuggledTagsInStyleContentCase() throws Exception { + System.out.println("testSmuggledTagsInStyleContentCase"); + + Validator instance = ESAPI.validator(); + ValidationErrorList errors = new ValidationErrorList(); + + // Style tag processing was not handling correctly the value set to its child node that should + // be only text. On some mutation scenarios due to filtering tags by default, content was being + // smuggled and not properly sanitized by the output serializer. + // + // Not expected to affect ESAPI because our default AntiSamy policy file does NOT have: + // + // in it. + // + String input = "Safe stuff"; + String output = null; + String expected = null; + try { + expected = "Safe<listing/>]]><noembed> stuff"; + output = instance.getValidSafeHTML("testSmuggledTagsInStyleContentCase-1", input, 250, false, errors); + } catch (IntrusionException ex) { + fail("testSmuggledTagsInStyleContentCase-1 - should not happen."); + } + assertTrue(errors.size() == 0); + assertEquals(expected, output); + + input = "Safe' stuff"; + try { + expected = "Safe<math>'<noframes >' stuff"; + output = instance.getValidSafeHTML("testSmuggledTagsInStyleContentCase-2", input, 250, false, errors); + } catch (IntrusionException ex) { + fail("testSmuggledTagsInStyleContentCase-2 - should not happen."); + } + assertTrue(errors.size() == 0); + assertEquals(expected, output); + } + + @Test + public void testAntiSamy_CVE_2023_43643() { + System.out.println("testAntiSamy_CVE_2023_43643"); + // These are new tests are variations from AntiSamy 1.7.4 and were associted with CVE-2023-43643. (See + // https://github.com/nahsra/antisamy/security/advisories/GHSA-pcf2-gh6g-h5r2 for additional details.) + // The concern is that when preserving comments, certain tags would get their content badly parsed + // due to mutation XSS. Note that AntiSamy 1.7.3 and earlier had problems (depending on it's + // AntiSamy policy file) for all these constructs, but ESAPI using AntiSamy 1.7.3 had no vulnerabilities + // because our antisamy-esapi.xml AntiSamy policy file is much stricter. Regardless, these make good + // additions to our test suite. + String[] payloads = { + "

    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 diff --git a/documentation/ESAPI-release-steps.pdf b/documentation/ESAPI-release-steps.pdf index 714f8dc0b5948cfffca0d9ad4927d1eef9339c03..53a30565ca5127518826ca78dea39612ff814464 100644 GIT binary patch delta 209656 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≤ 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 delta 215544 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%0D6d$Af+? zJVbajVIU;8%|gE0INR)(Vlea|@nYSF`cY79Y;`LMC-jALYy&7e)K|EpipbOX(p+Bg zL*`RpEEm^3sVOZb9<}QjB^9E2qSFzf7%o})6HeL?vl^0r2{5-X`Dc6S7_ckx_CcW{ z%o;KkH=s>S&A(lKPA*#O_EB>L3+ZM0m0|Mm9&a z-o6gH`UJl|&yuKQ;DzrVPFCU=%fiBJ##o3huRaWh;oR9Uc_%IVRv59ogtfJR;CE(8 z%`TLD$;dZ*Ank@o=N5uG0)D04RQ`a32R|+Shf_t!r~;%N$lB0*U+SocI6*7+4m8M! z*yh!@Qikh+89|(xoae=Ge6q2rkEEBewo_v>yWlg;ViGO zBPPveRlGdoth2je)g-K&!`Bp5XLQbGR=m`YuJhy_wb0dZ?(}W)Z}0H$>}+% zsEnEVD7=pRK(#+V&szn17MX0RwY~h!GSCG2dj;siy-*95;H-qKt6s=ghZVL)zw1(^ z^u4&#?|+tVkx^AdZMQ6bu{KjQ%^xaDx~J*UTz__ifXDP5ZFroi8rNeBtKLoam<%<} zwm$ZQ|5^`FMj-i9`gr$zGIaEOd)0_!qz)y}siPQ@KSu@Dte`h|aF{AJBxq8iD3-uQ z(g*N(HM{M3qyf`4RS+vC4pq#L!1uOIFeBruNAmfljTcu<6-BD}ilEJkiP3J3p&UH! zD;Aij#QP4PTs^o?!lNk0tlCTp(Zdj$f2<|NWwlEt1!TNa+3!7a*0VP?mLpCX*A$kig8*xi}0rv%^}?@-3~e|hD#F2s~Fii7xI(sP}X+ufj+ zZbSU>e#_Bt$h!v2sI7^hgOL1?uV=33FEY*G(c~+kWP0t?qs-&%kQgtOsq^A1FwEK)gSTF!?a{HgYC06i0KI>?L-#Dnr(cHWUY0@oA?#3-P1x{5ZR^9Ia3 z<5|KkxOOcpy~8*K8pmyt0_btZq!3hxkmG{*tS*^FH#p}IZ*p@5w|lzzHc6GmbSWks zki>6YuoiOW(JHkd$*?VES$5#%>qrz#A65mNC8aOvq(1M(OWmq?(--1P$dLJBjKY~14|C3HP4+CeRu-5P}V zAP+553Bu_CGs5BO1lUVvIDjB{PDrI!~j zsrK@Zphc}$xFRmU$Mm12D7-!ry+QkD-189G?z(z9oYj(WxZY&(9qLC1TY$ z-e>n~(L!wZHP{|(#&30|XTkj8T9zdKat)6gTH0JCyG)sFlsueUkb#rJ=Gm4?HjI;1?BuUTIr-2svfDUKm%{NHktod{@rcRM zlAfL09*`3mWWWf7jmr9xmw&j+6<7EfQK^@#=*3kO%XgMN$;YSA$I`dp%}C3%t_;jH zqNUXASF!-_1E8V#%cYQq_rYKS6Ts&?W{pGy1uYVbj<-9!FK1mHj=q!h&I_>{@`VkY zlsjJ43WDf3e?MI;!J?I|n=kj5+F%C;zhq3k#wOxx>k;K`Vv=_A$5Awex*5BKAv%o} zIRRWa5P?B16LgJFDW6oH)=ZcVZDcT7;*wNH(vKx*5Wp}KhzGK#ngngMam1ZOv~c-~ z*fW0jlH9f{lhdjRvfMOnERE82Rv^K-qX!CHA-(2qG-CZcfOeZMp&=M5+-iCjK_oPr z?0z`|y)h1QgNXMbgo7OpThnfYov0^0m|*Dw>Ih~sT=(1!A`Ceaaw7$+W7dKgyk(P! zP^8A{0;rRQg%V>1Ls%B^8$u(6aRri7zs1-701@M!bfZc#!y#jqagD!@^0c|8^jC2Q z6uyDI4O)x9fB!=T5`_)OrDZoA%wq?8;*tgQ)&@eJ7BOvS!nYwS$tre!K;5|85|P0|bh)XHxqbe3$BjmZHrTV7##pEqcH7nW8?MTZ8;wkQycNO8J$o1lHU& z3-HT1OBU7)U&3lem>T10^q)O&PdA(sWs;`h&~xWiP8lJ8bTldLP!o~Jv9XGZw!2_0 zRi$;cTuw0=7XXbSr#`q0{!Zs)%y&M$)%(ff%E(E

    iVFV`?L-z9R@c(2k1&3$_mM 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 l1nLt6jdf%?uj~KzHf98CLw@!X!^fvPCx_^FT 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 UK6`vMW7Tvio87*>xqmr(3(i#24FCWD From 0ebbe721ce080408efe12f8b8fe92f73a5a1ab4f Mon Sep 17 00:00:00 2001 From: kwwall Date: Wed, 29 Nov 2023 22:54:53 -0500 Subject: [PATCH 103/197] New ESAPI 2.5.3.1 release notes. (Initial version.) --- .../esapi4java-core-2.5.3.1-release-notes.txt | 184 ++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 documentation/esapi4java-core-2.5.3.1-release-notes.txt diff --git a/documentation/esapi4java-core-2.5.3.1-release-notes.txt b/documentation/esapi4java-core-2.5.3.1-release-notes.txt new file mode 100644 index 000000000..93def68c6 --- /dev/null +++ b/documentation/esapi4java-core-2.5.3.1-release-notes.txt @@ -0,0 +1,184 @@ +Release notes for ESAPI 2.5.3.1 + Release date: 2023-12-01 + Project leaders: + -Kevin W. Wall + -Matt Seil + +Previous release: ESAPI 2.5.3.0, 2023-11-24 + + +Executive Summary: Important Things to Note for this Release +------------------------------------------------------------ +* Rewrite the Javadoc for Validator.isValidSafeHTML to make the dangers more evident.\ +* Changes to the DefaultValidator.isValidSafeHTM method so that a warning is always logs one time about the method being deprecated and a reference to the relevant GitHub Security Advisory. + +Notes if you are not updating from the immediate previous release. release 2.5.3.0: + * You need to read through the series of release notes FIRST, going in order. + * For example, if you were updating from an older ESAPI release (say, 2.3.0.0), you should go back and FIRST read all the subsequent release notes in turn. For instance, if you are currently on release 2.3.0.0 and upgrading to (say) release 2.x.y.z, you should MINIMALLY read the sections "Changes Requiring Special Attention" in each of the subsequent release notes. So, going from release 2.3.0.0 to 2.x.y.z, you should in turn, read: + + esapi4java-core-2.4.0.0-release-notes.txt + esapi4java-core-2.5.0.0-release-notes.txt + esapi4java-core-2.5.1.0-release-notes.txt + esapi4java-core-2.5.2.0-release-notes.txt + ...etc., up through the current set of release notes... + esapi4java-core-2.x.y.z-release-notes.txt + +in that order. YOU HAVE BEEN WARNED!!! (These release notes are too large to put all this in a given document; very few read them thoroughly as it is.) + +If your SCA tool is reporting any CVE from a direct or transitive dependency in ESAPI, before reporting it as an GitHub issue, please make sure that you review the vulnerability analysis written up in https://github.com/ESAPI/esapi-java-legacy/blob/develop/Vulnerability-Summary.md. Please email us or contact us in our GitHub Discussions page if you have questions about this. See also the SECURITY.md file to report any security issues with ESAPI. + +You are encouraged to review the vulnerability analysis written up in https://github.com/ESAPI/esapi-java-legacy/blob/develop/Vulnerability-Summary.md and email us or contact us in our GitHub Discussions page if you have questions. + + +================================================================================================================= + +Basic ESAPI facts +----------------- + +ESAPI 2.5.3.0 release: + 207 Java source files + 4293 JUnit tests in 131 Java source files (0 failures, 0 errors, 0 tests skipped) + +ESAPI 2.5.3.1 release: (unchanged) + 207 Java source files + 4293 JUnit tests in 131 Java source files (0 failures, 0 errors, 0 tests skipped) + +1 GitHub Issue closed in this release, including those we've decided not to fix (marked 'wontfix' and 'falsepositive'). +(Reference: https://github.com/ESAPI/esapi-java-legacy/issues?q=is%3Aissue+state%3Aclosed+updated%3A%3E%3D2023-11-24) + +Issue # GitHub Issue Title +---------------------------------------------------------------------------------------------- +794 canonicalize sees entity which isn't there (wontfix) + +----------------------------------------------------------------------------- + + Changes Requiring Special Attention + +----------------------------------------------------------------------------- + +Important JDK Support Announcement +* ESAPI 2.3.0.0 was the last Java release to support Java 7. ESAPI 2.4.0 requires using Java 8 or later. See the ESAPI 2.4.0.0 release notes (https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.4.0.0-release-notes.txt) for details as to the reason. + - This means if your project requires Java 7, you must use ESAPI 2.3.0.0 or earlier. + +Important ESAPI Logging Changes + +* Since ESAPI 2.5.0.0, support for logging directly via Log4J 1 has been removed. (This was two years after it haveing first been deprecated.) Thus, you only choice of ESAPI logging are + - java.util.logging (JUL), which as been the default since ESAPI 2.2.1.0. + * Set ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory in your ESAPI.properties file. + - SLF4J (which your choice of supported SLF4J logging implemmentation) + * Set ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory in your ESAPI.properties file. +* Logger configuration notes - If you are migrating from prior to ESAPI 2.2.1.1, you will need to update your ESAPI.properties file as logging-related configuration as per the ESAPI 2.2.1.1 release notes, which may be found at: + https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.2.1.1-release-notes.txt#L39-L78 + +If you use ESAPI 2.5.0.0 or later, you will get an ClassNotFoundException as the root cause if you still have your ESAPI.Logger property set to use Log4J because the org.owasp.esapi.logger.log4j.Log4JFactory class has been completely removed from the ESAPI jar. If you are dead set on continuing to use Log4J 1, you ought to be able to do so via SLF4J. The set up for Log4J 1 (which has not be tested), should be similar to configure ESAPI to use SLF4J with Log4J 2 as described here: + https://github.com/ESAPI/esapi-java-legacy/wiki/Using-ESAPI-with-SLF4J#slf4j-using-log4j-2x + +----------------------------------------------------------------------------- + + Remaining Known Issues / Problems + +----------------------------------------------------------------------------- +None known, other than the remaining open issues on GitHub. + +----------------------------------------------------------------------------- + + Other changes in this release, some of which not tracked via GitHub issues + +----------------------------------------------------------------------------- + +* Minor updates to README.md file with respect to version information. + +----------------------------------------------------------------------------- + +Developer Activity Report (Changes between release 2.5.3.0 and 2.5.3.1, i.e., between 2023-11-24 and 2023-12-01) +Generated manually (this time) -- all errors are the fault of kwwall and his inability to do simple arithmetic. + +Developer Total Total Number # Merged +(GitHub ID) commits of Files Changed PRs +======================================================== +kwwall 13 16 2 +======================================================== + Total PRs: 2 + +----------------------------------------------------------------------------- + +CHANGELOG: Create your own. May I suggest: + + git log --stat --since=2023-11-24 --reverse --pretty=medium + + which will show all the commits since just after the previous (2.5.3.0) release. + + Alternately, you can download the most recent ESAPI source and run + + mvn site + + which will create a CHANGELOG file named 'target/site/changelog.html' + + +----------------------------------------------------------------------------- + +Direct and Transitive Runtime and Test Dependencies: + + $ mvn -B dependency:tree + ... + [INFO] --- maven-dependency-plugin:3.6.1:tree (default-cli) @ esapi --- + [INFO] org.owasp.esapi:esapi:jar:2.5.3.0 + [INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided + [INFO] +- javax.servlet.jsp:javax.servlet.jsp-api:jar:2.3.3:provided + [INFO] +- xom:xom:jar:1.3.9:compile + [INFO] +- commons-beanutils:commons-beanutils:jar:1.9.4:compile + [INFO] | +- commons-logging:commons-logging:jar:1.2:compile + [INFO] | \- commons-collections:commons-collections:jar:3.2.2:compile + [INFO] +- commons-configuration:commons-configuration:jar:1.10:compile + [INFO] +- commons-lang:commons-lang:jar:2.6:compile + [INFO] +- commons-fileupload:commons-fileupload:jar:1.5:compile + [INFO] +- org.apache.commons:commons-collections4:jar:4.4:compile + [INFO] +- org.apache-extras.beanshell:bsh:jar:2.0b6:compile + [INFO] +- org.owasp.antisamy:antisamy:jar:1.7.4:compile + [INFO] | +- org.htmlunit:neko-htmlunit:jar:3.6.0:compile + [INFO] | +- org.apache.httpcomponents.client5:httpclient5:jar:5.2.1:compile + [INFO] | | \- org.apache.httpcomponents.core5:httpcore5-h2:jar:5.2:compile + [INFO] | +- org.apache.httpcomponents.core5:httpcore5:jar:5.2.3:compile + [INFO] | +- org.apache.xmlgraphics:batik-css:jar:1.17:compile + [INFO] | | +- org.apache.xmlgraphics:batik-shared-resources:jar:1.17:compile + [INFO] | | +- org.apache.xmlgraphics:batik-util:jar:1.17:compile + [INFO] | | | +- org.apache.xmlgraphics:batik-constants:jar:1.17:compile + [INFO] | | | \- org.apache.xmlgraphics:batik-i18n:jar:1.17:compile + [INFO] | | \- org.apache.xmlgraphics:xmlgraphics-commons:jar:2.9:compile + [INFO] | +- xerces:xercesImpl:jar:2.12.2:compile + [INFO] | \- xml-apis:xml-apis-ext:jar:1.3.04:compile + [INFO] +- org.slf4j:slf4j-api:jar:2.0.6:compile + [INFO] +- xml-apis:xml-apis:jar:1.4.01:compile + [INFO] +- commons-io:commons-io:jar:2.14.0:compile + [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.8.1:compile + [INFO] | \- com.google.code.findbugs:jsr305:jar:3.0.2:compile + [INFO] +- commons-codec:commons-codec:jar:1.15:test + [INFO] +- junit:junit:jar:4.13.2:test + [INFO] +- org.bouncycastle:bcprov-jdk15on:jar:1.70:test + [INFO] +- org.hamcrest:hamcrest-core:jar:2.2:test + [INFO] | \- org.hamcrest:hamcrest:jar:2.2:test + [INFO] +- org.powermock:powermock-api-mockito2:jar:2.0.9:test + [INFO] | \- org.powermock:powermock-api-support:jar:2.0.9:test + [INFO] +- org.mockito:mockito-core:jar:3.12.4:test + [INFO] | +- net.bytebuddy:byte-buddy:jar:1.11.13:test + [INFO] | +- net.bytebuddy:byte-buddy-agent:jar:1.11.13:test + [INFO] | \- org.objenesis:objenesis:jar:3.2:test + [INFO] +- org.powermock:powermock-core:jar:2.0.9:test + [INFO] | \- org.javassist:javassist:jar:3.27.0-GA:test + [INFO] +- org.powermock:powermock-module-junit4:jar:2.0.9:test + [INFO] | \- org.powermock:powermock-module-junit4-common:jar:2.0.9:test + [INFO] +- org.powermock:powermock-reflect:jar:2.0.9:test + [INFO] \- org.openjdk.jmh:jmh-core:jar:1.37:test + [INFO] +- net.sf.jopt-simple:jopt-simple:jar:5.0.4:test + [INFO] \- org.apache.commons:commons-math3:jar:3.6.1:test + ... + + ----------------------------------------------------------------------------- + +Acknowledgments: + Another hat tip to Dave Wichers for suggesting logging a warning via the deprecated isValidSafeHTML method. + And, as always, thanks to Matt Seil, Jeremiah Stacey, and all the ESAPI users who make this worthwhile. This is for you. + +A special thanks to the ESAPI community from the ESAPI project co-leaders: + Kevin W. Wall (kwwall) <== The irresponsible party for these release notes! + Matt Seil (xeno6696) From 9fb6366b34e035ca3af2748b9c5ef19f893f7048 Mon Sep 17 00:00:00 2001 From: kwwall Date: Thu, 30 Nov 2023 22:35:50 -0500 Subject: [PATCH 104/197] Update dependency tree. --- documentation/esapi4java-core-2.5.3.1-release-notes.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/documentation/esapi4java-core-2.5.3.1-release-notes.txt b/documentation/esapi4java-core-2.5.3.1-release-notes.txt index 93def68c6..810cb55ca 100644 --- a/documentation/esapi4java-core-2.5.3.1-release-notes.txt +++ b/documentation/esapi4java-core-2.5.3.1-release-notes.txt @@ -96,7 +96,7 @@ Generated manually (this time) -- all errors are the fault of kwwall and his ina Developer Total Total Number # Merged (GitHub ID) commits of Files Changed PRs ======================================================== -kwwall 13 16 2 +kwwall 14 16 2 ======================================================== Total PRs: 2 @@ -122,7 +122,7 @@ Direct and Transitive Runtime and Test Dependencies: $ mvn -B dependency:tree ... [INFO] --- maven-dependency-plugin:3.6.1:tree (default-cli) @ esapi --- - [INFO] org.owasp.esapi:esapi:jar:2.5.3.0 + [INFO] org.owasp.esapi:esapi:jar:2.5.3.1 [INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided [INFO] +- javax.servlet.jsp:javax.servlet.jsp-api:jar:2.3.3:provided [INFO] +- xom:xom:jar:1.3.9:compile @@ -150,9 +150,9 @@ Direct and Transitive Runtime and Test Dependencies: [INFO] +- org.slf4j:slf4j-api:jar:2.0.6:compile [INFO] +- xml-apis:xml-apis:jar:1.4.01:compile [INFO] +- commons-io:commons-io:jar:2.14.0:compile - [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.8.1:compile + [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.8.2:compile [INFO] | \- com.google.code.findbugs:jsr305:jar:3.0.2:compile - [INFO] +- commons-codec:commons-codec:jar:1.15:test + [INFO] +- commons-codec:commons-codec:jar:1.16.0:test [INFO] +- junit:junit:jar:4.13.2:test [INFO] +- org.bouncycastle:bcprov-jdk15on:jar:1.70:test [INFO] +- org.hamcrest:hamcrest-core:jar:2.2:test From 7823a879289e800e975b177a96cc3f57cc211da9 Mon Sep 17 00:00:00 2001 From: kwwall Date: Thu, 30 Nov 2023 22:36:24 -0500 Subject: [PATCH 105/197] Remove '-SNAPSHOT' from release and update plugins & test dependencies. --- pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 6fd648711..0ff01bd4e 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.owasp.esapi esapi - 2.5.3.1-SNAPSHOT + 2.5.3.1 jar @@ -134,8 +134,8 @@ 2.0.0-M3 2.0.0-M8 2.0.9 - 4.8.1 - 4.8.1.0 + 4.8.2 + 4.8.2.0 3.2.2 1.8 @@ -296,7 +296,7 @@ commons-codec commons-codec - 1.15 + 1.16.0 test @@ -689,7 +689,7 @@ The skin is referenced in src/site/site.xml. --> org.apache.maven.plugins maven-site-plugin - 4.0.0-M11 + 4.0.0-M12 org.apache.maven.skins From 1707588ef285bfa1291b4c0d7565ddb404320704 Mon Sep 17 00:00:00 2001 From: kwwall Date: Thu, 30 Nov 2023 22:44:16 -0500 Subject: [PATCH 106/197] Update current release to 2.5.3.1 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b37f350cb..71a0f1f98 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Development for the "next generation" of ESAPI (starting with ESAPI 3.0), will b GitHub repository at [https://github.com/ESAPI/esapi-java](https://github.com/ESAPI/esapi-java). **IMPORTANT NOTES:** -* The default branch for ESAPI legacy is the 'develop' branch (rather than the 'main' (formerly 'master') branch), where future development, bug fixes, etc. are now being done. The 'main' branch is now marked as "protected"; it reflects the latest stable ESAPI release (2.5.3.0 as of this date). Note that this change of making the 'develop' branch the default may affect any pull requests that you were intending to make. +* The default branch for ESAPI legacy is the 'develop' branch (rather than the 'main' (formerly 'master') branch), where future development, bug fixes, etc. are now being done. The 'main' branch is now marked as "protected"; it reflects the latest stable ESAPI release (2.5.3.1 as of this date). Note that this change of making the 'develop' branch the default may affect any pull requests that you were intending to make. * Also, the *minimal* baseline Java version to use ESAPI is now Java 8. (This was changed from Java 7 during the 2.4.0.0 release.) * Support was dropped for Log4J 1 during ESAPI 2.5.0.0 release. If you need it, configure it via SLF4J. See the [2.5.0.0 release notes](https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.5.0.0-release-notes.txt) @@ -79,7 +79,7 @@ link to the specific release notes. Starting with release 2.4.0.0, Java 8 or later is required. # Locating ESAPI Jar files -The [latest ESAPI release](https://github.com/ESAPI/esapi-java-legacy/releases/latest) is 2.5.3.0. +The [latest ESAPI release](https://github.com/ESAPI/esapi-java-legacy/releases/latest) is 2.5.3.1. All the *regular* ESAPI jars, with the exception of the ESAPI configuration jar (i.e., esapi-2.#.#.#-configuration.jar) and its associated detached GPG signature, are available from Maven Central. The ESAPI configuration From 2136292c2225ca8ff770d85f41364873218b7ff5 Mon Sep 17 00:00:00 2001 From: kwwall Date: Fri, 1 Dec 2023 00:34:14 -0500 Subject: [PATCH 107/197] Modifying pom.xml for next planned release. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0ff01bd4e..25561233b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.owasp.esapi esapi - 2.5.3.1 + 2.5.4.0-SNAPSHOT jar From ddd2cda4e8b5cfd7441d8721a465b09dbaf3d4d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:33:01 -0500 Subject: [PATCH 108/197] Bump org.owasp:dependency-check-maven from 9.0.0 to 9.0.6 (#825) Bumps [org.owasp:dependency-check-maven](https://github.com/jeremylong/DependencyCheck) from 9.0.0 to 9.0.6. - [Release notes](https://github.com/jeremylong/DependencyCheck/releases) - [Changelog](https://github.com/jeremylong/DependencyCheck/blob/main/CHANGELOG.md) - [Commits](https://github.com/jeremylong/DependencyCheck/compare/v9.0.0...v9.0.6) --- updated-dependencies: - dependency-name: org.owasp:dependency-check-maven dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 25561233b..8a159d823 100644 --- a/pom.xml +++ b/pom.xml @@ -750,7 +750,7 @@ org.owasp dependency-check-maven - 9.0.0 + 9.0.6 ${env.NVD_API_KEY} 1.0 From a3a59dc3a6e030115c2aaf911c0076e272aa5523 Mon Sep 17 00:00:00 2001 From: Michele Preziuso Date: Thu, 29 Feb 2024 23:41:03 +0000 Subject: [PATCH 109/197] fix: upgrade Antisamy to 1.7.5 to resolve CVE-2024-23635 (#833) NOTICE: CVE-2024-23635 does NOT impact the default ESAPI deployment. --- pom.xml | 9 +++++++-- .../validation/HTMLValidationRuleCleanTest.java | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 8a159d823..c07caedc7 100644 --- a/pom.xml +++ b/pom.xml @@ -243,13 +243,18 @@ org.owasp.antisamy antisamy - 1.7.4 + 1.7.5 org.slf4j slf4j-api + + + commons-logging + commons-logging + @@ -281,7 +286,7 @@ --> commons-io commons-io - 2.14.0 + 2.15.1 diff --git a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java index b5d516456..c28d24f9d 100644 --- a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java +++ b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java @@ -362,6 +362,10 @@ public void testAntiSamyRegressionCDATAWithJavascriptURL() throws Exception { // // See AntiSamy GitHub issue #380 (https://github.com/nahsra/antisamy/issues/389) for more details. // + // The output has changed again as of AntiSamy 1.7.5. The expected output is now: + // Walert(1) + // See AntiSamy Release notes for 1.7.5 (https://github.com/nahsra/antisamy/releases/tag/v1.7.5) + // // Also, this test, which originally used Validator.isValidSafeHTML(), has been // changed to use Validator.getValidSafeHTML() instead because Validator.isValidSafeHTML() // has been deprecated. See GitHub Security Advisory @@ -375,7 +379,8 @@ public void testScriptTagAfterStyleClosing() throws Exception { ValidationErrorList errors = new ValidationErrorList(); String input = "Walert(1)"; // String expected = "W<script>alert(1)</script>"; // Before AntiSamy 1.7.4 - String expected = "W<xmp<script>alert(1)</script>"; // AntiSamy 1.7.4 (and later?) + // String expected = "W<xmp<script>alert(1)</script>"; // AntiSamy 1.7.4 + String expected = "Walert(1)"; // AntiSamy 1.7.5 (and later?) String output = instance.getValidSafeHTML("escaping style tag attack with script tag", input, 250, false, errors); assertEquals(expected, output); assertTrue(errors.size() == 0); @@ -392,6 +397,10 @@ public void testScriptTagAfterStyleClosing() throws Exception { // // See AntiSamy GitHub issue #380 (https://github.com/nahsra/antisamy/issues/389) for more details. // + // The output has changed again as of AntiSamy 1.7.5. The expected output is now: + // kinput/onfocus=alert(1)> + // See AntiSamy Release notes for 1.7.5 (https://github.com/nahsra/antisamy/releases/tag/v1.7.5) + // // Also, this test, which originally used Validator.isValidSafeHTML(), has been // changed to use Validator.getValidSafeHTML() instead because Validator.isValidSafeHTML() // has been deprecated. See GitHub Security Advisory @@ -405,7 +414,8 @@ public void testOnfocusAfterStyleClosing() throws Exception { String input = "kinput/onfocus=alert(1)>"; // String expected = "k<input/onfocus=alert(1)>"; // Before AntiSamy 1.7.4 - String expected = "k<input<</>input/onfocus=alert(1)>"; // AntiSamy 1.7.4 (and later?) + // String expected = "k<input<</>input/onfocus=alert(1)>"; // AntiSamy 1.7.4 + String expected = "kinput/onfocus=alert(1)>"; // AntiSamy 1.7.5 (and later?) String output = instance.getValidSafeHTML("escaping style tag attack with onfocus attribute", input, 250, false, errors); assertEquals(expected, output); assertTrue(errors.size() == 0); From 7a9ec0034d13dda94d5cb6b90ac7e65fa5fe85c1 Mon Sep 17 00:00:00 2001 From: jeremiahjstacey Date: Mon, 27 May 2024 12:26:57 -0500 Subject: [PATCH 110/197] Issue #839 JavaLogFactory ConcMod (#840) * Issue #839 JavaLogFactory ConcMod Removing support for esapi-java-logging.properties file from baseline. ConfigurationException is thrown if file is found on the path at runtime. Exception message links to a wiki page with instructions on how to configure the application instance. * JavaLogFactory Cleanup Removing unused imports. Consolidating String duplication to a class constant. --- .../esapi/esapi-java-logging.properties | 6 -- .../esapi/logging/java/JavaLogFactory.java | 61 +++++--------- .../logging/java/JavaLogFactoryTest.java | 82 ------------------- .../resources/esapi-java-logging.properties | 6 -- 4 files changed, 21 insertions(+), 134 deletions(-) delete mode 100644 configuration/esapi/esapi-java-logging.properties delete mode 100644 src/test/resources/esapi-java-logging.properties diff --git a/configuration/esapi/esapi-java-logging.properties b/configuration/esapi/esapi-java-logging.properties deleted file mode 100644 index 71011acc5..000000000 --- a/configuration/esapi/esapi-java-logging.properties +++ /dev/null @@ -1,6 +0,0 @@ -handlers= java.util.logging.ConsoleHandler -.level= INFO -java.util.logging.ConsoleHandler.level = INFO -java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%3$-7s] %5$s %n -#https://www.logicbig.com/tutorials/core-java-tutorial/logging/customizing-default-format.html \ No newline at end of file diff --git a/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java b/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java index 47502e16c..9ebd52d92 100644 --- a/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java +++ b/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java @@ -14,18 +14,23 @@ */ package org.owasp.esapi.logging.java; +import static org.owasp.esapi.PropNames.APPLICATION_NAME; +import static org.owasp.esapi.PropNames.LOG_APPLICATION_NAME; +import static org.owasp.esapi.PropNames.LOG_CLIENT_INFO; +import static org.owasp.esapi.PropNames.LOG_ENCODING_REQUIRED; +import static org.owasp.esapi.PropNames.LOG_SERVER_IP; +import static org.owasp.esapi.PropNames.LOG_USER_INFO; + import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.LogManager; import org.owasp.esapi.ESAPI; import org.owasp.esapi.LogFactory; import org.owasp.esapi.Logger; -import org.owasp.esapi.PropNames; import org.owasp.esapi.codecs.HTMLEntityCodec; import org.owasp.esapi.errors.ConfigurationException; import org.owasp.esapi.logging.appender.LogAppender; @@ -35,13 +40,6 @@ import org.owasp.esapi.logging.cleaning.LogScrubber; import org.owasp.esapi.logging.cleaning.NewlineLogScrubber; -import static org.owasp.esapi.PropNames.LOG_ENCODING_REQUIRED; -import static org.owasp.esapi.PropNames.LOG_USER_INFO; -import static org.owasp.esapi.PropNames.LOG_CLIENT_INFO; -import static org.owasp.esapi.PropNames.LOG_APPLICATION_NAME; -import static org.owasp.esapi.PropNames.APPLICATION_NAME; -import static org.owasp.esapi.PropNames.LOG_SERVER_IP; - /** * LogFactory implementation which creates JAVA supporting Loggers. *

    @@ -58,6 +56,8 @@ * */ public class JavaLogFactory implements LogFactory { + /**Consistent message offered as a part of the ConfigurationException which is thrown if esapi-java-logging.properties is found on the path. */ + private static final String PROPERTY_CONFIG_MSG = "esapi-java-logging.properties is no longer supported. See https://github.com/ESAPI/esapi-java-legacy/wiki/Configuring-the-JavaLogFactory for information on corrective actions."; /** Immune characters for the codec log scrubber for JAVA context.*/ private static final char[] IMMUNE_JAVA_HTML = {',', '.', '-', '_', ' ' }; /** Codec being used to clean messages for logging.*/ @@ -93,43 +93,24 @@ public class JavaLogFactory implements LogFactory { LOG_BRIDGE = new JavaLogBridgeImpl(JAVA_LOG_APPENDER, JAVA_LOG_SCRUBBER, levelLookup); - readLoggerConfiguration(LogManager.getLogManager()); - } - - /** - * Attempts to load the expected property file path into the provided LogManager reference. - * @param logManager LogManager which is being configured. - */ - /*package*/ static void readLoggerConfiguration(LogManager logManager) { - if (System.getProperties().keySet().stream().anyMatch(propKey -> - "java.util.logging.config.class".equals(propKey) || "java.util.logging.config.file".equals(propKey))) { - // LogManager has external configuration. Do not load ESAPI defaults. - // See javadoc for the LogManager class for more information on properties. - boolean isStartupSysoutDisabled = Boolean.valueOf(System.getProperty(PropNames.DISCARD_LOGSPECIAL, Boolean.FALSE.toString())); - if (!isStartupSysoutDisabled) { - String logManagerPreferredMsg = String.format("[ESAPI-STARTUP] ESAPI JavaLogFactory Configuration will not be applied. " - + "java.util.LogManager configuration Detected. " - + "{\"java.util.logging.config.class\":\"%s\",\"java.util.logging.config.file\":\"%s\"}", - System.getProperty("java.util.logging.config.class"), System.getProperty("java.util.logging.config.file")); - - System.out.println(logManagerPreferredMsg); - // ::SAMPLE OUTPUT:: - //[ESAPI-STARTUP] ESAPI JavaLogFactory Configuration will not be applied. java.util.LogManager configuration Detected.{"java.util.logging.config.class":"some.defined.value","java.util.logging.config.file":"null"} - } - - return; - } /* - * This will load the logging properties file to control the format of the output for Java logs. + * esapi-java-logging.properties file may lead to confusing logging behavior + * by overriding desired configurations provided through Java's LogManager class. + * + * Verify the file is not present and fail if found to enforce understanding of + * the configuration method. */ try (InputStream stream = JavaLogFactory.class.getClassLoader(). getResourceAsStream("esapi-java-logging.properties")) { - if (stream == null) { - throw new ConfigurationException("Unable to locate resource: esapi-java-logging.properties"); + if (stream != null) { + throw new ConfigurationException(PROPERTY_CONFIG_MSG); } - logManager.readConfiguration(stream); + } catch (IOException ioe) { - throw new ConfigurationException("Failed to load esapi-java-logging.properties.", ioe); + // This is a little strange, I know. + // If the IOException is thrown, then the file actually exists but is malformatted or has some other issue. + // The file should not exist at all, so use the same message as above but include the original exception in the log as well. + throw new ConfigurationException(PROPERTY_CONFIG_MSG, ioe); } } diff --git a/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java b/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java index 523660304..201a3c42a 100644 --- a/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java +++ b/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java @@ -14,12 +14,8 @@ */ package org.owasp.esapi.logging.java; -import java.io.IOException; -import java.io.InputStream; import java.util.List; -import java.util.logging.LogManager; -import org.hamcrest.CustomMatcher; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; @@ -28,7 +24,6 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.owasp.esapi.Logger; -import org.owasp.esapi.errors.ConfigurationException; import org.owasp.esapi.logging.appender.LogAppender; import org.owasp.esapi.logging.appender.LogPrefixAppender; import org.owasp.esapi.logging.cleaning.CodecLogScrubber; @@ -48,83 +43,6 @@ public class JavaLogFactoryTest { @Rule public ExpectedException exEx = ExpectedException.none(); - @Test - public void testLogManagerConfigurationAsClass() throws Exception { - String propKey = "java.util.logging.config.class"; - //If defined, grab the value; otherwise, set to a known value to allow for prop to be cleared. - String sysDefault = System.getProperties().stringPropertyNames().contains(propKey) ? System.getProperty(propKey) : testName.getMethodName(); - - System.setProperty(propKey, "some.defined.value"); - LogManager testLogManager = new LogManager() { - @Override - public void readConfiguration(InputStream ins) throws IOException, SecurityException { - throw new IOException(testName.getMethodName()); - } - }; - - try { - // This would throw an IOException if the LogManager was not being respected since no esapi-java-logging file is specified - JavaLogFactory.readLoggerConfiguration(testLogManager); - } finally { - //Restore original prop values - if (testName.getMethodName().equals(sysDefault)) - System.clearProperty(propKey); - else { - System.setProperty(propKey, sysDefault); - } - } - } - - @Test - public void testLogManagerConfigurationAsFile() throws Exception { - String propKey = "java.util.logging.config.file"; - //If defined, grab the value; otherwise, set to a known value to allow for prop to be cleared. - String sysDefault = System.getProperties().stringPropertyNames().contains(propKey) ? System.getProperty(propKey) : testName.getMethodName(); - - System.setProperty(propKey, "some.defined.value"); - LogManager testLogManager = new LogManager() { - @Override - public void readConfiguration(InputStream ins) throws IOException, SecurityException { - throw new IOException(testName.getMethodName()); - } - }; - - try { - // This would throw an IOException if the LogManager was not being respected since no esapi-java-logging file is specified - JavaLogFactory.readLoggerConfiguration(testLogManager); - } finally { - //Restore original prop values - if (testName.getMethodName().equals(sysDefault)) { - System.clearProperty(propKey); - } else { - System.setProperty(propKey, sysDefault); - } - } - } - @Test - public void testConfigurationExceptionOnMissingConfiguration() throws Exception { - final IOException originException = new IOException(testName.getMethodName()); - - LogManager testLogManager = new LogManager() { - @Override - public void readConfiguration(InputStream ins) throws IOException, SecurityException { - throw originException; - } - }; - - exEx.expectMessage("Failed to load esapi-java-logging.properties"); - exEx.expect(ConfigurationException.class); - - exEx.expectCause(new CustomMatcher("Check for IOException") { - @Override - public boolean matches(Object item) { - return item instanceof IOException; - } - }); - - JavaLogFactory.readLoggerConfiguration(testLogManager); - } - @Test public void testCreateLoggerByString() { Logger logger = new JavaLogFactory().getLogger("test"); diff --git a/src/test/resources/esapi-java-logging.properties b/src/test/resources/esapi-java-logging.properties deleted file mode 100644 index 71011acc5..000000000 --- a/src/test/resources/esapi-java-logging.properties +++ /dev/null @@ -1,6 +0,0 @@ -handlers= java.util.logging.ConsoleHandler -.level= INFO -java.util.logging.ConsoleHandler.level = INFO -java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%3$-7s] %5$s %n -#https://www.logicbig.com/tutorials/core-java-tutorial/logging/customizing-default-format.html \ No newline at end of file From f45876f0555fcf372a1555c484e743ad1b204d9f Mon Sep 17 00:00:00 2001 From: Matt Seil Date: Mon, 27 May 2024 10:32:56 -0700 Subject: [PATCH 111/197] PR to fix #824 and reference to #823 (#828) * Updated DefaultEncoder.getCanonicalizedURI(URI) javadoc to indicate that the method takes into consideration canonicalization of mixed/multi encoded URLs as specified in ESAPI.props 'allowMixed' and 'allowMultiple' accordingly. * Per issue #824. Updated DefaultEncoder.getCanonicalizedURI(URI) javadoc to indicate that the method takes into consideration canonicalization of mixed/multi encoded URLs as specified in ESAPI.props 'allowMixed' and 'allowMultiple' accordingly. * Fixed #824 by nesting the original canonicalize call into the else block of the check to see whether or not we were dealing with a query segment. --- .../esapi/codecs/LegacyHTMLEntityCodec.java | 2 +- .../owasp/esapi/reference/DefaultEncoder.java | 25 +++-- .../esapi/codecs/HTMLEntityCodecTest.java | 20 ++++ .../owasp/esapi/reference/EncoderTest.java | 95 +++++++++++++++++-- 4 files changed, 122 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java b/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java index ce66ba256..240cc2ca7 100644 --- a/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java @@ -1,5 +1,5 @@ /** - * OWASP Enterprise Security API (ESAPI) + * 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 diff --git a/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java b/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java index a754064bc..348cb4a4d 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java @@ -520,6 +520,9 @@ public byte[] decodeFromBase64(String input) throws IOException { * This will extract each piece of a URI according to parse zone as specified in
    RFC-3986 section 3, * and it will construct a canonicalized String representing a version of the URI that is safe to * run regex against. + * + * NOTE: This method will obey the ESAPI.properties configurations for allowing + * Mixed and Multiple Encoding URLs. * * @param dirtyUri * @return Canonicalized URI string. @@ -548,7 +551,6 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ parseMap.put(UriSegment.SCHEME, dirtyUri.getScheme()); //authority = [ userinfo "@" ] host [ ":" port ] parseMap.put(UriSegment.AUTHORITY, dirtyUri.getRawAuthority()); - parseMap.put(UriSegment.SCHEMSPECIFICPART, dirtyUri.getRawSchemeSpecificPart()); parseMap.put(UriSegment.HOST, dirtyUri.getHost()); //if port is undefined, it will return -1 Integer port = new Integer(dirtyUri.getPort()); @@ -557,9 +559,6 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ parseMap.put(UriSegment.QUERY, dirtyUri.getRawQuery()); parseMap.put(UriSegment.FRAGMENT, dirtyUri.getRawFragment()); - //Now we canonicalize each part and build our string. - StringBuilder sb = new StringBuilder(); - //Replace all the items in the map with canonicalized versions. Set set = parseMap.keySet(); @@ -568,8 +567,7 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ boolean allowMixed = sg.getBooleanProp("Encoder.AllowMixedEncoding"); boolean allowMultiple = sg.getBooleanProp("Encoder.AllowMultipleEncoding"); for(UriSegment seg: set){ - String value = canonicalize(parseMap.get(seg), allowMultiple, allowMixed); - value = value == null ? "" : value; + String value = ""; //In the case of a uri query, we need to break up and canonicalize the internal parts of the query. if(seg == UriSegment.QUERY && null != parseMap.get(seg)){ StringBuilder qBuilder = new StringBuilder(); @@ -597,6 +595,10 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ } catch (UnsupportedEncodingException e) { logger.debug(Logger.EVENT_FAILURE, "decoding error when parsing [" + dirtyUri.toString() + "]"); } + } else { + String extractedInput = parseMap.get(seg); + value = canonicalize(extractedInput, allowMultiple, allowMixed); + value = value == null ? "" : value; } //Check if the port is -1, if it is, omit it from the output. if(seg == UriSegment.PORT){ @@ -618,11 +620,16 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ */ protected String buildUrl(Map parseMap){ StringBuilder sb = new StringBuilder(); - sb.append(parseMap.get(UriSegment.SCHEME)) - .append("://") + boolean schemePresent = parseMap.get(UriSegment.SCHEME).equals("") ? false : true; + + if(schemePresent) { + sb.append(parseMap.get(UriSegment.SCHEME)) + .append("://"); + } + //can't use SCHEMESPECIFICPART for this, because we need to canonicalize all the parts of the query. //USERINFO is also deprecated. So we technically have more than we need. - .append(parseMap.get(UriSegment.AUTHORITY) == null || parseMap.get(UriSegment.AUTHORITY).equals("") ? "" : parseMap.get(UriSegment.AUTHORITY)) + sb.append(parseMap.get(UriSegment.AUTHORITY) == null || parseMap.get(UriSegment.AUTHORITY).equals("") ? "" : parseMap.get(UriSegment.AUTHORITY)) .append(parseMap.get(UriSegment.PATH) == null || parseMap.get(UriSegment.PATH).equals("") ? "" : parseMap.get(UriSegment.PATH)) .append(parseMap.get(UriSegment.QUERY) == null || parseMap.get(UriSegment.QUERY).equals("") ? "" : "?" + parseMap.get(UriSegment.QUERY)) diff --git a/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java b/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java index 070e28a26..5414d9ecf 100644 --- a/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java +++ b/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; +import org.junit.Ignore; import org.junit.Test; public class HTMLEntityCodecTest { @@ -48,4 +49,23 @@ public void testMixedBmpAndNonBmp(){ String input = bmp + nonBMP; assertEquals(expected, codec.encode(new char[0], input)); } + + @Test + /** + * TODO: The following methods are unit tests I'm checking in for an issue to be worked and fixed. + */ + @Ignore("Pre check-in for issue #827") + public void testIssue827() { + String input = "/webapp/ux/home?d=1705914006565&status=login&ticket=1705914090394_HzJpTROVfhW-JhRW0OqDbHu7tWXXlgrKSUmOzIMsZNCcUIiYGMXX_Q%3D%3D&newsess=false&roleid=DP010101/0007&origin=ourprogram"; + String expected = input; + assertEquals(expected, codec.decode(input)); + } + + @Test + @Ignore("Pre check-in for issue #827") + public void testIssue827OnlyOR() { + String input = "&origin=ourprogram"; + String expected = input; + assertEquals(expected, codec.decode(input)); + } } diff --git a/src/test/java/org/owasp/esapi/reference/EncoderTest.java b/src/test/java/org/owasp/esapi/reference/EncoderTest.java index 963939626..51f72d063 100644 --- a/src/test/java/org/owasp/esapi/reference/EncoderTest.java +++ b/src/test/java/org/owasp/esapi/reference/EncoderTest.java @@ -15,25 +15,21 @@ */ package org.owasp.esapi.reference; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; -import java.util.List; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.List; +import org.junit.Ignore; import org.owasp.esapi.ESAPI; import org.owasp.esapi.Encoder; import org.owasp.esapi.EncoderConstants; -import org.owasp.esapi.codecs.CSSCodec; +import org.owasp.esapi.SecurityConfiguration; +import org.owasp.esapi.SecurityConfigurationWrapper; import org.owasp.esapi.codecs.Codec; import org.owasp.esapi.codecs.HTMLEntityCodec; import org.owasp.esapi.codecs.MySQLCodec; @@ -45,8 +41,7 @@ import org.owasp.esapi.errors.EncodingException; import org.owasp.esapi.errors.IntrusionException; import org.owasp.esapi.Randomizer; -import org.owasp.esapi.SecurityConfiguration; -import org.owasp.esapi.SecurityConfigurationWrapper; + import junit.framework.Test; import junit.framework.TestCase; @@ -747,6 +742,7 @@ public void testDecodeFromURL() throws Exception { fail(); } try { + //FIXME: Rewrite this to use expected Exceptions. instance.decodeFromURL( "%3xridiculous" ); fail(); } catch( Exception e ) { @@ -985,6 +981,50 @@ public void testGetCanonicalizedUri() throws Exception { assertEquals(expectedUri, e.getCanonicalizedURI(uri)); } + + public void testGetCanonicalizedUriWithAnHTMLEntityCollision() throws Exception { + System.out.println("GetCanonicalizedUriWithAnHTMLEntityCollision"); + Encoder e = ESAPI.encoder(); + + String expectedUri = "http://palpatine@foobar.com/path_to/resource?foo=bar¶1=test"; + //Please note that section 3.2.1 of RFC-3986 explicitly states not to encode + //password information as in http://palpatine:password@foo.com, and this will + //not appear in the userinfo field. + String input = "http://palpatine@foobar.com/path_to/resource?foo=bar¶1=test"; + URI uri = new URI(input); + System.out.println(uri.toString()); + assertEquals(expectedUri, e.getCanonicalizedURI(uri)); + + } + + @org.junit.Ignore("Pre-check in unit test for issue #826") + public void Issue826GetCanonicalizedUriWithMultipleEncoding() throws Exception { + System.out.println("GetCanonicalizedUriWithAnHTMLEntityCollision"); + Encoder e = ESAPI.encoder(); + String expectedUri = "http://palpatine@foobar.com/path_to/resource?foo=bar¶1=&amp;amp;test"; + //Please note that section 3.2.1 of RFC-3986 explicitly states not to encode + //password information as in http://palpatine:password@foo.com, and this will + //not appear in the userinfo field. + String input = "http://palpatine@foobar.com/path_to/resource?foo=bar¶1=&amp;amp;test"; + URI uri = new URI(input); + System.out.println(uri.toString()); + assertEquals(expectedUri, e.getCanonicalizedURI(uri)); + + } + public void testGetCanonicalizedUriWithMultQueryParams() throws Exception { + System.out.println("getCanonicalizedUri"); + Encoder e = ESAPI.encoder(); + + String expectedUri = "http://palpatine@foo bar.com/path_to/resource?foo=bar&bar=foo#frag"; + //Please note that section 3.2.1 of RFC-3986 explicitly states not to encode + //password information as in http://palpatine:password@foo.com, and this will + //not appear in the userinfo field. + String input = "http://palpatine@foo%20bar.com/path_to/resource?foo=bar&bar=foo#frag"; + URI uri = new URI(input); + System.out.println(uri.toString()); + assertEquals(expectedUri, e.getCanonicalizedURI(uri)); + + } public void testGetCanonicalizedUriPiazza() throws Exception { System.out.println("getCanonicalizedUriPiazza"); @@ -1000,6 +1040,41 @@ public void testGetCanonicalizedUriPiazza() throws Exception { assertEquals(expectedUri, e.getCanonicalizedURI(uri)); } + + public void testIssue824() throws Exception { + System.out.println("getCanonicalizedUriPiazza"); + Encoder e = ESAPI.encoder(); + + String expectedUri = "/webapp/ux/home?d=1705914006565&status=login&ticket=1705914090394_HzJpTROVfhW-JhRW0OqDbHu7tWXXlgrKSUmOzIMsZNCcUIiYGMXX_Q==&newsess=false&roleid=DP010101/0007&origin=ourprogram"; + //Please note that section 3.2.1 of RFC-3986 explicitly states not to encode + //password information as in http://palpatine:password@foo.com, and this will + //not appear in the userinfo field. + String input = "/webapp/ux/home?d=1705914006565&status=login&ticket=1705914090394_HzJpTROVfhW-JhRW0OqDbHu7tWXXlgrKSUmOzIMsZNCcUIiYGMXX_Q%3D%3D&newsess=false&roleid=DP010101/0007&origin=ourprogram"; + URI uri = new URI(input); + System.out.println(uri.toString()); + assertEquals(expectedUri, e.getCanonicalizedURI(uri)); + + } + + @org.junit.Ignore("Pre-check in unit test for issue #826") + public void Issue826GetCanonicalizedDoubleAmpersand() throws Exception { + System.out.println("getCanonicalizedDoubleAmpersand"); + Encoder e = ESAPI.encoder(); + String expectedUri = "http://127.0.0.1:3000/campaigns?goal=all§ion=active&sort-by=-id&status=Draft%2C&html=&contentLaunched"; + //http://127.0.0.1:3000/campaigns?goal=all§ion=active&sort-by=-id&status=Draft,&html=null&=null&contentLaunched=null + /* + * In this case, the URI class should break up the HTML entity in the query so + */ + String input = "http://127.0.0.1:3000/campaigns?goal=all§ion=active&sort-by=-id&status=Draft%2C&html=&&contentLaunched"; + URI uri = new URI(input); + System.out.println(uri.toString()); + try { + assertEquals(expectedUri, e.getCanonicalizedURI(uri)); + fail(); + } catch (Exception ex) { + //Expected + } + } public void testGetCanonicalizedUriWithMailto() throws Exception { System.out.println("getCanonicalizedUriWithMailto"); From 797456719696bcf9cbbce4e28301da831e87bc2c Mon Sep 17 00:00:00 2001 From: kwwall Date: Tue, 28 May 2024 08:49:10 -0400 Subject: [PATCH 112/197] Add reference to release steps doc. --- documentation/ESAPI-release-steps.odt | Bin 328702 -> 314135 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/documentation/ESAPI-release-steps.odt b/documentation/ESAPI-release-steps.odt index 838ca0df0b0a75498613cf5d60243c9233553d00..38a23f4770b92c8a5f2399649e2c55554adfe9f1 100644 GIT binary patch delta 79039 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

    !lGw4%Ynf}xhvNyFi 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 O13=(ILJWd`$^Q?Z-qrvB delta 93780 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

    is3uy&Oqm%=acix&SaUUOg$h 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

    8go( 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 From 1801b7825c75613a2b0e9df905922f4033e1dbd3 Mon Sep 17 00:00:00 2001 From: kwwall Date: Tue, 28 May 2024 22:05:21 -0400 Subject: [PATCH 113/197] Added Reference --- documentation/ESAPI-release-steps.pdf | Bin 526660 -> 381480 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/documentation/ESAPI-release-steps.pdf b/documentation/ESAPI-release-steps.pdf index 53a30565ca5127518826ca78dea39612ff814464..7832d2cc2fe4e81186d751939ff531f06c1091d3 100644 GIT binary patch delta 176142 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%0D9I_&kDwwa1tE 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 z⋙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%0D;$IUV-(>b*)(%EV0EZc$%QeT zQsY&q47Vv(EG(h-Mgy|=mL9ul~X1tax$q&sJ?VdlDAw-ar zn%%cNk-RSa@(J9gA!I%E5};#GvbpWbp=};|z9GTi@lQce5YW4Abxqi zp2{G0M`cnziy=&)ex`<6CB7b(Fenz0>sllRP}vhjUKln`n|UDfhkjnp9y6Ec6sxwWWCs zYcq6!Bg`s|7ju3-(BxKl?7Z}gY`Q+iDlV-!=$V~@y;CJDPt6#3?!(wf;xmSwT4esX zWzaIHa$!GhxycBiitBf{hK|&1^7=xx6^*nv5$RWI^U8F~c5vM!n|fhAyP}X}f5+sR z%8EDii&18T0ab!F*4&bM6TbdrDOV_`>9wG1<* zAbfUyOLbAWJH6U(7I3B9gt)n^N%abLDTpxIcFWs!_JG*Vrksz9dNP9Idf7aVZjnWb zD3$zNR%~8#d=D3{XxmlG_UtVEKorFYrpLVnA(E?BfLpNF zzVR?$1Cuen%TA&;u`$+#LQft!8V|mpZA2L}Rma@J{A&$bmQOZ?1y>Jx?Xxw;n8}G_ zlxTMq)xBa{Y^{Q9H_{?*uSDq9=^v<>3JTI(etsZE^2*&CB+)6t7FxkY0;QdbF4GAY zY66GPv%}h5wU*VvSs@FaP-lsOT@ZEY{wNN&Z|7@CwAgsKL@^*7R18NO z;r+N!05RO-?S(3~ny$*R9@?5D2)!o~j95-f`*)I#`ukMP*~My9HSp9Mbh_aI*BSnl z77L&@yOPc;00Gjbw{9)}ZdS-j64jG>l1(IrTUjQCB577Vh;?8g-6k6*yF0lZ#nfZ! z)oaD%f~P_6pf&i+QFOcGc$9 z7WT8eJDQM-wck8l#}Hj|^JXp2ybrREEs#oz6y4DHN$MzR;7YhJex`mw+VyNh zPJN)XFjfRLMv$*=x(k!7g?BLir#LV`0q1FE%MC|pR*yzHftj3F-1c|0OaP7fRK{0z zb3KWGdUHE}(kgG+E2ImFo3M!Z+E-sN$xVLLCC;@bN_m`34@ zD(~yja4Ak2;GFK0sgwe70-(i?mr|K1a&2YlSSLNYXJwlt!Hp{2Fq*hzI%>#} zKg&pm%wro68cUXuffmts3d6NlH(a*ThojD?i8Mo@=~y)u9U@RwjmOB-EFLlLqjpNP zKkt?L>qQOCho8{EwGf?-IXXn3#HGTqj<}Ra7K_z4WD8e2g4XBI9cA4G1F%1X;#b0M zAa*T>y6^X;v3hZ;X#6xKEhKr(62iBWK}#Gr>FN$FZ|d$Qz1H<}iCR38IuOki4%oc} zdLss&#cUGaNkP(+R3IsTVY(yyqp%YikOa&$=x$Yl1Fd}&41|Bz`Q!dYZ2_aYl+^0C z0r5z-SZ{zik4?75j07?S*QwJ4S-HT`-(fPPh&tjPB#__tclHw6T)Z{|hr3JH7VzK{$ZXc&g_ydt9Mi6xl zj&joQOTc*vo03|jPsbW-t4SCR^ah!%L7U-QKFRm^OfsCvX6GXV;4RSk+ovM7b8SvO ztznHXibD^o!x}Ww$3NN9uk(z7?n<4CssWS8!mP+yg9beEOZaQC2+<=J^Zg*|5+cl7 zzE2pWkpxUjq6i>rJ@>H@n52BoG*KYG*ZcmHVz{RUvwT_(leJDr5i?nhe{$p?zdEGc zK1DVvEb%?Dfn5cEe4nFxL;UZo_7O zz#n;_yJ1_=IFkiy4Wo{Sgt0OZ*JFuYB7@w1oN z_rtE*$709I5$PehP2`AV>1B++qsBAf+U$e+%?`O44P9Yu;1zdCY+bvW72dCAmc&Ep zMUw_B0lJ;%+nEucwJ-Ix=~W<{*&*~z=UKrUtm=$}%a1GlqmP%)DMQIk&;88FH%XtX zE88n>wNEHO5vhr%t)l5uxrpNd zz=r(AG-}2Y`L$8BRk}#NDj{gD|MpK)g+nns;XyLsc?P`)RXb{YL(eXB4^2RllwLX} zw{N7*nCnPE4^MaVFEka0F};O9db|})9!!;Q`S;j?T(Pp6FUEF+P-(8gL|Sn==Pd%v z45x0-Z`-_|P>s=uNc$Dh079CwdIZ5jrQDcZX6pHiHjJ2oU&_%vRB)%PuQ53DH+pH` zYjAh~8H!%{m(!i6B>Ok5m*C8BzT1v3&`?XHJzv38 zU~Bk&x52f@_~~APGs3#gT||5*cP@8%XnOj=D=@dBpW2;HxIBM@af4$+nxSn$gYjZ* zsp08*2O(YCV&o|K$|w4`f^o{fbzwn1UEII|xR9mHgHi~Ud8~fag|In4%GdCsyN{Y< z<7Mdmq?m>%+?c%iYA8OUvmQsV?r7m0M?W4P^Qs+GKd%s3Ji>=uuZThr8-?*DdTPv$%V><;Wp3H} zEF@45927lH3-w!RfVLfKO>U$fN{Q+ZLoOZ6f?<}Paw^rbCXDBc2K_X$ElMVYw=lQ) z&&PA=C=1WO>^E|C#hLQKSv z5FU)c4FgbY!lmxlJzBE{XB(T8niV<;J4V>InU?OQ;MbkdQY}uJ+*wk9QVn$)v%C3Y zK2jn3hgKyU$}DW8=$cZ&J9<&09aiaqODrgj6!rH{ffchS@CbTLNVSe z6WXZ6cGQDwV|m<$Q2cO_0e6-xqFx);PGrn-5N7#ReB+P7)rB^gV9WP zm7eCdt3UcrsV^0~;yNJ2U>`;V{6V$PezKX#PViy9XToQ&98(-09eW-7tdVNy(DUwH zSXQxFwRkP(S=O<#ZOV2;=di#(#Ute6;>xETOxi7TqOm`BCTmY=Av^}==vr3{?-JcG z3+IYDKr4LCwkO9Ew_M$O^KM+8As)8Z7gy4^jZcVAx;NRUJ4G6b5+eDe<#B;&MsXm9 z+N5ncJJ<%MIZ`J}1%XN5RC?%I4Gl)(WD{}5G<-?NP)Akj@%(dLLP<+8RCns+h4|Is z3pEYVGvvrZsCY=IT4rGInVvG4H5T1OcL%5#GuntL6pkMnbeAL=wjyxwH^Fh7tjRYt z|B<=eq?Z0uJcI1tr)d{?k`Kg8Z6v726O3&1sVjd{tU=T^BxfAD49#%PL;>8%m}0QN zzvY-NZ$Bdo5el*|1TziYBMPE>>kpAyfOTTqqbcy)TI{?LlcRGUYZpW#UBWV)s8t?H== zd!qD;LcmB;2I{GBZ0_gBTQZ<^1?R`o#SE1pFc;=tNR6UL?=V!ERpwb=C@rYGchN9J zCsXB_I>Rw#sx8ba`1jfdEsSoHIS^RlM$(TZEaS!?AMt|?v<&ChC^t*O2M5cNt~j-x*N522a983J>ecad0h)RL9aAzXY+i6O_vcQjC|ISEy)I zr#A8^?t_OIe~m7xHgWM5T-O@Wss4KxTvn!GRh(C6pfO&NE>a+`JuSz84-F?;Vd4>p z_%+(E8tBSvTCCwfaK2amyH|iKq9Y*GH0KvNH=eGEk-OBWtek`*jGVMIpsogko29Jk zT0WEX-5KGpjKIXC z#xB3=+iGjO0F{Lf_gh9P1BJ9`fnlK$bpX;*3y{;rKobrSFn*|rBY)Nqws0&lOOlDi z<(*+`BN!@1PP-jI_ITOhT;{5Gt$@KBOn(^^Gbu1pG12ZHtC$WV9+p!OG})OAojflH zS3)J^#YnC0nR8MQJsAd{;jb;Loh#P5`L%w{7GjjJ@$~c;Ayhf!N?mO;WYijeXL0rt z7LaI;o{N_XJfb*@Io{W^u!@W!(D3MLLZ7Bl>{01BRpPV_dyJFpNBTmXq5{2;^# zwdYBe8j9B_D4e^B(|LMh2;vKtDTo!zi2-Ql90Aog?O7a|^M{AqM~9u^nE?GxKu8^+}uw1!2=t>_PkYkf)$ zU3jc*Sq~CxQ$sSy&sAofpztRpG&H9xSJcMMORT&2tcI}4HBk~IX+GwER*e)Y0L7+O z9i~&4->jQ4SFiLnl4@fd%Iw&7VQIab{!ku0l{02XO^Jka;g6bbZ~8AufueTvn>cA$ zQx2xn)H9E`c3#`%hIMe@lr>HMIL(Smo-$~Qy2r%m&{3iUeNv7j#h2wUdE+dk3a`pP zmlScz|0dDENU$T`XXTYhs@0*u0~TiEb&Rm*zZ$!!4v0AX>*k7EEGUUq5sgy%#Sn3W zd(7XS?4T(=dV)$^t~VauSn%M6*~r&STEG}!k;dtfl&DetN#DhEw8T89QJIgYypv67 zs+@mPbAd<6;*43!x#l+iS9$8XGGe~GSfzwvaMX&Es;qQlKH=kt-{hz32%t+k-xcj> z>|s@8H0U<*!dF#%r7SC2vs+;%cEyP6j`tmO+Zfi$THId|C24@Ckrg*5F*kHqOwa1j zMMX~TxG%xA3|bi;^~|*}L^!~u;6vd|PHRA7LgB^H#1=Q;Witm*cy=wlsvgmPU;F*c zmh$~wyV?5#g=^4yakm-^0H9-$?}l!Co+9js{8XNS@uNqRt%CEZm9On9z72jpcTiW_ zzS-gJ?vofUw;$y-A&*x2Q<^SC$MA-nOfOQ)X)LBLncE1P85d{oFXaN&$5gRhlujPq z+{#BhJ|}ynOvP%)N+q(}r2@^5Lxd}xd_8=mUb=Vdfwqo+1A&iSfDrAYJyhz6%ly&D zXMGrk%rEn5!1*k&yY^gXR&*l<`-PaQfJL85Pr|v&wAz9P~WUoU`>%lUeS` z*3nf_jMHY8cS4E4_=<8(#Bv=|TY~wzy8&53W4<1A{j<5*x{m=DlgDbhwbVjWn{`NY zqwOxMwbU)9ZD8BIof}UDozy*V&BQ)SvrdWbY)7zq`&W&{ z47L8quJ*Hww)W-yp!1D!*S@;K&d#Vfa9c<&1y!yoP0du`Q2Og*pv=!lNbAtdoZhMw z;tKd|5S*u{BpH@F*={w>5U1bJ_O`H@J6Cl{i@7 zO2w@M-w)@#K~&%c!P^eIZM2;xP}GW?!4VCENiR)*m`Y0TdqcK$pAIW!Tttdy%4nP> z0y>ehlp+J9&q=Mpk~0}hB;3WE4_7EZeIFV2$A-g(e19!+G15W>Fhd-fX&<>sx{^9jV4DA2YlFz`x!N`!JKK4J9 zeg6(5D-`_?4mOVekK>ta7n0;3WdGmw`2QQS=V&(Ag)9P3X&e7vwr7q5NcMk}eY5=m zqz@Pm1N;B2%4h$ds{H>)>~s7F;Z1O@sB{Rr&w}0~7QA zsnSO~Y~12t@>r_-j{tfZQ-JvE>ek|yI`;tRXTPW@>l*1_f;B-TnnX>7VvLaKUpF@n zv^2*F*NNwe+t;q&!%s%vZuDW@Vnc=?7~G#%l)qeYf5Ai~{C9}jbX*nj zul{037xPDCsN2V7^7Tu)orkbemw=)Lg}q5OGd-@Pb$^5~D%@Jajl zUt+Va5(4QEV#sV?#oEiGu1sMrzegZK%X~v4@&)Qsugb1_tZOIjFC79$1L4s8u4COU zvb$xTkoh-wYR!nA;onR!^_FduuGP5Fan(PkB)^P0etB}q`}t0x%In7ob?6qQQam}# zvbT>5CuJh3kMagMo5%QL!zx)pEJExDz3R-Ic<1#;+wF?_0+af>NCbTKQSXc8CnW67_;zgkAIc3ZE zP;o=uXmvr%%k+ibP81kYnYlOi`pU&1#)&?jdAH<9ti0yqu_pRxeTR1_SJ)+uf6I8b zowc{&Yj{;+p$pa#Hhy>U18%YmmNVy(E)mEgrut`X2-%{IH%W1s9qJBTTjqRx3#^jp_Q*G49nM_YT7tBaMT?druQ2{l++==mFj(eOk9Q_oN_Ic_{-*A&Cgnr%&)RSlQ z`{DEY$FN5D{Jh5uXl7DV>_sO2X~QN?Uyg1Wl&o~>cjYvSyd28p9!y$GVN_D-_g#>{ z&mFQbIjr`(R@3+IJv5f;eEq+p<v4;mAFC8m==d|#lX?4>Ezjvc8|@{^0ld5VvIu*z^$5i{>2>_;YJ_4_nE(6$iy$r z!*BPdsOnJu1|2H!i6i`|5wglSG0*s~|#aBwF!4@>j{lNXAR7V9n+3rARUT<{@WE0HvEPHho2Oz7fzBk2I6Pc$?nF zEQX`$;~buJgQ_dz!A4P7frUjCr$NtYlNTx)ho^WlJh)E|AT6muhdmWi$Uibi(F~pg zp!-M)_;dK1l}%xDCsX1ay zS8+q}#3Ios!NJmK+<1(hc*oqxvF77?P*%BZrY1*58iq$wV!ixRqsZ(>$Vq)^R9vE3 zGPy9_)1TNQtbPHBi))H5ifw&)m4IG@s)Mpi9IM|o-xt3HPs*=2N2PFy5fKo86BQM4xY6Cp3cD} z4+RqY8ZE+{hQcvg`BOtCn03JHEFFx*sO~q_;onvVUei51rjpnRM4+``}web|BVL{fXE?|GxL-~Yt2C6Rexc;pM%j!ikkYRi&@v;MlK81a^c zO@duIcT|*wHU1oDu=bH0PRzzkGQaJfSNOwSZ)@HybvUK4L`l~Sat~ORJDA#Aag&TQ zo~owWi9)`@jgaA_Kj%6ZDI77S#x6wDp-)=zBI^4Wt;?87z;ZY%n#*KZn4CqGXI-VNK1%WY#KcZwOF zj>fecC~upaKVSO!iayV-F1&L8oYG8ZPy*LQr`P-g^9U;YTVKm(ai7^(5KDZMYG4pY zqP`NNW7?R}+ibBLLeVKDhbt?yun3e+wX`DNI52C}yDK;AYRSOl^Ht7L+&^VTG+4I3 zYt&DLHk&XCBKEX7lf)Oe<@|VXhSREZgFSc5iD#=YD^c}osIEO7mdEEP)BShk>;)9G ze0NZdouu(u^*WCh)FXy>=f%>hs*zL3$#>FpKORrowX4If$N4_ZADd9C=5Jv)oUYi4 zv$|&pmZwHDdE$KrA4@f(0VZ#EkgKGqc#UG(|{U~>dVR{xVOF&o__({$|Mx4K z&B8OA?S|6N^M{E>j)ci>$0Z0G%WTh!PsKf8`&S&TLploaw$mvow*tJ`y6XDP0Rwd< zqqeoay+1ClP7zq~H}@CSb6ZA{OiKPlXGwG@gefMmD}_OhCVf*+)GG{J7M`y#;hP01 zfs@3)XsAsEouNr`&B3f zT)khX`yU^Is5*4t`hhE%)NcdRW-{=~nFvYJ0l@+j~|(Q9?+W?IZJBZ5bLLmh{Jn!R6V4SM3|)K{qKD4N&auuqhA-+w z&%FqAjn3||_D5RVXn`u2hK{DuNzI>{334h19~9+M4sKBl=Gg7mC1t!8!m^zWX2N)6_Ke7?>~^?hI(Ggf zqJ?13@Be{==Q;k9ibi5es%p_X2)#SfNN+i2Jn2kDKYx-wpC#2A-#t=SUxP5o4Dbf0 zcOI{FRc=fG6WYfsJf3zLgvhHi-R&>mZnaKU+xJeApOb%WuGiZ-Y|gyl&+l@&$K~em zPu>bYphivWojn|mcm$MU_tf>v?pk1S8`F{dT42^oNIDy#;Nnah-m3}2QT?<8+d*^v zM^+D!$-W(lmRsU9(edhdvG=am72cTg!RfwVU{<#Rn{9z71rZB@Oz5xNHT|Z>y1eKo z{Hhx9mU+kH9gVA#tI5ebxP{o%0|yEfbix7=lJbfYxpV`jSX-AVJ4p(Aw8=X`3V4*l zt?0SvgnGU>r@u*7EJ|!A0$*1aa**qHhOHo0&PHV5cz^?}>aMq$NxJSAx?|O*JFCr> z(s~eJ@p0lw_;#G{%IEPo^Vs!XzRCTh%h=eR?ByY_Dt-uq;_`PMN`&~RA_D7lJZChYRbEy<7T6Ua-x9-0ZE49Ga1YnZ-#hh zOZ5EFarCFJO!xOIK=)I-F5dIID_cQ@oc`k1vL_m`@v zGoO6G1@{hWoH;j=ZL4pczkq~Lo@8uY${UBES(0>sMg73zQO&q=EMyDqUhWL6PlW@9 zMU}MV^*^NA&I?m?yY6NR@2D#AS8?_qtTkJqtDE$ZU+uWQ&TNWj4>p>K1F5{(ANnsm zO3@g5LyQukQI&$k4rnyLgFEmvv>bl4w-nr584(bS_Lp*>4GVH0F(u}5JMC{Lad-5P zKkn-r5=gk8;DF3E_x*#&3QsZfXHNj|KgsyxbS1m&W|`g*kJpn^Wk-R&9bHQ0G?b%@ z=;oO1Bh2d`b&T{N1g(MUT-&Lu`01wPunfWk2f~8e6GoG+1`M(%KBPW?#8fygT$hW zyOZF?8ji!VEE%07Cp<&XR6zL`{cI)k-}j4B$4pZa+aT;sJH^k5qGKvTfmvjrX*-+R zl^QT5;qKXU6<4F%R)Dca{m|$uu7}S~xQY!#8JrrE%H?n%(UR2oC=PV^ZK|B9>yf7dJ%PJs3N5OL}6L0%xlIL}~c}t#+$;=xPee7Llgy2x8wbk#daq zgLg_+`gf`~2zSGN8v_fml^#ONX&VZwNXu;|Xh@5FzYiPt+&=eAz;Af0Hq!`R(CXX4 zVxDGoYnAx6Kd^SuNm@Q-HtEG{%9oEtt#=lv+7jJ_W3)LLJqDMQZ)qGbB=dS>f(WE{ z4MkKB(DJeQWgXnfyPMS+if#^Cm|72b$Yv(QD9DUd`TYHUr2S@p$E9mQ=W&VnI&+|( zOuRxM(arkYc0CkO6h-Jubqktu7v0Ky{=Am8om-dY0=@|#R&J(6?A={BjlNa?7hC5P z+({g!>xpgKw(SWgwr$(VKelb#wr$(S#CGOn_n>xb&uw4yMOXE&tH1aCo(JbIgZG14 zy)E7q(?3{z8Q=-lUzKl#bs;;t177Ve@_%mFBDk-S>`}TSubYDqC>f&}NWN8fpfX)z z8QTp@nqhLp2>55JPw@Bsdjr37mS`8Htz<2HYjvvm@+VhU&lW4#hU?OMDp@FyStKSH z#J79_8x9`q9hej+);nxw0?4QIXeWXoB-B%j>+ZeKR^~SyO2N(gLA8~2F{Yn2&=>oR zpNY_?f=ujX_CJh{PG}r^U^~TqUiBe9ju#pWyq64UoP2+da(kepyXlB0?BmsJrB7Wn zF+^5yv=c&crQ!kJs+B5512|=i0qUw^Z*K)auuGk^lT`52ZO;iA+Kj)+20^7gJ?%nI z;Q;t`0=-`FgTBp-oeC$x^AR+)b7n(T&!!pelKOn-kcaS0;YN3X>j#0V4#- z@Wh;1n*Am>N*uX=td3c$z;-4XOz0dS69OL;bmec%oD?SO4g!@CNqZ3~{TqdCpx@q@ zlNJ}2G)SKk3F~Jb?GqYgWde!~7sr5tG7nO8FIX0Gi60({ygxQn7N_q&E&(%cPgu^$ zhc7ikGU#7lFOt-LhbehgsEijyI>>tGPD$h(3=hpyc<3K4{+GE#-dc>ZPS_a0iyn)w z&%Qz)a+p5{DuWIQ{wz8|EV+OVKLj#}$^@-t%-K&Y?2l;ZAHI7aQz?x|JHe2L2nyy2aZvJ7u6xP8T1SGpzB)1Km_{2TthFTF2H{+$tje+%?GM|D zibPg`lC!oHwD8CsqNRXzf*YP#JFwjgE&>=O!z7`c6NC zZZNqzCWd{e!>}-2V$I2%@myBM8rmA ze_(68HF0Dk>uW%ije#m2P|9Xp#s%pEAx>@H-*Q8jC;N{?jFCw-Qj`@mt50U6} zNcyU2(2ER^idl_ql&Ouqtk`sO8f~M$(pa&hYk!?5wSC3ZyG@9(jW;X>h)zgo*(F_8 zC>tpy0O?U?mNZfgiL?aiz7xt$_YA}s`ghS4j!f7JCli1*=9zbrDQZUWi}NO`c$W!1 zyvo5~9hRzR>1@l!M}ick%ZPeN`pekYEV@HuqtcBp6ek^y_B=pi`dKksSzrg?z`!`?3?67GLcXu~IbBK;l#mXru|=gF(_rr$vbDlQ(>$T_1~mpw*u={u*KX zpzB5F2TZ_-0wu`?qVqoC<01N55OcSQ;NwDPxc#wCXr_L|D?5@8%RWwckH4xs3LjYq z&N;tuE4br%`o4w`FLE~-S}j>uh_UP<%6hdtPIyIEE7FeGP4(Z-wU;P-FPw^d1)?uXk=S<$kBgXB+Ha*4`motUirL6OI_~YAtV ztdAG|+Taa-nX4oSB!~#eR=vL)IOpmwbPoXZNApp82y41K#_pKggTgoeH*f9i`SywH zQ(T7mYJAN{$Lp1r=xR%Kz~oYhqgGCNb22QGjf>4OdNbF%4Zc+`n9P@HY^@)lz3ws94W`8TwIo33 zU!UzR>;cB78$KVju9>){N-YE1(W6^Y0O%Mrqp06Hmk~&9-O ze)tiofn-^YEGZ_$b`U9wL=fma$|HFiw)lKP-|vK#EK*ew;r7HJIqHE3ZsJQB#NWUZ zc7^FwmFb%7THti~y6*y<6i@O$DOutVatr$>5c@wN89OH{%r@ z^25qzdpOVt}#Ht?154-=l@%J*9Hd055mF0k@^A#rbofV z^*lBl{%=uW>O2uJ3J4R|e?evcN5=Ty0=sQb4{x01r8$(yO{c)HNJpU&pXDvp;a;F{}Y%WKv*Rl!kTE$VEX z&>(zn9w$84`~GM!C@vQfxFlv<()SH~@@M0eBIu1E`wp-B#rJ07A&62IrGUS?(9G`C zB_2VSEnboLW35j;BeICzu z9%501YJsp@08~(>7s={~6`B@SkOS<%i>RkjF8}KwB@utoD%rtTxN#D08maL)P(43C zVkF0I=NDN}Js(dLXP>~`f{_B*0PN2n(Gs>zjBIYE*|qqZ%Ap88R? z%r~GXDKspYl`0hlBz*BSDw0nU_Xv|H@g{Qak!70~@V5T%4?XL`1*Jz)7J29x&JlGx zv0y+^=B2Ro^ApIu(@=z3oHbEwd_KeZGbvZ#6S7VkE;?EJ5gO@BoYIjvix^abt|Q<5 zJ*fu>dICXVXW~?2{{6~F5NL^OS|}|{d1r;-1WYeayi-47Y0kC5vg9#B#?*HFzTGThfB#-@~`0l$`XQ)-1t zML5wHmJ*joPPUAr#KloNtgYkKk>0vQhunM(Agx%t#{G>TI{!VS07ENr{AFRav~c2S zLVR8m^IZ6Fg)YBkC1pC39h{>|Z?(&H`ftgIpvV{XKdF4%;d_%*x@w&UcZKNzXgv>& z^R9NM2s5upXg=4*c$TB%zm7i|Y^id6EW%=M=m9vYmNX7<;vI0iqVlRFyE?b!)MR#d z0LVTn!M@U~;?x~Gn?e#t!oi@oC43LD#+kj8;KWQMC0Mv(S^;Q`o>)q_i2K_T&6Dmo zto8a@$g#-N4r1=RU&`uygCRVaBN8R;5PA|#yjBkp+S)eT5~3KsfpTi&L??BMlB$%L zle7Ag0TtUU4neR7jURfN2izZVtb%bgK&YrB4)MIQy^)qkcViu+vT6r+@@aLciZR+1 zbFpT!;v)T`QxxU1!7{*7=r}I~21b+(mzN~&3bF{CqeYTY zu7xL;Frbz+$#B4MTD@dsfqDfNU}{;C5!!9O*_^oxH-EaauHmxd;WM`0!{}%E-@6ni(%U# zU+gY8gExR%Djv_C!n_Pw0!dR-agZl1B+|MeTp=32H4;=|f5$~RlM+9`j@RV*y|jv^ zVR^2*J(@i}vv{gfk#viwRq74fT>B1AWZyF!te)X!q@`4H`RLW0?S@xHv_i5>m$aou zm?3kKaS8oO+GAjbazuw>_k>m&im1tcY!e+O+%^%#TW@KE%!_%Ni1j>-Q}Xt^3#HZMq_c)$NJ=J}M1&4FGEw zTs9$Jj9u~JEkwOrnqq*3TP5PUse)=TQwp>`S4C!KKtA6&Ihk2~dJ@D4Cc12?L>jGx zs%kC|P-9s@sgUYAfBwd9H-&TWdPhaHMm|Aa5o)QS3clQKU6}&Fl22)nmnlN5WbrGT zQqCJnuijE72`=p`iL6jFt9T=dcDp(us&}g0A`+TWD-Amv7(gyeJOO6P>rV6XfEURC zf1E2L4C~)&R=ynSOT9VK6vj zcwu1UlqQ4oQ*%$i<=5ofOTe-liZ1R66!moiPao;{N0mL6Bpw+z*Zt$l8&x5qIpczWsg9*68I}n7WKpQAx9qiDEoYctng1$5g5OOm|Iz!RO zcy>pZDT4ztr;pj~5rUv$DOxh1n=XB{nz!5=L3 zxLxC7uDLG%DyJcG)l-oSp9gIosh}qL(ozR9O>Q-pm3b`C9>gCE^xy-*|yj5lpzLj0UMpXKmSGe_{oYV^D7;wcVEyrNLOX9VUaNlICcn zdL}a@2|hwMDBR3rO#j)j)RK)~HD%5WAZlbuMF?@MrZ3%SXDX6+qJ;`k58MkDVnAeA zQgt`jf-ypc_YxYTUiA<{hYH?sO{P`WQ3;P%Ubj%74F_J4`jP+ny*XJy+tBVjaK_UA8`>b)ON^6;pPE)L+6dmi@aT!^UY>GR;3 zM4F}gKKJrV0ZeT&a$7#UU0uJ{USKGq#2h%-2!i<|?lZ>4@~6sF19k1{E24(Ru+n*p z<4vY;Q*mG&z?=ES31E-aH>&sQ1N6aIVafrSC%7IqyROOcj&>E*MJ4s_r|9KNViPqA z=z(0C4Ndn}$-B}YFPA`xuIn_DYpDx9vKK+S3aTgi9^&gY6Ex?@iJ%m_W*}pkU|;8P zb;CgVlymB^=&76j+#H;|@M5#vxSomQ*s$rG-Ht{Qc6gJViAP!v96{TNMb|CBdI10& z>aD&`f2Tn%snFj`qu{?eCbfUJgoH0`_)w~aTPH;=YE0QSjTH>1@Cx3r6g1w6!JwAY z1}{4a)_d>9h>BBF!{$OqoBZz!I3 z%Alyp%#iE?yX`E4J>Ay*)`po?(eL94HLfAuhmP&S(MQ*}!!Uf|Yct+~kJz?IYp>cJBXy9+85vkuVZNPN) z6X$YQ3|oT)!>O1D8sJQr1=hg@up?SCng%ApiBXPi`ZWU8_j5%EEm%*aAA}<}E1j1b z)%DGMu^v_|DVdRryHdmMd*%bGlo6#SgR<;O@JLz(!w+nr(E0T;!iAHZ_(pb7Facac zQaMPr%+xNwC9Pd$bQz2GF`XEP)IE3*d7?In%tN7h>|Hs<`x{*`8$~AINn9~o2J`R^ zTp>4w>H?RJ8bT?lB^1z5C+8zBpGlgEmtb?%bgUO`^y)tQ`jn4ku`tEj2BP4X3}=)z zrqWn3>g9?ubw8GCcRq(}7V53!>B{g+W3A)(XtX*I7(5$~vs#VX8G1 zMImS`SK3S@T)*`~HsWzSd*D^P76>e{bIW<$=-Pw;3xl8i3agMEM=^HuPh|R0iJxTf!@*P7orpIHP~%)mOONejNZ{2)lj-!1(F?ie>P7 z2CFjwGWJF}lr}|oGP`o#$hseCXH#Kc0?0HYOki1}PSLYO*jf=fr2%d2-}4t0I>AqP{y6Yny5~<|7gnnn z$|p<; z%r-4p(-Iq}PAg&nb&da$!MCUM8>7Pj@xB^)WwHym%^Mf=DsAQBK5Pgsy5Y>|ndt+Z zC9F#}b{4&S+g=w;&rQG=y+jA$-vH#)sNNGDjINUa3?2IoFmXyS)!J#x2Rqc>pWPp& z&q*xa=Vib_z&ot(d9H={s19Qmn{qRZsS@-7@JSZTh>raV7zsV5v(Oe;0E|0^J-viN zT%j||Nx<`;X-vH|#Rkig?z9tCssrovri`0v4cwCc&CDyOfAuAj^Pm4f%u5L^7}wLAds;h`f-Lu!f6Mk=(EZV z76OIm4q_2S%xINeUG*D5%+nh1j`ToG3iRwVclT43JU5azA5T_%UlkDf{ORAUS6ExU zPJeLC34Ms_z7w@Fx`(%@^SqdNYq-0{P#FwLlXIionrB{_sP!facL$80r2(^ zMDev=*yFrvC5Il-#k~OZtTgq|xQA!3P&V6oab*i(6rdd}dD?J_^W zk;%DZ-%%RG7Vw%@60^E>OJM6h0jF1JA)@L2zAZ1g2yTj&jMKsIFvzfV`{P=$2Qkg! z*{aJ`bXy=r$y*Y&Wt=B<+JXC*xL~BpeH9|k@(5zPb{!&Iw*vcxN>FO{3_$80 znof|Td_v_AXYPhkGk##nyeFy2pEYr{KoXWGsv~S1$(<7P%alZtunrf#21asg&s0_`zZdv*WMCP8K z8CeR$0}(~OndDd@-CPjTl-?cV928d#$YyV|;9QP9`OiV4EG1JJ@$zL_-SgLRVf22Dc zL9FNhjnU=edOPoOy>utEyp*t_tR*Q2pVX$$;c4~PUK5Q%HDlDF67FK~YIPSAQ2BAp zz)-2)vEI4MTNl{gXnlQA+bVsjb$+V4!AI&;(w{%wbYwtOvvh2(G6q2;r5Ya5*i{mU z;bN}|G3sLf8{)$yZb?WPqR~Zv#a}q|gH?*DYLIhDNF72550V>mQAi4c1og;S(AhpF zKq6I!okVARvk7b6!g7!tI;wF6&;<5AyuAhq3as(ns{RQc=A_8aMKpw!jW1ZpLPcwe zmpHiBK{)!$Gr*D^Y0>}&5`B+Okk)<$m?!q z_6c0GINj7sOmVy@VImy|IWtSW($XHHfY}d&4-T3JBOh&jIO?F9Ovf}95bI%i0DQFS zTbws>N@?Wtwq=t`*LB;m_^J4=Vc9u3Co7&jsjx#66ye=GQM7zgeot#k#)JuXMFeML z-0bn*^(^0`87nN3P0A9%Xo$25>Fgk{l68v4IS0w;Ni_L_#*rIBkQ=4#e(vmf zH=dZ*lPmA7F0Z6?+b($rSUP>-wzABMfPk^2cQ5+1&HT(}4(2_H&xM3|f(Lq6pT#b6y1HWg?cp zEFMwBmHWs06}q?z;J+WwCFc(YbuQ`6{+8`HI~q@%g0dH!KV7xT3-h7+GJbdFPWDwM zN{`8*VBgntruYCkARR7JD`T;Yh(znsy^*hTIz`1eMzw)mrxPQgZ-opZX8e;*$@|-h7SJICBH^9~mmeWAH7tQMR>z-UULA-3{Nip2CE$ezhKMhsZ+f z&0lM+I=u-hTUhN2truu^8$WuYi$5Nh1$NAdH#E6}-Uj3Vv@I^FKn;r)bu1ZKTa?61 zEB2#2FK`inSTm7aDG$qAxjl>OnK~h~RV3QqYQ|0IEHqSAPP^bmRm}PUB$~@s;e-`c z`G7-ItY%<#B30>BRrgfj05nX}eG3A07W3dbw16hzf!yYShbFbE2(A2VVuo}kliKX| zEff;1sB?=HgZ?!RXqx?aGS?%5?X3m=O3 zQDV1N+S(A`l+2^E+#?Ecj@SNYe&I($GTk80w|;l^lmiohpRGayBr!k#dO;Es(eaDn1OA{_EY-6Ea<^_R zWs6ucRR{j^_+EyU)HhX71LVeuQ?CKR&>sUBl|BgD@s1d)tE-SW=u)|*Q{Fvl>dIbZ zcxEsgS9J~PQv+X*h7_YyidvYFlhpurE=l~BI)ezb)NBybZc3KYwJT00$XrgI6bE>v}&nAKy%=|D}9Epn* zSWbS2IY6dA9K}x|ouf9UaxR-hWkFFurVOf&B^@hmukP?VZCC5zNx)zC`g8HmgDRN& zyC6yeXuddK4OHK~-#gC}&jo%yN*&qnMl2eF@Q^sC=@F4O?1`Z&$Hz!$R8-lib`uK>X zxeP{TL&*ylrD|{GjN<|)?*bh&TOINzt1i}GmbsB=ImJilR!cjo)5 zP2x?T?mhPje`g*EbuxeI@=j~=bSg(o!>p{2vR^mc@-m!%MMYmSOlAhUDj2Z2nZVx% z(!Yzc5o685g-YV?jT)lLJL{%7Zd%)tTQK&junv{U%a+lYckMaa1n@&ACzg0sAP+H` zX>i8uQL`cO>xemUkfs10;pHW59=szAx`%twZ|OGs+XbJVGI6DzF-}y;52%>Cf8V7y z-8tX4i*|VG=f_^?u~|#_KKhR)?gx!ly^f31Uh9Yd-ZmeV&f^~s&p#r*Ij!ps{|>CZ zQyWPV{D70;l!3?bR`o?T#2=LfmK6!&&aD7JV`A29X3{--*sc%Lp_-Br+PlRO_k(krk1)(;Lz*-VZTh?xHy9tmhk$bY;URmzuo7(!kEey$w zzWy4&{?KxJS-CVH>uop*XS3V#8i-reWA1tumaAs$>^-<|=3wl!-Ey0p@&Ed$E#3`+ zI^;}IdzN(TG+5sa6Mv7s0@Mn8ES~Ghmw-&1CLP?gvmJBHUo|<>%#-$gin~5bNPM;KnvfIz3RrcCc4C|SaiKGD)wp}eYcW$iF||kh{*AlI9=#lt zu&WLfWkbWpWFw`Ie}H3NA!l-@5Z3<*X8nk{dZ@a!`HM-mM2SEhY1qz_CTXv+JdYcI zE#SvY$i~UUj~gN|$4DGCWNHS{Qj}K^S&}AA=*B^MwP*bKAty}m(ua9Do+h6iPgWhd zQUObK*zH;3&}+xUFVJ@w?G)=YN6a2>CTv`_?z;3=W4y;y?NwxrNxkutTvM47KlM;NjRFr9`it>o&1~%%GBqm}qvLqX ztJ#ZAH)o2@+DOqibJCx@^Zn2ZqQlLZ4DjZG_wY6m5sc<-1o#(|gV|dFAlwl^lyrT0 zNj|OWNUKWN4bov1O(_2S+Y@tta(%@Vp0bOJb9TLjx>;XI!Cc2Yk8}|^0{+VUZ5R=` zKWPL4g;YkXr>@JQt0*<)8J=&UL2cSO< zj5n@g7#Dvp@Sap2gv-v}#$$@O41*&jk=V+;6qc>sVVlbib9DHwype2ax(35t-3#`+S8f`pT)fiDUFqBDTufI z(e~HIUhQ){y@?fWdd%n)OCVgH(!wPfG z8?Q-h!h=00>oc!*W+6U zfxJAv=#fk;t_%1@i6!coXk@uPzmU~i2oQveDcCQm0!C|e=Vi-Ij6>QbMg;{{hP{X- zFN--8c9Nw>Qs2G3o-e6l$4brxCzFh3djQI*TR5@f&zOi_=T{bD4=>>*o1#}V(DfcJ zEWJcA?@)wJUDEOsX1q=YfHz?eNM$28-gHVi=a-}xgv(nSNY+Hp1sT`9?4b{CWDlgqG8BYFY$+nmergujfR5 z#Tb}pm48jGQnWS+?dAp5f9jjCH{J9Rrq^tFR!m!){#AWDYD!5jD--L%+|{%jPXbo#IG%@;WGF16$1E6*zp;m&e(d!{ z2>9oQOP)|w;R=*eUT7b-q7lB(8=Z@RsASCJ|l(}}oj3y<oh=vBcnkQ{Z}N5L z<*ruL)PLLXR-=vEahnJnTWoTse3YYN@uetih9wM9mKstClK^;H&hm}^bh#+pgvoD? z7;90KgJSuJnn;S)9HJ_TVVCKJ-Qg#?c!HgTpZs~Iv|!xi5Y2p)_eIh0c~P(}RAQFe zKri<^iYE>C0+{o6m`?C#FYS^>i&@y2=oLK3R%HIzJ_U{`BLE4*WV?SyTRO}5irf>r zxZc2~Maz6Yj$Iuxk`tI2x>@-<${9#l;|HWKNwn3-XfIX zOh-riP#L<%j2dyje3TSgX=r>|Qr4ol%F<6F+b#uw02)r8qI_WrP7X8L5>6-5RHSy7 zVw{q1lJYt!N?5M?U*Nd;>0?$7%pNce&f!+dINI%ahM;*cu5sQ6{)`$3S4C*53CDzc zT7BFCJ!(X>J(C7pSid`t!}R=bnTPa3+7|<7xw|;_d@$|6c92EE6kl(z68D*d{?rf8 z-ad^@N_etjB5ZVv|2!aH{0F3wk)T6ijXXCm3 zuQRX6vzwE{B9g1zTQ1NtC;TS?1C&BG2GgKi0nt+o(13wd0G&DKKGB?9X~gLozS}x z03Skv*X^@VV_lFnCdY$pv#q$lzQDPgsApoSQqTuY%36ot60_a+ z+!(rks?lt!GC;yS=x^+A_2*;Zq90m8H?*@lumWGLs|0!AlZpPr z8zLrGSbJv{ZO7reRAy-x6nZOg>%RB)iw5-M16a6E2QzK?$huioLo-_6{I~+P8a6M# zQlfH}(Lx_K#C4EA@bx^KF;G>001Fe}W?fsc;W^6Fad9Jwyp0VELUA~AxU|jz@JGsp zP*k(k+6D*g)$=SxBs6TdnO&v5oes@4c%`I39dT%Y5S??iEcsO={C7i;uDoKvvCb4*efEXVqgQENE-?HQxE&Udq2n!1X`44$O@Ilk33D`2V;L+(4kI8;&64&>UWy3zl9+I=f$~P);C(04p5c zF~1a&fGiW0nhYg5z9w{{M|j~i)s{M4e3r5U70!QrxKbX|T@|8{irbJ#ZDMj$T65~( zn&&OK#6xz1lqSD}M~~@Wletjxkr)QQ;?Wr8^Oddk-mThVs>>?$wDCJkS%uFHe%Xxy z+ofNu#dFQ}FNNFpHcvFSg&eBh0qlLyYmP0|l1ulKH@w@f#mu+F*>*bK*U!FaAeZOA zjx#jnWZp!-VTGUUsg(OLLJ+=K`pPA0xdvbg#3~aX!3)Q&>o9$ppcuMN@rw60={Fv_nnvg zV+K#rnhc)^PMDTU2I z;eEm*=No^KfNVO1h#ev2&I(Lo+~IwieL}HD)E>&+7JK8#lEgxi4d8P!k6mQJ;fchT zfdIn(&Jo>nNs@%Vg?B;u03>ANe9lnTz>eU&tbcdPqwE=u>NZ7L9Yp9K$?St}fDbwOu~y`bb|M!D`S3a&alsx?KRI!y{PEVeoJ{gd%?0ba2aap6UlHG-nr zV#EZwG^lOArRi} zdcBRC7ft{vMz8~4+Biq6$Kd$8zFQQ`wTpUF?S%55{$XBv@2VQNx1t`YE04c%aPq00O0A9dHf^`ghm-Vst;T{73SAc} zEmlV!YHJSm2|TqL)R`lZV2vwbb)N9WmIntW0-wd{*boX?x-6>J7h}0cp=tVTNTWrw z0jll*1I*c+vFmx6&0x+~hSnw>`pUSQmMuJ%6Wd6$DSLe!0JWOto1+1SI|&@L1NQ5r zL|0Vv0CSA^xVW6lwjXV2hpbC6sCr?QgThLgBfiUO{M@x%l4|t%g}`bARGnk4V?r(R z6(uyB(D+%HlNc+-d9gdMJ7nqVpM6f^s6Vn2@W;r=35~#2DdtqH{s_n}B88yz<}!J0 zVs#@wr%c-nARuIi&QHZ0q!?00I4qh_r%6=2&a`fYGK?zay8No+AU#{6?f(8uLunIk zSZR}PxK-AM17lZ8Jl^TC%0WjDJo*A2`{mf9kN3@cbzbSTQ!!SPUY%au25SYjk`6K^ z3ROROWZ<8I5!2T^cGCRE;6Ddd))*p5PJTXM2#rL0z2a&Ly-_n#YxQQwysuNnXI#oYJtcD>w>=1$-7Yyvv1`J$|$!S?;Z zTo+TrPu0us6>)^jo>ve8toNlkQr&cFYD>t_ifyK7{|EZku-hse#JPysUl+thH^K3@=^d8`?J8BdTBuCCGfg6w&gFBU-ygP?g4JzQ$F2GD=5orjWIvgs zO-EUp$4#Ee-<|hbpuflVlZep*O}*}kt10`C>445`*MK}18SyyG(J7xV*S^vfpn!{@ z%SAy7SsIVVmF=%NQz0%KX%PrtU1u>^G|vfZvQg%*8S$m~_ixF}A#a}bv|lgkr?zq5 zh+j4kXqrJYL`iXsbZdzQ9i^1mO5i9$*YjWh!->#|(g})*(1G*okVpzSUDAtAKtYy@ zZ*=H^`rpdyE=PFhawuFI$_j@OKme_aRg)Fi=%M-<>mCNU%LX?r&VVpp)=Ivp5?3Y{ z4{X}A$*O`WT*`xH~LIeg~Hua4enzQr~KPAuc&C2&b03CiMcT!Cps*-ipth{lVKCz;1@l>jwV# z&#_F_+!xb|vwi2P?FFkt>$LCPG!h9stjthheGtek=y717RxV%NAcYq*n0Z41YN^gr zpy-8UW4VZ%I!U-@(KJv^0FaUyxO0|gDDk&7QC+-Lw#|;*k&v;JvF*Y0C^ye2t|nd_ zs#s35Mr`kz6C$XtE;*z$V6{taCZ5Bf*ZncwDQmtj{c(|mq={RWL?$*WYAoRqDPEt< z>Xv(_XQbX%zBKtJ>Y~mT6Pf6oM1-x3QrT+3{Azw(gi^P(V+KU{w$yR8;PW`(m;s~A zlzCEloBAUM%?EMVh<8*2jXd~#5LU8p@3&8ZL6vP4tE#|CUTS<4z^I*Q0r6|j&)BQM z$b2s@j3^$;QCQjf6Wb!%H`*Y2UW{swQvvyDNHA*X_tcPZfFvXonSpm3JwKO$_rMj@ zBytMHR_0uaJ(B@q+D`Ub{{1*UW_UV8Y&gC&9`AA=QeYyJ(?cI$13%#A(&ggB77O6~ zqSl-JwGnX7p-sa9aL=*lcldX+O9x0H0O*g!9T=L~CRv<;T(k&apgb6QzE@?IqK~8- zX{lbX5eR+ZL98PUL?gmj@Zz1YhBMsD6%J~q@JfpPCm+nn2eZ|n4FlTn5>X%Y26O%)11K@g-ry!DpyQ1%|B*V zZZ`Z2PnrIBvFi!5nFx;jSNRF0H6EIa$Md{Su;cmga5bSNm3l8Oe+xTj#DhO=-UG?n zJ2J|cG3a*!Q2E4ff;K1T#a{ZuLYU4B4O#R%z#*5noYFfg;FEO*JV!$w6Z;Al{`@z& zS83k1{@*?=NyONuEz(MvT)Y`d8I!&;m?qrrxO;7jq5H5FNMRpBdqzBKmJFj7tgx>~ z|J!jAJUpYEo{LvB=i^r$xtFfDHJ_KOZLeLQ*!a^nz~=W#^Xk&s$7q>LdEs`TAu6@Q(-DG}RaY=fyz}a@5jYw0qby5FW@q@ zgq;Qa&D>gED<|MR-|wRlHR}ia2eoHa$ZuHfw1v`Oh5p z4OO3!?Tk|8KEwG0yB$Mdt9Rf-&`f;vb!Z_r7ugf&ZHxDx4?M*DQz#8 zCEUbWbaqtjs-*K;?d@oua>kuDYJ46Vz-0)N5)6xO1k`NbH^5vDLCy=f!19=JvA8g3Q;EuwKA4%2q!cnB*Wx_ zax7t?9hF}clP-EGmNkmqG>v(RYDM~JNOndtt4ql~LN;0{vv@Lv9Lq_j-L$kBfVmxI zcVZeR+#^qkWM(ea)OuzcZ+d2iX_{`D4pV*HmQ@)?Et7nrXqD(%Z&B}o*P+#_*}G9U z(>BvI^XXS3x@)**x?#Fgyldh<@EFv-{SI>xx_~{;H;W=zGv+KBe z0_HJnp)jG&HecaxHQq9A74h~7xTZ7q|C@{8w=-+po`M(c67poCg+uDSwqx*1r}g52 z=wiY_-Yqfz-3l>S;P{?fw}eW~uUQZMP>ILeuS8qU)mhrTV?Vj|mf@DjRxZ}+bOyuC zK_+$cIW<*>)GNIg#3y6g`yKK2oT)#=KHEk{P`@iC~K!6+76e3wL zO>Rapr+?w(BR*R>BgZAvmvKIS(5-uO`|DZf|o1-Q=STpc4gb_)UBHOE+MZ9ZHkM16SkDz^1V%GzyrvaM-lK&*tL3 z_39H%tpjPd=$$_d>xgB~fD!u!HrU&Q&Q8-vn`Yjd3=&r@Y{c|8An|IQDCPR0{QIoT zTXGR4tm{Pn&)NN)m&m3tSjO7h0|>x%l-K~(7&P}-K>2kF$BtL&RsOqa+sTs<1ute8 zEB5yMBNUFu?O>?gVDNc(L>S0qfSs2-y(<3y-&T>mN}2=E-OS(<)7_|+k?t(ca~fk8OT9AUKV9QO1(FVFOh zhQjd!M~N?sQ{&CV z%np=KS&~!ABv1<}U`%wiggilvLi9G=!dQ zpB|@EFjhexAkp~~R#M#5@8ZN%f1@6;8oOG|PgA9Gd5(GcS7W|3+mGQ+yf3o1XchZ0 zLH5U4MQFzH&exIrOk({=}Ir?AR_GbChIzY>Q?p5v<6jMwj#_T7HQQ06iIGdJS~#YY^$2#zWgR*)8cy z6aEAvxk`-l~wjiAtRflaL6c0B)TbyD5FrRBr7x|Wu&Bx z3L&dPS?PbBLC5iXf6x1W-sjWj;aul?efPS??an;@+&}4fTzPHPcI=%QCEnM6yw8X{ zOY#q%c}`9>R2wwvQX8)#tFk2@l}$B_f8mjR?|5aE$RRxLz6Wrle1pqX%z2e5^Dx9Sv+}kf`eDwEazU6m0Q8>{3oYu_eHorv`SK*8BY`1Hg4f`=Tn=4SD*@F&2)K5 z;BDcb7Z9<#o2+2QO%~e5-vW-U3~y{X(VS50a>IZZso>^%AwQ>FDWEm~>-=;^s4%HI zu*t4NJvRIT`Ao@pS~hp@=hBr9Dfc5~`@gsjJNWa4 z@ulN#dC--Ocw~|7G^S1BeZsmp--}OXtHp$Hr`~DtB2wiJ<&jtLBl0fq#wg|3u^!;t zRgjl`yN)z`KO?2uW`^T~bfN3Zdea*ptgP=J=JU9+jS%uP75($P!Z)F+KWjxtPW(PA zCXub)(VVGsD3bj2G^xQ-J1*tgCyrzKT(Gcct{z>tnzafn-#i0^z8*!-pst`)Obk=g z(TPF@sSSHt_WAZ*>`T*mtk@i``FL}hY}biHr$uaJ@TYHl?>xZOwRN=BIyYIndCTg` z183D&xU1yb45yO!5kp9ce+F8R^I0#>h4r)iAgQi8%IT7@mmGg2fiI&+dQCmnuc$I)yQ*YnZq%joF~Dfc(b1cwkJkjXIU3F`RLRMa?dm2 zVZSK1D`CgY6-FD#$|yr0euM6!@)OT)1W6Tpn28S=rD4LXqp(U-rY`Z>&78zdoK7*R zTO<6^pMFeQanHi}ZD?Xmgl}p88MpCGBdouFpnsqCzlhsch21ph5gfKLJTz|hj$u4& z3#-Q(rJNW6*IlC3BdmOGt{&DEZpkh~CQn1AjypB*U-{UkHoIeWRlSRr`JD$5JH*v% zFCXF6n3Rr0Bt995+#Ri%A|dJ&7XG%&`^iJ_+Az{cWqQ%CRXKmmuGPEC)!kTkpg_dX z8!A7=CPju;z6yNmsvV)$bTPyyDaz)S$Zh*|l6SUzO|sH9=KFKK>6l0VRA@~9wY6Ph z+!s81y%LCbZ;>ao!%z^Bf90 zLP5HA^K_YovMR+TqVu3pj#HyciQG(-8HAoVZ!cnxH*~eRWmX*>htl%q`2( zNGN&0d5|m4uIE5`!xWAnUh6sVNPRH((&x^4;iKIGeF?q; zt3!42R3bKbv)aEOcW9J-pqaXQW^-;w48cUeV!+QTA?H+j;M4I|HMX{xubHbl`fon^ zCD+uG18(KCuU^0M=Iyi@rR_f>qO87(f7yag+WlE-Rq=C^JEvW=vOnEbp4@Ome&wCh znJ!3?2FY)$G}5Hqb+fS2Elhl~Oo}TmwNW)skzf^l>|2;v#Cstl>Zn*-9f6bk zv+wqSyD2ODb#H%N!TNZ)K=lI ziK*Jd!*x8=!uJSc_x9@?|8R5k6iLVVSF3lF%7~Yye!=dpHVo(V{z7=lv7}!Asr_!& zQ&N&FLz^rjI4@LBvYf^Kgs*;vYU$cgQ_+6DI;1mXLsWWkQGbW(8~z<@1SQHj@Ec?F zFB2la8W%_Nw8^ik)+r=OKN`NJqZ1hwy%MH4%z~F45gxcZfAX|g3&Qxm|7^?Cy**C@ z;CKyDG4t7{)^05NguUaLU?yXz0+u4FKAGg*OXts7JuJj#Rd(rx2a8Ace z-caw`Ki-MKYg2PW=Pi4+zKN{0lDve~I+g4=xOH@^LuAsHJ|FVyNV&SSLq6lBN|8Y( zd0JQaJ7JdNzIn;+>uPX2pSiC3tj*G)qGk9^?PE&9SxABn9iBYC#^YA?fy8NP^^Hz( zH{-&0lMECtIld-(uGZ^+9m%`>-t>3uAsy0D&i>wFSWW^=owRGHRZ+|<-8my@e0QOi z(hDP(6AjT1rb;#P$QJoBZypACJ};2Mk zyCeQaK;V#=;g`UR>FCa{1^NftRyke1T3%S5A2#`JifiHlcK0ot zhjqaLm{#|A4t`_hnY^*m75tx$BOgtwYZD7uZB8ns$W1^di=xtwxYW* zU!MnzbyUu#Y9GH4JSWu0)>k}Dw(4p%o$dYf#bb|XRb0fp$+VI~+fbH{yuHPjnAIXj zzLa9B4D~`4ln#v;-WWSg-i)2=ljrM$n|t>&8{S)_!*iB`JGJWvPo;1SOtB*aZjbBNM(DDyz#J^{9NOoZRB%(J%nuKl8{-y+YtiuqTzGSZ1YB}Bw@?!xc>K%e1fgl zU+bK9SSxWm{d&l1wT8Q&bFI9up*>bkhiRqbHeecG3h+7cwe+;OtT6k=+s85-BxE?) zbuYf?QU_|f#T7SiVqdauB1&~{tPeZ+ln1`m`JL94yr@+1ohjlI`G?%zwJAmIZ{R*^ zaX)lclc$=@qv9_xlvE^dZ&q2Om}x}HEN6SR3i%kT%$jpgCZJyMnk7r~XPxqu-95!B zEDu;O@JFW~xgNnIwpM7BAp-wHVps3Eh;L^%UaolZK%^pf}Hi4@tTYFcxb&!59wtO##ra|15AeprybHBwU_$KN9_ui z6FceWYfzn6ky>W?z;fu*eC&q?OI9C_n4|&sZCT%3J|{gIKmR0K=e>-8`ie;HqaRhs z>|>93(g#bA+7LU7<7CI?F^*|o`IGzuDdbIh`;#Vj(yxOO7uCn?G+7ty^rh(!=?z`Jco-A z8xqXagSM5HJ=nS@>u#ELo~2CZ3)l|}LsoC;nCch_J0&dwYrJ>@d{FuQ^us8ys^cUF z^SD;?tXCS68?YFBC5V0Y&AXgep|;lE{DLs}$7c}e{=6;Wh1L;q5!;zM(GQVFwyMd# z{Or0vV(NOI-1@k~dDvU+DaqDvl%rIxs9Fdl@qbcJI4|)zL#5u#iCp?)@3rLbp$Y@>R)NVR_$nh`pWQKcR(^Y? zm0@U{kQ=TwpZoq)>GibhYmR+cm+jC9$L{PQtM0$_+~Hg#hd_;^gNUo{$kpiY&sc88 zyx(OvIz1&}cC01xwIpQLB(*Y$|B!dyH`SoWzk<6?-S_)^L_}XgPZ*1gM?s+(p93(7ikPhz3*vXzgeS+XIep49|N%j#wkB!JS`nW!-w2>~TE98)~cA zE3T1O7M!%Wmp=V?Q_`8O#2$75BkS^a8&Tyi@5>y}oXe7lSbbZwcJplqXJIXQ4*M^; zO}szLzq#-q|BlKkYI85$ab;-Y_@p>Efqcyy=|uj3YQFvGL|EvUf%ni@XT@yS@n6Gc zM~XTk3+H~FtiR6pOC>*e@{M`DdD&Jkt9!oVUy^U&eTux?J-dE>y!gdK@<(-FWBIQx z%nP3SX0OA_<0sY9+Nao$yeYD=AFD1eF}V0lq`XI5PMTlM>{t@lgS98W zsO)?ya;*0gzunQPbDA~>b%*!&HP&D8OwF1bj5SRD<3MH+-V#05DM}dlEpN7KQ#0ow zB7VJi>l&S0-ieF&@VA`r5Sd8h7eW?17DcLSSxs?9rYhG|1+TIDa-Qz&`n4}Ud>2vY z{Hx4kSl&H4#YU1=k)t{ncPOvsep*|%GcBHLHSFnno3ldS*545ndSeon-8`xi*EFcL zk9ad%HpftOh+Mko)R3yKfq%}3>3i=%_tn2DyWEi5e62M7j1urohx_kYt(T4o5^FHb z<$mjPx7O`-;uXr4QHE3w+FL8O#Lmh|&SW|7bkcBVVL)Z8VaCR`vTP&BgsbqCVfzSTTn`g7#! zpL`q6SV`E%a$k*_aLhI>>SH}24s+z>;yqEDh=3P=H+EC^KdqyK^S>oxq*Jf%cXwu| zHSTiPhTPa00Shv3*BL3*nI_HnZ709q+I|V|VLY++ueuueG9I z=i*y3)zXjE{+Nl{xAXVlc#u~2{p;zi-7ehU%=LAf?#e1e5U*E1%hQp(Oj1Luk;uWS zN5|*KY(I6i`MisTf0cdxJ>p=Vm#L`N${!PX#}jr68Y*y?6aijwjnC?rOUqe|PLr^MUu-oolNzkwYA+9!9si)~k=_jCbn3iA=5x^FDnW zzh)R!&nYq6vDVOD;g|iHUi-c2J%_pLb3E$B_1Wy=y~=pp%W<7U$z1iKJ}d5b-u{K{ zx|?&TeL`T0#U|>;cee9nzfiy9c|Qt&?CLYGFY}q-BzMM1r9msl_Ct-z^DMr^Trr0l z7vY~J$g=hi+j|By|0G33-Hce3nNr!L5y!{+gIx9dh#|JMUF8Gm*ENT`m!7AuLyX=( zn^?BlspQhL-!Sd`%&)^YGfQUwa5p6XO7?y!a>_SBJmS^Nyu)gZi`yj0<$u(YOTS)u zwfmD{hOZdMNYC5aj-G+F;6zCJU6a`8W?!zctcYO#hv#>Pe|G@yxy>-2GHklsq3&;d zD@*AU@$pkt%{`R?@Bw0sde)S$zZ7}2UUC$YPJOkZEo(h{pvwDdC!3%vgO@3!P`u`5O`GS^v7c?_iN*Le2$Q1hCX{VrP`9d_=Kau_lE zXt&la>L7fxXmzvP;mFdU+%?_<8`UDlSK<#T+*GU0lC=$HQ+yh)d#N-c<>dEC@57O` zFTHna7IE!rMt$@xPKo}SfnM2u)n!8d7=O-3^V_V+TC0Acf8pA9b@gOT%gvJy&5_4D zYeGIB_@1y;V|>F)yO(44V%|S_SQg+lpc?Hz7wTH&Z>MHuf7R=a+6^`LCc(tj{BhTw zmc^ai9r3a}sMPXyhhwVy^t+2rwg*%Wzqsvj%a+4p?Jc#BjYrBta#b3;9LSBRr?;gN zc;r^uh)jLRn2mVI9yKMQ2fhg$Rq4mt6F>bbh^RK8#Gi4U^jV4j+{(?yjd}cPgGy}?ap}J<3wiK3{HfZ9$y~>x z6x_ctn`bI{tmE`l7|(v)hM^UiNn!E9{hMHlH!JR2R&_;uahQMSpw$6#K@M}=IV!P?kIoTV17o$tLw!LsHDXBNL z9Jzw&G_{5LCcB!)?sU7x2)NWQ8>Ia ze;nU>A*jCM-ng>foAjB@__)tI@&+VrL`?d>*ZHY%mB+46>>Ug9NmO=KKe$KxvJKhN zw5Oop*Mq(vR$j?zmP3{Unop|WJw_4rne!iZnskruNZn;-Jmgf2owNRv?GF2K*-6I! zo}bg@-oznyTTjE}8$Z{yTZiI!^|np4nwh>u{WO33oG;yqXBb!X)|5M2igjeiMme^# zELS%49V;5n_e^r%vH#X1r4kXM*(y2j=VYg_yDKq6vdW>V$;m-C-1aM8HnL}F3V)IQ zRq>-8_Mo0W>k7XYg%1_IEU$6>Jm1lECwiM}mxasSuS#k0+g4-g21T~*>MOW*v`ecyb-4vf zUd!@4Bf-Z;Y_l2D;K|zYW=r&rqV@ZZ52>#XAb*uk*57l5J@;4dL(aAnuoj#6c=s@N zix~G6m%H4WVy#N+t%pkG+kHb0#^rRtge3EJa+h28xvg{$?;EZEp`Y(k2%F3}=FPgp z){~HB<0OnTGT;93&8t7_S^Sa_UA=}06e)Ab8M5^+YiiXKBN#k5@1Y7<2sIGdu$I7uo)dw8S_i(2`?xUYCs!KBC-?=HiUBEjW_(E15cl3pxC~ zyxobGN!$AkAg)+WeP1bO!=x-sPHlky)!<#8-+NC8JV7@|*EcAnOY-;DrA`<3=9Nxw z*g)Vja*n&dz;b`ZhM|C;9rujFdqToq+#bgdRHsxz?ZuXdP$rAZ1umWZy>59@o>M%kFFKvQG0ES z_I1S8Z!djayrHk*YRBNdEhKGNn0)df^);`<1Rfb~D-RZ}+^6F|Y&8;Q>3=W&QA~Sk z&zS#}dmZ@FiJYdq(_|bmJ=?2pVlN^=ZdBg+5YO|2G>vA@dnJk~JfHDXQm%#P zd9ow9P~!KYUj4*vC&^ZY5_#;i5x$axx(&(Ml{R|w-d#|yXp+1hTa!~jPyA)H-W$7Vc+T#Y_={-0$|Sw{d71P6 z0re8(D@l3}J?ka@h|8Scmu89f&}Y$B^84|t{%p2tJ$dI5iRohT>64DSCVz%^&fB%0 z^X~*d$ztv6Oy9CZw_KXq*_|>~_h-jv@sQ)6#mOfh>mG<{eAMx2ObR`1NUt;KLNK)+qc*F{IK6a^MF@PD|@wZx$E9s)yMLfW*n2q63bmJ`N(UV zez>7v+RG>bbo~j^WbT@?R=w)-`=Zu6VEIjJ=OlYmn{T?miC7vODBen+Vh*Ej>m$haOHff`G z#XUnF0Enh zZ6}RhndROkznzs(cP)Z9Jj-yLdJr(jV1rmGQLp?OXK2^DCm^Z+j;qzVt`f zZ*0>~>&hyhL{1+K+huo`iY5c^>c@g=fI~wdor`3mE&+A9;g_ZSxZ^p%sn2el1cGYk+|88sN zKH^JZ4MeA|231dlPCO@ znU8rud+o64n+ozksMY$H61r^<+r5NqZ>)a%Ab3KrfwO*x=8a8B$BsN}yy8o={#cwX zRzdtZvg0@BlPZx3^EaUn4~iNN?Bp&MBn%rpHJiQdgW>#|TKF=mY;w5p;mL{ZN)j_S zOIIV^_Z#g?mph=LOZJZRr=9lLQ>4>|DWADp7=Km!jHqe1E4&Jq zgekHe$!dD-rAwH-eq7>?eSOR{GV4tB-u|gR-N~cjjm6WF`=0(hf;l4_l5*DJt>tj- zE7;nK2F%3sj4Fk%J>*CC(lZ3Vw9Vek^n7GfRWRXmvx;Y+%D@?0w&~0I@t14?d-|dU zciD7rF;s~4y<_;(bhxCE9L#UoTD((BJm-b3amxyWkPlY%=XLB48wchnD;y#|47qqW zY|zzX?9^$QzPz$44YTf-)lNLL(7NfUdXS|o@tBM+W_MnB{;bczE^^p|{L$WDnex|F z@<(TWJ-DbAK!&!eT}X^Sp~~%t5(o)g%|7afQ!6}aebumw>)pe8uWw&Wiu~PDuLPi~ zTHtMJCT%y)g&r?eJa#lV^i^%{x3RmYjQgC2vWhnFWE~%@JQlU`*IYCH;gt({`166L z!Kp8XJ3sKWv0o9MnsgNFAQzOcd8X`w>hZhRnCSj7OGkl!JU6|I?{{C}=V8%vh3+zZ z4Yewy|vuzA4vy{kn_8n_10xj>?XQlJ#xyt)i&&sc>nf_1S}^Ada>@*xiuW~e2Af>(4>3v%F5mY(V~(sa*cqgl zrN*O*&Z^p^b2{}fnx#^-&^~Z0ii6iH#^)e=mcse(nPDRdPrew-n}mLubh9y5%iFzw z?y7HAilL*D6Z-7#DtXCJm*3a?R7Mhx1*SY6c;TE@f3P@*O|;k{)N|}qethYfx2sg` zZXiu7%mcO*i3Um`1@j!eqHT*q$co9&j}j6%x8+!Gnh)8RyS{EB#BktQvFc#|Z1&Kz zoRkrpVBx}!n!~6|FY6ueq<6WClNv&Erjb{gZ#aag?vFN9<2r^CsWp6(Cf@6N3G zF{Wa4VneEG-!w9<>jif}^u%^=)9z$$pMo=QNRt(z$M^S+Ucvoz%KAP2>TxK!@;-TM z#<5R&hdtkzj?d`4anp;l47q3Ur(@(8-~B2@Gru76+YeAkZl!fW%*>$*&kI*>koMbp znSFK&$|xaVEFX{ld@>Z-aOVrr*qQx#LDyoPxco~V4tbAX5>N8q z<783$x#HoAEl2FeUhI|*;jS$84}MNIeRHeok6*#+-l6(OhA$@3C+FvioPHF3e`At- zrWSi;_mAoV?fHi{ z=2zh5(BaBqvWePG!6u%EisLi=lM&fNKO=g{K59E>41Q;Xrv_W9rOg}@o=@#Ah#()U zSQ9(pH6;7IZ6Z1QPgPNCQBiA~!&Ftfc_O>kJF>mK-a~_XKd&^ICl-D%|C%*m|JppU z@|yiO@E&u$0nriJNtJ*Z)U1BUPyDT-i9OA~E|u+a3n_G7|HrjcauxTmylqw4_o6|0 zz3v*@Qc?Jy;8azy}Vty$lZtsQ^bCeLOM)z5XmQA#Wv6n_5ae%HB)xQeVwktVgOK#AXM6l-F&P%p*lkU8K;Pr1(Q8q4;eoIyFT}HyBUau!&e0296&jLG(LsIUO*#hhrI~}>b-S%v@^dL+A zxt3rmTTrtt>gL@2aU+lSfT3BQ6X3MJyI#F`?bK2~8 zjJ9xd=2dBZl|T1>SMMwEu&$V0)IM29b>31AY2JnuvK8rOTRB4t=42;h{{s?Je7H9H~A zEU{C6>o!MLf=!BdjAO+Pbk6!5ji<7`*M&T4_8jr;Ar^aQ#hnpy=Y2{lN_lP}E|5h| zSRHjn#ED0-%-sZk6@hi?EoUSq*((zA6NDxtBrO%PH|gC;m*8$& zrMD4nqq~0Z^IMrdHAsTM#r+$ipPpMOB(PpoYV~u8?>>&+X?B|qZ}mC0{zk&4D6LC+ zyiEd5;&(1-*=$bwZ{%*VOlT*0=f+jhvHPP|`<_R9+?Sxi>R`Md=_CEP zFkwa1yZtBjh?!-)xu`9-E2e$VZcdaSD=bT6HS)vSofDkrhbr_lnps>}UiEjY0p1H*N6WV%rL*J^5?`iM4^}scmnu zS+hd#+m<{}J$Q!=%Zf*q2p6-FSOfuXK+}X%VV{?&r|Us4M<)atNqy4>bo?DmfOEGK zcvp}M7+ZYD24{&l66OL2GZ&uwMiKE?24?BceK!zbXc!tnLgW7fuX03~90G->|B45&bN~VnnLbJczfwmz6?8}d1$`KW z1QY4dC=>$lOI4(*DyIc_Lf-3u8z(0kwO~+XWd$8C@YFjRKvLChVR*pJ>7YLt*Ym)V z5a1t$TRjgP76JazerYh6zRUG4Pqj5sIcx@EH$%nn&1jD(L!p1$YCU?p4_5>)`3< z?cnR=c`!&pb1(R_14mpBI+^HdDCi;leFL0SRTVUWLBL-k0P3U23+%RFHY_Bj1rz$8 z^(=0H!qG^ga5PE(HEF6Pp<})-EX{TPwY^YOJPf{qBK?!I z7^1Lrx5v@K;a?M{`8hNl^pEzeA3p8W$QN|D(QycK%BWRG((>Jq)x?1Gf3U3~2D4M;xeA1R1iqcHS1qU8_-3PVq)7+T@@*GeQ{A(`|4s6=sn6q?>i zVg8TtMS!xC{xQRflTm28z-U_H01Fyw%ZWnMD}@{eLXqwBCIULk>lw zFp#?*OkfKdMWwB<+rbaC>9l@f$;t!;H5&q5KGlPfcF;gAEUiFyEe~9tKq<|(3PzNE zlhWi<#ZfSDI!gJ#oVLLTq^=L!v=)t`ibp4jMnTmkunkbKKFpN`3k~SQ5Mm3MjC`Gr z08BKpG_*9;L7oG!O^}i?Oc=7;1@i&(s;uFggccd0(q3SMszm5=KbVnc2U`Q^Q`JeQ z4>}nteS_VwYdh!?P$VS%M+s?&>3q?|pz}p_A?VB}I$sy8;42|-3-~9_w9lfwkBAQ+Sz&i*EIa%a}@pxkHO>RDQn8V^3y@+79~NmDj{MMOqiLeCEmW=&xj06m0Q9bSTR@#VFeQsW0H;PRZGO7xjfJe2NY=q zn`FfhpkQm5C@-3B4!TmPQb0|Ei*~0=P0L&u94(BetYL*LNGR6^CaSPBjVv)Ptxhwt z0i>pAwS>F8Rcm8&Il(a;q;N@k-~FuE%O1yD1~dplS@zw1zm!P)cA#in1*kLs+?i#pil)k2ZY!QgG2YtU>d9d z(<*1Gt{4*^tv_ALAT>o(F@i|ufWn+%qu?(+dLN?Xce*m@il)gxvoEcQhxUA<^Hc&b zJYm7m_v0vOi4wbbEKwfV^l$VoMMy0e(6Lbz|T@yB9L&GW-}ETAs3*#lR&kJJ3kbw7&!^25NGr1PE;% zM1_UaiEw3gu;D0A_=^UQ2CejRewI1|BO1^~6X7@&G!7+Cd0{vTk7eYFD(3%$ZqZwz z(o~w7w&Q5?LAIC20`;K&m-91I7UvU)jN*_`|3#d|*n`CA^tUQf3`1Bn(}H&YH)euF z(&$X6(rt{xgJAsswlN7}v4E@Kz{w7SAZRp_K@jE)yO;r?%NJ=p$fH2q{`C$t2Fu_b z%+qNJ8WO%lpNqr*9W1&8#j@ZWke0rv;kMY?EtCgHFr7A4bMt=%yM38XVKW}bNCDVv z(dqEi+QkQ@Qna~W8IF~sdpMee{wo7592XhEVe!CUKxTmi7D3?wi>n}11AtMn#l zQwEKl?ZOx&i9uT!G>VZDrETDY3a=~zqcMz_fwC4c@V^6=gJI(!*jHk{&IkFN%++984`m z0j)KLt8NDF^jCpcpw7RHP?s8fj5`yQ(=iHN1sr2q!-BQiV%GkT%N;0{qH}~XTwVds zn2@kQfs6ELC25gkdKe02(PyHGluEIXg0R3Ui!|x0hXsE@;Rv)Q0+PN?n+yy?s|z@w z_rC;befM8YFD^QvvTF-A#-SK92M*1UIcV!*KIlp|9T-a33x{uCAO(Idl3KR7#~^{u zDBdKtKnaZl9{N{6aN7P?z-7~Edjrse+(kA)J^gD(9MJM#+SE;nrFH~|R+MrFsan9{ zqy>hF3>k%CvxVCE5=qNKkg{b2aG-HS#?*o%F{Bm-EVL-18&xWY&i7^D1yJZQZZ-G_NPjY-CE z1D2+C2N)8b!9-Xjkpaoygh68hkEO)O(wIY2vKC&2QqM7q-2t_t{C`yUl03Rh8*$Wr z0D%Er6CN}@I9hp!d_3UN&_^e@AXs0*Nl?R08vIrvG+4jj0bLp(IMhc{D>5F5wPl`U zN1wDE{GBUGq=CK>Baa7M;%TLK5q=k>dV`K1B0Ix5HqZe6BFA9y#8 z0xI`{b8G}RM1WwR4F>*8>0*H&6TobgH=MjgbCg{mB3y+J305OGpg52j0Wq+D3G7J) zmx2hsa1=Cmd%-m2zHpB9Xc7{vUN9IG)m?zw*h19-a3mDv2VV!BrNhdvqe6iTC_vK$ zigQt+G$GGhbYwzUBvu{={0Mxvs9+2rj;Dhz<(1YFLl#HiB9N~Kd29Gko}?(@BCwufPe#*#GeDqb9Hd5u3)4ui35WARawQ9-t-=;4P`{|W zzwkw1ID@d;p!7vK=S~1QP2%7Z(1u93+!94$>54iZxquWXiVIpF1y_QIr3;udqiC3g zAmeDjRsDm7FKVI}z6d=DM?m?DO#V2zpjxRI;Aryn8S>DB7$6K)qaezJAlFzR>VPs0 z-*#v!7S2!M)O`t)prr#U0bRgZFk``9+m?c$XS=3@4^kbb`H)f zLhY03+nmhv3Q-wNGD?a6!U@iW1?%aQgiu zXfP43AWq-%;siS#o`=GL@xe^z=Lv*LpUR-V;CF~Lm)!h zNpMLri2%9)%6|yY#V?7Jqc6rWBoa-cTxeQ4hQm{?HZYE1Kzl>E-^4hEMB=E;!qPDU zNOlxBG9zJdmx+lPkc0@7wrt5{Km)}7k}*ISLurng;84rQK==n4!96-=1_5Cb<>DDL z9OY))(lIQO(w;Jofkg|7auy5zBQM&W;#ZUnI7UDuny}0lz+?=imuH5f?9VJ2!yqw~ z?I6Z6Fc%B9Y#7Eg!S4W&vIETs2u6V0EFA-r@yqN9;0O?+0xnJlUlW*>1Wb#^F}n{~ zH2nwEB+8cZQWln542eZ9^9l?Oh>1f`9OtbkTOO&%wQTL(fx7J9RV|-uU`&Fxrn)RE?AKPW~lmK z$YJ2P5lcCgWCR2V36z_ojALLomAb{gbPR{YGZ6uENlVfOn1BWumVrSsHM648pm%4o z69%-o%qF40QL4=n!WdwcWrVRHVwS_xU|Mm z^bY{B%xwY~!&6SbnI;n`_iCBOh?MPnrZE!bR`t>`67{AG(-<1$pJjl{VjF`eVVR32 z7^Ch@F(D-U2YkyJ1Qw4PM>OdhaXv`ii}fw_DD9|7iK zE2r&d^KLWK8#hkyu z*pkkcYJV^Y`co!^-~f&C5XllEIOMWafX0Kiohf5e#+ESy&PAA4Drh{83|3K0L_kep zwmX^tLX9c%1>MFc*> ztSzu{f@ca@H0W@b^e`0tQwEts3{9dmuS|qVSS+)%0yqNY0t6$2pcP)8*}>Sd%#K2m z$l&oErpe&6aY<4G$pR#M0+af|@`L*H%u>Q2&n&}7!cZVjs8If4E$SUmOVt0f#_!3HL?TCrfim?@4iSOSPK zCT6f8BQ1j?f#V%!IABjQv${ZOWVSm7)bnL3#DSv6Oa#RCGG73vfXoX@(2^1sY8iPU z`GCP?VFFSkSmrZv4fZf-q4PI!0XU$pWpJRRGmqiXOnwA~et@&fF#8q`Pog|3w!|VJ z0h2ILa}ubT%+|*dh|8Kw99TFmg9G_`8Cv4{uI5FkI#1a|7{{1qeg3}NtI5Oz*z;j;9CWDIs%f>*mXZA4A2`+0;@Zcbs zSzDl|UE1A%Pyw6tD4Y^A*I*xO*<>tWn;8xZwo;L)a9#-63+Lry{u*#k!a+V99D-y} zkQ7Y3yeQY5f!Zh!f$DiWdx1|NB&naY5Y`A~@P=NJjuue^i9%~&wJ~^Yf(DXA)Yir# zwYAYWEe%!9e+HpE5v1jHP}9Zfpu1my2SPyyucc1V)Y8^QY5|OzI_er)ByAlnu%HBi f2~v~}WslI$-@(_Py2nSUx&#!bq@=c?4(I;^eYY71 delta 313305 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 z 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�NBzTyBRF4BdQ?)z_SwgGlXhY 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 Z8^3t%;)6$sY2su!@}d`=f8B*6{{yWq548XQ From 8d3439700206360ae04fc63288520d64c802f40c Mon Sep 17 00:00:00 2001 From: kwwall Date: Tue, 28 May 2024 22:07:12 -0400 Subject: [PATCH 114/197] Delete 2 ignored tests, as per https://github.com/ESAPI/esapi-java-legacy/issues/827#issuecomment-2136294286 --- .../esapi/codecs/HTMLEntityCodecTest.java | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java b/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java index 5414d9ecf..869871c1c 100644 --- a/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java +++ b/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java @@ -49,23 +49,4 @@ public void testMixedBmpAndNonBmp(){ String input = bmp + nonBMP; assertEquals(expected, codec.encode(new char[0], input)); } - - @Test - /** - * TODO: The following methods are unit tests I'm checking in for an issue to be worked and fixed. - */ - @Ignore("Pre check-in for issue #827") - public void testIssue827() { - String input = "/webapp/ux/home?d=1705914006565&status=login&ticket=1705914090394_HzJpTROVfhW-JhRW0OqDbHu7tWXXlgrKSUmOzIMsZNCcUIiYGMXX_Q%3D%3D&newsess=false&roleid=DP010101/0007&origin=ourprogram"; - String expected = input; - assertEquals(expected, codec.decode(input)); - } - - @Test - @Ignore("Pre check-in for issue #827") - public void testIssue827OnlyOR() { - String input = "&origin=ourprogram"; - String expected = input; - assertEquals(expected, codec.decode(input)); - } } From 977dd2bbf2f59e649b83d75af2b200f81638cdb0 Mon Sep 17 00:00:00 2001 From: kwwall Date: Tue, 28 May 2024 22:09:35 -0400 Subject: [PATCH 115/197] Remove SNAPSHOT from version, update dependencies & plugins to latest versions. --- pom.xml | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/pom.xml b/pom.xml index c07caedc7..6b962cc55 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.owasp.esapi esapi - 2.5.4.0-SNAPSHOT + 2.5.4.0 jar @@ -132,16 +132,16 @@ UTF-8 1.37 2.0.0-M3 - 2.0.0-M8 + 2.0.0-M9 2.0.9 - 4.8.2 - 4.8.2.0 - 3.2.2 + 4.8.5 + 4.8.5.0 + 3.2.5 1.8 - 2023-11-24 00:00:00 + 2023-12-01 00:00:00 @@ -233,7 +233,7 @@ org.apache.commons commons-collections4 - 4.4 + 4.5.0-M1 org.apache-extras.beanshell @@ -260,7 +260,7 @@ org.slf4j slf4j-api - 2.0.6 + 2.0.13 xml-apis @@ -286,7 +286,7 @@ --> commons-io commons-io - 2.15.1 + 2.16.1 @@ -301,7 +301,7 @@ commons-codec commons-codec - 1.16.0 + 1.17.0 test @@ -418,7 +418,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.6.0 + 3.7.1 org.apache.maven.plugins @@ -446,7 +446,7 @@ org.cyclonedx cyclonedx-maven-plugin - 2.7.10 + 2.8.0 package @@ -494,7 +494,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.13.0 ${project.java.target} ${project.java.target} @@ -528,7 +528,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 @@ -548,7 +548,7 @@ org.codehaus.mojo extra-enforcer-rules - 1.7.0 + 1.8.0 org.codehaus.mojo @@ -564,8 +564,8 @@ - [3.3.9,) - Building ESAPI 2.x now requires Maven 3.3.9 or later. + [3.6.3,) + Building ESAPI 2.x now requires Maven 3.6.3 or later. @@ -617,7 +617,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.1.0 + 3.2.4 sign-artifacts @@ -630,13 +630,13 @@ org.apache.maven.plugins maven-install-plugin - 3.1.1 + 3.1.2 org.apache.maven.plugins maven-jar-plugin - 3.3.0 + 3.4.1 @@ -650,7 +650,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.2 + 3.6.3 8 none @@ -668,13 +668,13 @@ org.apache.maven.plugins maven-jxr-plugin - 3.3.1 + 3.3.2 org.apache.maven.plugins maven-pmd-plugin - 3.21.2 + 3.22.0 @@ -694,7 +694,7 @@ The skin is referenced in src/site/site.xml. --> org.apache.maven.plugins maven-site-plugin - 4.0.0-M12 + 4.0.0-M14 org.apache.maven.skins @@ -707,7 +707,7 @@ org.apache.maven.plugins maven-source-plugin - 3.3.0 + 3.3.1 attach-sources @@ -755,7 +755,7 @@ org.owasp dependency-check-maven - 9.0.6 + 9.2.0 ${env.NVD_API_KEY} 1.0 From 8e69d0e1434918abadb4825fa7afc0cf0287babd Mon Sep 17 00:00:00 2001 From: kwwall Date: Tue, 28 May 2024 22:10:34 -0400 Subject: [PATCH 116/197] New release notes for ESAPI 2.5.4.0. --- .../esapi4java-core-2.5.4.0-release-notes.txt | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 documentation/esapi4java-core-2.5.4.0-release-notes.txt diff --git a/documentation/esapi4java-core-2.5.4.0-release-notes.txt b/documentation/esapi4java-core-2.5.4.0-release-notes.txt new file mode 100644 index 000000000..351729e64 --- /dev/null +++ b/documentation/esapi4java-core-2.5.4.0-release-notes.txt @@ -0,0 +1,205 @@ +Release notes for ESAPI 2.5.4.0 + Release date: 2024-05-28 + Project leaders: + -Kevin W. Wall + -Matt Seil + +Previous release: ESAPI 2.5.3.1, 2023-12-01 + + +Executive Summary: Important Things to Note for this Release +------------------------------------------------------------ +This is a patch release with a few bug fixes and dependency updates. While the AntiSamy 1.7.5 update was intended to address an XSS vulnerability (CVE-2024-23635), the ESAPI team verified that this vulnerability did not affect the default configuration of ESAPI and its strict AntiSamy policy file, antisamy-esapi.xml. (Our AntiSamy policy file has the 'preserveComments' directive disabled.) + +There is one important issue that was patched (GitHub issue # 839) that has a side-effect. In particular, if you have ESAPI configured to use JUL (i.e., Java Util Logging) as your default logger (i.e., you have ESAPI.Logger set to 'org.owasp.esapi.logging.java.JavaLogFactory', then you MUST delete your 'esapi-java-logging.properties' to set some of the JUL properties. This file was conflicting with the other uses of JUL not used through ESAPI. If you start ESAPI 2.5.4.0 and this file is found as a resource, then a ConfigurationException will be thrown and the exception message will direct you to our GitHub wiki page, https://github.com/ESAPI/esapi-java-legacy/wiki/Configuring-the-JavaLogFactory + +Notes if you are not updating from the immediate previous release. release 2.5.3.1: + * You need to read through the series of release notes FIRST, going in order. + * For example, if you were updating from an older ESAPI release (say, 2.3.0.0), you should go back and FIRST read all the subsequent release notes in turn. For instance, if you are currently on release 2.3.0.0 and upgrading to (say) release 2.x.y.z, you should MINIMALLY read the sections "Changes Requiring Special Attention" in each of the subsequent release notes. So, going from release 2.3.0.0 to 2.x.y.z, you should in turn, read: + + esapi4java-core-2.4.0.0-release-notes.txt + esapi4java-core-2.5.0.0-release-notes.txt + esapi4java-core-2.5.1.0-release-notes.txt + esapi4java-core-2.5.2.0-release-notes.txt + ...etc., up through the current set of release notes... + esapi4java-core-2.x.y.z-release-notes.txt + +in that order. YOU HAVE BEEN WARNED!!! (These release notes are too large to put all this in a given document; very few read them thoroughly as it is.) + +If your SCA tool is reporting any CVE from a direct or transitive dependency in ESAPI, before reporting it as an GitHub issue, please make sure that you review the vulnerability analysis written up in https://github.com/ESAPI/esapi-java-legacy/blob/develop/Vulnerability-Summary.md. Please email us or contact us in our GitHub Discussions page if you have questions about this. See also the SECURITY.md file to report any security issues with ESAPI. + +You are encouraged to review the vulnerability analysis written up in https://github.com/ESAPI/esapi-java-legacy/blob/develop/Vulnerability-Summary.md and email us or contact us in our GitHub Discussions page if you have questions. + + +================================================================================================================= + +Basic ESAPI facts +----------------- + +ESAPI 2.5.3.1 release: + 207 Java source files + 4293 JUnit tests in 131 Java source files (0 failures, 0 errors, 0 tests skipped) + +ESAPI 2.5.4.0 release: + 207 Java source files + 4297 JUnit tests in 131 Java source files (0 failures, 0 errors, 0 tests skipped) + +8 GitHub Issues closed in this release, including those we've decided not to fix (marked 'wontfix' and 'falsepositive'). +(Reference: https://github.com/ESAPI/esapi-java-legacy/issues?q=is%3Aissue+state%3Aclosed+updated%3A%3E%3D2023-12-01) + +Issue # GitHub Issue Title +---------------------------------------------------------------------------------------------- +824 DefaultEncoder / getCanonicalizedURI returns mix encoding for HTML special characters +826 Fix Encoder.getCanonicalizedURI(URI) for the test case of a double-ampersand in the HTML Query +827 HTMLEntityCodec Mysteriously decodes &or +831 java.io.FileNotFoundException Error in Logs When ESAPI.properties and validation.properties are in resources. and the application is up ,features are not working. +832 easpi .properties and validation properties are present but still it is throwing error and the application is failing do you have any solution for this +835 Validator.isValidSafeHTML() is vulnerable as per CVE-2023-4780 +837 Validation does not work with esapi jakarta jar +839 ConcurrentModificationException + + +----------------------------------------------------------------------------- + + Changes Requiring Special Attention + +----------------------------------------------------------------------------- +Important Note affecting ESAPI 2.5.4.0 and later: +* If you are using JUL for ESAPI logging, you will need to delete esapi-java-logging.properties file so it is not found as a resource stream. Failure to do so will result in a ConfigurationException being thrown. For details, see our GitHub wiki page, https://github.com/ESAPI/esapi-java-legacy/wiki/Configuring-the-JavaLogFactory + +Important JDK Support Announcement +* ESAPI 2.3.0.0 was the last Java release to support Java 7. ESAPI 2.4.0 requires using Java 8 or later. See the ESAPI 2.4.0.0 release notes (https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.4.0.0-release-notes.txt) for details as to the reason. + - This means if your project requires Java 7, you must use ESAPI 2.3.0.0 or earlier. + +Important ESAPI Logging Changes + +* Since ESAPI 2.5.0.0, support for logging directly via Log4J 1 has been removed. (This was two years after it haveing first been deprecated.) Thus, you only choice of ESAPI logging are + - java.util.logging (JUL), which as been the default since ESAPI 2.2.1.0. + * Set ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory in your ESAPI.properties file. + - SLF4J (with your choice of supported SLF4J logging implemmentation) + * Set ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory in your ESAPI.properties file. +* Logger configuration notes - If you are migrating from prior to ESAPI 2.2.1.1, you will need to update your ESAPI.properties file as logging-related configuration as per the ESAPI 2.2.1.1 release notes, which may be found at: + https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.2.1.1-release-notes.txt#L39-L78 + +If you use ESAPI 2.5.0.0 or later, you will get an ClassNotFoundException as the root cause if you still have your ESAPI.Logger property set to use Log4J because the org.owasp.esapi.logger.log4j.Log4JFactory class has been completely removed from the ESAPI jar. If you are dead set on continuing to use Log4J 1, you ought to be able to do so via SLF4J. The set up for Log4J 1 (which has not be tested), should be similar to configure ESAPI to use SLF4J with Log4J 2 as described here: + https://github.com/ESAPI/esapi-java-legacy/wiki/Using-ESAPI-with-SLF4J#slf4j-using-log4j-2x + +----------------------------------------------------------------------------- + + Remaining Known Issues / Problems + +----------------------------------------------------------------------------- +None known, other than the remaining open issues on GitHub. + +----------------------------------------------------------------------------- + + Other changes in this release, some of which not tracked via GitHub issues + +----------------------------------------------------------------------------- + +* Minor updates to README.md file with respect to version information. + +----------------------------------------------------------------------------- + +Developer Activity Report (Changes between release 2.5.3.1 and 2.5.4.0, i.e., between 2023-12-01 and 2024-05-28) +Generated manually (this time) -- all errors are the fault of kwwall and his inability to do simple arithmetic. + +Developer Total Total Number # Merged +(GitHub ID) commits of Files Changed PRs +======================================================== +xeno6696 5 4 1 +jeremiahjstacey 2 4 1 +dependabot 1 1 1 +mpreziuso 1 2 1 +kwwall 6 6 0 (direct merge) +======================================================== + Total PRs: 4 + +----------------------------------------------------------------------------- + +CHANGELOG: Create your own. May I suggest: + + git log --stat --since=2023-12-01 --reverse --pretty=medium + + which will show all the commits since just after the previous (2.5.3.1) release. + + Alternately, you can download the most recent ESAPI source and run + + mvn site + + which will create a CHANGELOG file named 'target/site/changelog.html' + + +----------------------------------------------------------------------------- + +Direct and Transitive Runtime and Test Dependencies: + + $ mvn -B dependency:tree + ... + [INFO] --- maven-dependency-plugin:3.6.1:tree (default-cli) @ esapi --- + [INFO] org.owasp.esapi:esapi:jar:2.5.4.0 + [INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided + [INFO] +- javax.servlet.jsp:javax.servlet.jsp-api:jar:2.3.3:provided + [INFO] +- xom:xom:jar:1.3.9:compile + [INFO] +- commons-beanutils:commons-beanutils:jar:1.9.4:compile + [INFO] | +- commons-logging:commons-logging:jar:1.2:compile + [INFO] | \- commons-collections:commons-collections:jar:3.2.2:compile + [INFO] +- commons-configuration:commons-configuration:jar:1.10:compile + [INFO] +- commons-lang:commons-lang:jar:2.6:compile + [INFO] +- commons-fileupload:commons-fileupload:jar:1.5:compile + [INFO] +- org.apache.commons:commons-collections4:jar:4.5.0-M1:compile + [INFO] +- org.apache-extras.beanshell:bsh:jar:2.0b6:compile + [INFO] +- org.owasp.antisamy:antisamy:jar:1.7.5:compile + [INFO] | +- org.apache.httpcomponents.client5:httpclient5:jar:5.3.1:compile + [INFO] | | \- org.apache.httpcomponents.core5:httpcore5-h2:jar:5.2.4:compile + [INFO] | +- org.apache.httpcomponents.core5:httpcore5:jar:5.2.4:compile + [INFO] | +- org.apache.xmlgraphics:batik-css:jar:1.17:compile + [INFO] | | +- org.apache.xmlgraphics:batik-shared-resources:jar:1.17:compile + [INFO] | | +- org.apache.xmlgraphics:batik-util:jar:1.17:compile + [INFO] | | | +- org.apache.xmlgraphics:batik-constants:jar:1.17:compile + [INFO] | | | \- org.apache.xmlgraphics:batik-i18n:jar:1.17:compile + [INFO] | | \- org.apache.xmlgraphics:xmlgraphics-commons:jar:2.9:compile + [INFO] | +- org.htmlunit:neko-htmlunit:jar:3.11.1:compile + [INFO] | +- xerces:xercesImpl:jar:2.12.2:compile + [INFO] | \- xml-apis:xml-apis-ext:jar:1.3.04:compile + [INFO] +- org.slf4j:slf4j-api:jar:2.0.13:compile + [INFO] +- xml-apis:xml-apis:jar:1.4.01:compile + [INFO] +- commons-io:commons-io:jar:2.16.1:compile + [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.8.5:compile + [INFO] | \- com.google.code.findbugs:jsr305:jar:3.0.2:compile + [INFO] +- commons-codec:commons-codec:jar:1.17.0:test + [INFO] +- junit:junit:jar:4.13.2:test + [INFO] +- org.bouncycastle:bcprov-jdk15on:jar:1.70:test + [INFO] +- org.hamcrest:hamcrest-core:jar:2.2:test + [INFO] | \- org.hamcrest:hamcrest:jar:2.2:test + [INFO] +- org.powermock:powermock-api-mockito2:jar:2.0.9:test + [INFO] | \- org.powermock:powermock-api-support:jar:2.0.9:test + [INFO] +- org.mockito:mockito-core:jar:3.12.4:test + [INFO] | +- net.bytebuddy:byte-buddy:jar:1.11.13:test + [INFO] | +- net.bytebuddy:byte-buddy-agent:jar:1.11.13:test + [INFO] | \- org.objenesis:objenesis:jar:3.2:test + [INFO] +- org.powermock:powermock-core:jar:2.0.9:test + [INFO] | \- org.javassist:javassist:jar:3.27.0-GA:test + [INFO] +- org.powermock:powermock-module-junit4:jar:2.0.9:test + [INFO] | \- org.powermock:powermock-module-junit4-common:jar:2.0.9:test + [INFO] +- org.powermock:powermock-reflect:jar:2.0.9:test + [INFO] \- org.openjdk.jmh:jmh-core:jar:1.37:test + [INFO] +- net.sf.jopt-simple:jopt-simple:jar:5.0.4:test + [INFO] \- org.apache.commons:commons-math3:jar:3.6.1:test + [INFO] ------------------------------------------------------------------------ + [INFO] BUILD SUCCESS + [INFO] ------------------------------------------------------------------------ + [INFO] Total time: 2.133 s + [INFO] Finished at: 2024-05-28T21:48:33-04:00 + [INFO] ------------------------------------------------------------------------ + +----------------------------------------------------------------------------- + +Acknowledgments: + A special hat tip to Arshan Dabirsiaghis, original creator of AntiSamy and the creator of the antisamy-esapi.xml file, the ultrastrict AntiSamy policy used by ESAPI. That avoided a vulnerability that affected AntiSamy itself, so kudos to that foresite. + A shutout to Michele Preziuso for the PR that updated AntiSamy, added a test, and avoided the convergence issue that resulted in me having to reject the Snyk and Dependabot PRs. I appreciate you saving me having to do the work. + And special kudos to Jerry Devis for one of the best bug reports (GitHub issue #839) that I've seen since I began working on ESAPI in 2009. I hope your bug report can be an example to all. Excellent work. + + Lastly, our usual special thanks to the ESAPI community from the ESAPI project co-leaders: + Kevin W. Wall (kwwall) <== The irresponsible party for these release notes! +Matt Seil (xeno6696) From 56fca47028ac60fcb8c30b05613827b6e0ad6983 Mon Sep 17 00:00:00 2001 From: kwwall Date: Tue, 28 May 2024 22:11:27 -0400 Subject: [PATCH 117/197] Env variable file from which the release notes were constructed. --- scripts/vars.2.5.4.0 | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 scripts/vars.2.5.4.0 diff --git a/scripts/vars.2.5.4.0 b/scripts/vars.2.5.4.0 new file mode 100644 index 000000000..0422a674c --- /dev/null +++ b/scripts/vars.2.5.4.0 @@ -0,0 +1,14 @@ +# Do NOT edit this file directly. It will be created by the new createVarsFile.sh script, +# which should be run prior to the newReleaseNotes.sh script. + +# ESAPI (new / current) version +VERSION=2.5.4.0 + +# Previous ESAPI version +PREV_VERSION=2.5.3.1 + +# Release date of current version in yyyy-mm-dd format +YYYY_MM_DD_RELEASE_DATE=2024-05-28 + +# Previous ESAPI release date in same format +PREV_RELEASE_DATE=2023-12-01 From b6d8ef3e3281b043245e44c664607198aa4b8fc0 Mon Sep 17 00:00:00 2001 From: kwwall Date: Wed, 29 May 2024 18:13:12 -0400 Subject: [PATCH 118/197] Back off commons-io version to 2.15.1 because of convergence issue with AntiSamy 1.7.5. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6b962cc55..49131449d 100644 --- a/pom.xml +++ b/pom.xml @@ -286,7 +286,7 @@ --> commons-io commons-io - 2.16.1 + 2.15.1 From a859fe5f5cb581a472d90508ae1a95e21ec41aa8 Mon Sep 17 00:00:00 2001 From: kwwall Date: Wed, 29 May 2024 18:15:04 -0400 Subject: [PATCH 119/197] Update 'Important Note' paragraph in section 3.1.15. --- documentation/ESAPI-release-steps.odt | Bin 314135 -> 314246 bytes documentation/ESAPI-release-steps.pdf | Bin 381480 -> 381689 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/documentation/ESAPI-release-steps.odt b/documentation/ESAPI-release-steps.odt index 38a23f4770b92c8a5f2399649e2c55554adfe9f1..4bcf16361eab8aeecc2573a408ce7ee8f6634446 100644 GIT binary patch delta 77008 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 PbCvB?1b%P;zcTKan&R&MeS^0jb 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 UpML)FgaP&n1qKE+0Qs5we~BaOL;wH) diff --git a/documentation/ESAPI-release-steps.pdf b/documentation/ESAPI-release-steps.pdf index 7832d2cc2fe4e81186d751939ff531f06c1091d3..239dba3782975e132733df4c8b2498f8a7ba9a2c 100644 GIT binary patch delta 25485 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 To@>QN+bxNR&zfasV=n%G1@9oN From df8f05c82c882cc4b36a75d1db89a2c41f84c5de Mon Sep 17 00:00:00 2001 From: kwwall Date: Wed, 29 May 2024 18:36:24 -0400 Subject: [PATCH 120/197] Reset release date to 5/29/2024. --- scripts/vars.2.5.4.0 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/vars.2.5.4.0 b/scripts/vars.2.5.4.0 index 0422a674c..a5423489c 100644 --- a/scripts/vars.2.5.4.0 +++ b/scripts/vars.2.5.4.0 @@ -8,7 +8,7 @@ VERSION=2.5.4.0 PREV_VERSION=2.5.3.1 # Release date of current version in yyyy-mm-dd format -YYYY_MM_DD_RELEASE_DATE=2024-05-28 +YYYY_MM_DD_RELEASE_DATE=2024-05-29 # Previous ESAPI release date in same format PREV_RELEASE_DATE=2023-12-01 From 8c0e5e0ffe0e12326cda2896b149e2a0179e3378 Mon Sep 17 00:00:00 2001 From: kwwall Date: Wed, 29 May 2024 18:37:15 -0400 Subject: [PATCH 121/197] Fix release date, commons-io version #, commit table. --- .../esapi4java-core-2.5.4.0-release-notes.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/documentation/esapi4java-core-2.5.4.0-release-notes.txt b/documentation/esapi4java-core-2.5.4.0-release-notes.txt index 351729e64..665c1d280 100644 --- a/documentation/esapi4java-core-2.5.4.0-release-notes.txt +++ b/documentation/esapi4java-core-2.5.4.0-release-notes.txt @@ -1,5 +1,5 @@ Release notes for ESAPI 2.5.4.0 - Release date: 2024-05-28 + Release date: 2024-05-29 Project leaders: -Kevin W. Wall -Matt Seil @@ -101,7 +101,7 @@ None known, other than the remaining open issues on GitHub. ----------------------------------------------------------------------------- -Developer Activity Report (Changes between release 2.5.3.1 and 2.5.4.0, i.e., between 2023-12-01 and 2024-05-28) +Developer Activity Report (Changes between release 2.5.3.1 and 2.5.4.0, i.e., between 2023-12-01 and 2024-05-29) Generated manually (this time) -- all errors are the fault of kwwall and his inability to do simple arithmetic. Developer Total Total Number # Merged @@ -111,7 +111,7 @@ xeno6696 5 4 1 jeremiahjstacey 2 4 1 dependabot 1 1 1 mpreziuso 1 2 1 -kwwall 6 6 0 (direct merge) +kwwall 11 6 0 (direct merge) ======================================================== Total PRs: 4 @@ -164,7 +164,7 @@ Direct and Transitive Runtime and Test Dependencies: [INFO] | \- xml-apis:xml-apis-ext:jar:1.3.04:compile [INFO] +- org.slf4j:slf4j-api:jar:2.0.13:compile [INFO] +- xml-apis:xml-apis:jar:1.4.01:compile - [INFO] +- commons-io:commons-io:jar:2.16.1:compile + [INFO] +- commons-io:commons-io:jar:2.15.1:compile [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.8.5:compile [INFO] | \- com.google.code.findbugs:jsr305:jar:3.0.2:compile [INFO] +- commons-codec:commons-codec:jar:1.17.0:test @@ -189,8 +189,8 @@ Direct and Transitive Runtime and Test Dependencies: [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ - [INFO] Total time: 2.133 s - [INFO] Finished at: 2024-05-28T21:48:33-04:00 + [INFO] Total time: 0.903 s + [INFO] Finished at: 2024-05-29T18:31:30-04:00 [INFO] ------------------------------------------------------------------------ ----------------------------------------------------------------------------- From 838c4736d969942c3811cc21433087316971a7fc Mon Sep 17 00:00:00 2001 From: kwwall Date: Wed, 29 May 2024 23:14:07 -0400 Subject: [PATCH 122/197] Modifying pom.xml for next planned release. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 49131449d..37187903d 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.owasp.esapi esapi - 2.5.4.0 + 2.5.5.0-SNAPSHOT jar From d06d95755df254bfc86e67392ac5fbfe07931554 Mon Sep 17 00:00:00 2001 From: kwwall Date: Thu, 30 May 2024 18:46:19 -0400 Subject: [PATCH 123/197] Rewrote 1st paragraph to note ESAPI DOES support Jakarta EE. --- README.md | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 71a0f1f98..4c4468441 100644 --- a/README.md +++ b/README.md @@ -14,18 +14,37 @@ OWASP® ESAPI (The OWASP Enterprise Security API) is a free, open source, web ap

    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

    -# Special note regarding Spring Boot 3, Spring 6, Tomcat 10 and other applications / libraries requiring Jakarta EE - - - - -
    -IMPORTANT: We are aware that all versions of ESAPI (unless you are using very select parts) do not work with Jakarta EE. Jakarta EE relies on jakarta.servlet-api. ESAPI is built to use javax.servlet-api. This causes things like Spring Boot 3, Spring 6, Tomcat 10, the latest version of Jetty, etc. to fail to load certain (well, many) ESAPI classes. The reason for this is that the package names between these 2 libraryes are different! The dependency javax.servlet-api has a package namespace of javax.servlet. The jakarta.servlet-api library is using the package namespace of jakarta.servlet. So references to things like ServletRequest, ServletResponse, etc. in ESAPI are using javax.servlet.ServletRequest and javax.servlet.ServletResponse respectively. We cannot make it work for both at once and we will not stop supporting javax.servlet-api, which is what most of our existing ESAPI clients are using. -

    -Therefore PLEASE STOP sending us emails and/or creating GitHub issues regarding this! Instead, please -read ongoing the GitHub discussion https://github.com/ESAPI/esapi-java-legacy/discussions/768 for further details. -

    -
    +# Jakarta EE Support +**IMPORTANT:** +ESAPI has supported the Jakarta Servlet API (i.e., **jakarta.servlet.api**) since release +2.5.3.0. (Unfortunately, we were just forgot to note that in this **README** file. Duh!) + +Therefore, for release 2.5.3.0 and later versions of ESAPI, ESAPI ought to be able to support Spring Boot 3, Spring 6, Tomcat 10, +and other applications or libraries requiring Jarkata EE. (If you find a case where it does +not, please file a GitHub issue for it.) + +The ESAPI jar file supporting Jakarta will be named esapi-_version_-jakarta.jar. To use that +specific Jakarta version of ESAPI, in Maven, you would specify your ESAPI dependency in your +**pom.xml** as: +```xml + + org.owasp.esapi + esapi + 2.5.3.0-SNAPSHOT + jakarta + +``` +(or any other version later than 2.5.3.0). Thanks to Jonathon Putney for creating a PR to +fix this. There is a long discussion in GitHub Discussion [#768](https://github.com/ESAPI/esapi-java-legacy/discussions/768) +where this was first announced, for those of you have insomnia or really long attention +spans and are interested in the approaches that were tried. + +Of course, ESAPI also still continues to support the older Java EE Servlet API (i.e., **javax.servlet** namespace) as well. In +fact, without the +```xml +jakarta +``` +that's the version that will be used by default. # A word about ESAPI vulnerabilities A summary of all the vulnerabilities that we have written about in either the From f05876c0be84c6d4c358f36fa7874b4dc7e37957 Mon Sep 17 00:00:00 2001 From: kwwall Date: Thu, 30 May 2024 19:03:07 -0400 Subject: [PATCH 124/197] Add bullet about deleting JUL config file if using JUL for logging. Change latest release to 2.5.4.0. --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c4468441..ac6dda95e 100644 --- a/README.md +++ b/README.md @@ -96,9 +96,15 @@ link to the specific release notes. (at least the beginning portion) for some important notes that likely will affect your use of ESAPI! You have been warned!!! * ESAPI 2.3.0.0 is the last release to support Java 7 as the minimal JDK. Starting with release 2.4.0.0, Java 8 or later is required. +* Starting with ESAPI 2.5.4.0, if you were using ESAPI's default logger, JUL + (i.e., you had the property **ESAPI.Logger** set to "org.owasp.esapi.logging.java.JavaLogFactory"), + then you must remove (or rename) the old ESAPI configuration file **esapi-java-logger.properties**. + Failure to do so will cause ESAPI to throw a `ConfigurationException`, thereby + preventing your application from starting. For important additional details, please see + the ESAPI GitHub Discussion https://github.com/ESAPI/esapi-java-legacy/discussions/841. # Locating ESAPI Jar files -The [latest ESAPI release](https://github.com/ESAPI/esapi-java-legacy/releases/latest) is 2.5.3.1. +The [latest ESAPI release](https://github.com/ESAPI/esapi-java-legacy/releases/latest) is 2.5.4.0. All the *regular* ESAPI jars, with the exception of the ESAPI configuration jar (i.e., esapi-2.#.#.#-configuration.jar) and its associated detached GPG signature, are available from Maven Central. The ESAPI configuration From 036b83a6b336899a66bfa524f6db712d820aab29 Mon Sep 17 00:00:00 2001 From: kwwall Date: Thu, 30 May 2024 19:18:40 -0400 Subject: [PATCH 125/197] Added lead-in paragraph and updated 'Supported Versions' table. --- SECURITY.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 455c21fc6..df4e09bfa 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,11 +1,19 @@ # Security Policy +In general, because the ESAPI core development is so small (3 people, all +working full time jobs), we can only support the latest version of ESAPI. +If you are locked in to some previous version and are unable to upgrade +to the latest version, perhaps one or more of us might consider back-porting +a patch (especially if it is the only way to address an ESAPI vulnerability), +but if it is anything but trivial, we would charge a TBD consulting fee. + ## Supported Versions + | Version | Supported | | ------- | ------------------ | -| 2.5.1.0 (latest) | :white_check_mark: | -| 2.1.0.1-2.5.0.0 | :x:, upgrade to latest release | +| 2.5.4.0 (latest) | :white_check_mark: | +| 2.1.0.1-2.5.3.1 | :x:, upgrade to latest release | | <= 1.4.x | :x:, no longer supported AT ALL | ## Reporting a Vulnerability From cb3839f24c8117ae5d6b63a40a68a3b88606f89a Mon Sep 17 00:00:00 2001 From: kwwall Date: Thu, 30 May 2024 20:07:06 -0400 Subject: [PATCH 126/197] Suppress 2 CVEs that appear to be false positives: CVE-2024-29131 & CVE-2024-29133 --- suppressions.xml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/suppressions.xml b/suppressions.xml index 876c4fa6e..3c09dc8ff 100644 --- a/suppressions.xml +++ b/suppressions.xml @@ -45,5 +45,20 @@ ]]> CVE-2017-10355 - + + + 2b36e4adfb66d966c5aef2d73deb6be716389dc9 + CVE-2024-29131 + + + + 2b36e4adfb66d966c5aef2d73deb6be716389dc9 + CVE-2024-29133 + From b610633ec17b0e70520d0a3d8b5462a1bee8f01e Mon Sep 17 00:00:00 2001 From: "Kevin W. Wall" Date: Sun, 14 Jul 2024 16:36:45 -0400 Subject: [PATCH 127/197] Pom updates to address issue #847 (#848) * Close GitHub issue #847. 1. Update pom to latest version of compatible dependencies and plugins. 2. Remove commons-io:commons-io:2.15.1 previously needed for convergence as Commons FileUpload no longer requires it and AntiSamy 1.7.5 now uses 2.15.1. So we no longer need to explicitly load it for convergence to succeed. * Minor documentation tweaks to esapi.tld. --- pom.xml | 55 ++++++++++----------------- src/main/resources/META-INF/esapi.tld | 6 ++- 2 files changed, 24 insertions(+), 37 deletions(-) diff --git a/pom.xml b/pom.xml index 37187903d..661519330 100644 --- a/pom.xml +++ b/pom.xml @@ -134,9 +134,9 @@ 2.0.0-M3 2.0.0-M9 2.0.9 - 4.8.5 - 4.8.5.0 - 3.2.5 + 4.8.6 + 4.8.6.2 + 3.3.0 1.8 @@ -233,7 +233,7 @@ org.apache.commons commons-collections4 - 4.5.0-M1 + 4.5.0-M2 org.apache-extras.beanshell @@ -243,7 +243,7 @@ org.owasp.antisamy antisamy - 1.7.5 + 1.7.6 @@ -274,21 +274,6 @@ 1.4.01 - - - - commons-io - commons-io - 2.15.1 - - com.github.spotbugs @@ -423,17 +408,17 @@ org.apache.maven.plugins maven-dependency-plugin - 3.6.1 + 3.7.1 org.apache.maven.plugins maven-release-plugin - 3.0.1 + 3.1.0 org.codehaus.mojo versions-maven-plugin - 2.16.2 + 2.17.0 file:${project.basedir}/versionRuleset.xml @@ -488,7 +473,7 @@ org.apache.maven.plugins maven-clean-plugin - 3.3.2 + 3.4.0 @@ -543,7 +528,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.4.1 + 3.5.0 org.codehaus.mojo @@ -553,7 +538,7 @@ org.codehaus.mojo animal-sniffer-enforcer-rule - 1.23 + 1.24 @@ -636,7 +621,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.4.1 + 3.4.2 @@ -648,9 +633,9 @@ - org.apache.maven.plugins - maven-javadoc-plugin - 3.6.3 + org.apache.maven.plugins + maven-javadoc-plugin + 3.7.0 8 none @@ -668,19 +653,19 @@ org.apache.maven.plugins maven-jxr-plugin - 3.3.2 + 3.4.0 org.apache.maven.plugins maven-pmd-plugin - 3.22.0 + 3.23.0 org.apache.maven.plugins maven-project-info-reports-plugin - 3.5.0 + 3.6.1 @@ -694,7 +679,7 @@ The skin is referenced in src/site/site.xml. --> org.apache.maven.plugins maven-site-plugin - 4.0.0-M14 + 4.0.0-M15 org.apache.maven.skins @@ -755,7 +740,7 @@ org.owasp dependency-check-maven - 9.2.0 + 10.0.2 ${env.NVD_API_KEY} 1.0 diff --git a/src/main/resources/META-INF/esapi.tld b/src/main/resources/META-INF/esapi.tld index 596acb9c8..1a730f420 100644 --- a/src/main/resources/META-INF/esapi.tld +++ b/src/main/resources/META-INF/esapi.tld @@ -7,7 +7,7 @@ ~ Enterprise Security API (ESAPI) project. For details, please see ~
    http://www.owasp.org/index.php/ESAPI. ~ - ~ Copyright (c) 2007 - The OWASP Foundation + ~ Copyright (c) 2007-2024 - 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. @@ -22,7 +22,7 @@ xsi:schemaLocation=" http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" - version="2.0"> + version="2.x"> OWASP Enterprise Security API (ESAPI) provides a JSP Tag Library that supplies easy access to @@ -30,6 +30,8 @@ functions. These can be used to properly escape user supplied data at display time so that it cannot be used in injection attacks like Cross Site Scripting (XSS). + This tag library applies to all of ESAPI 2.x versions. Its + interface hasn't changed since 2.0. OWASP ESAPI 2.0 From 3a78d6d110c67eb06b85bc47e5ef77fc79775161 Mon Sep 17 00:00:00 2001 From: mickeyz07 <32490762+mickeyz07@users.noreply.github.com> Date: Fri, 6 Sep 2024 00:13:58 +0100 Subject: [PATCH 128/197] Update the logging properties to opt-out of the prefix events #844 (#845) * Update the logging properties to opt-out of the prefix events #844 * Update the logging properties to opt-out of the prefix events, second iteration for #844 * Update the logging properties to opt-out of the prefix events, third iteration * Update the logging properties to opt-out of the prefix events #844 fourt iteration * Update the logging properties to opt-out of the prefix events #844 fifth iteration * Update the logging properties to opt-out of the prefix events #844 sixt iteration * Update the logging properties to opt-out of the prefix events #844 seventh iteration * Update the logging properties to opt-out of the prefix events ESAPI#844 eigth iteration * Update the logging properties to opt-out of the prefix events ESAPI#844 ninth iteration --- configuration/esapi/ESAPI.properties | 4 + src/main/java/org/owasp/esapi/PropNames.java | 1 + .../appender/EventTypeLogSupplier.java | 14 ++- .../logging/appender/LogPrefixAppender.java | 38 ++++-- .../logging/appender/ServerInfoSupplier.java | 22 +++- .../esapi/logging/java/JavaLogFactory.java | 27 +++- .../esapi/logging/slf4j/Slf4JLogFactory.java | 27 +++- .../DefaultSecurityConfiguration.java | 6 +- ...entTypeLogSupplierIgnoreEventTypeTest.java | 45 +++++++ .../appender/LogPrefixAppenderTest.java | 54 +++++++- .../ServerInfoSupplierIgnoreLogNameTest.java | 116 ++++++++++++++++++ src/test/resources/esapi/ESAPI.properties | 4 + 12 files changed, 337 insertions(+), 21 deletions(-) create mode 100644 src/test/java/org/owasp/esapi/logging/appender/EventTypeLogSupplierIgnoreEventTypeTest.java create mode 100644 src/test/java/org/owasp/esapi/logging/appender/ServerInfoSupplierIgnoreLogNameTest.java diff --git a/configuration/esapi/ESAPI.properties b/configuration/esapi/ESAPI.properties index d489cdce8..b5b6aacc6 100644 --- a/configuration/esapi/ESAPI.properties +++ b/configuration/esapi/ESAPI.properties @@ -407,6 +407,10 @@ Logger.UserInfo=true # Determines whether ESAPI should log the session id and client IP. Logger.ClientInfo=true +# Determines whether ESAPI should log the prefix of [EVENT_TYPE - APPLICATION NAME]. +# If all above Logger entries are set to false, as well as LogPrefix, then the output would be the same as if no ESAPI was used +Logger.LogPrefix=true + #=========================================================================== # ESAPI Intrusion Detection # diff --git a/src/main/java/org/owasp/esapi/PropNames.java b/src/main/java/org/owasp/esapi/PropNames.java index 2f3f8ee49..ab30e47fa 100644 --- a/src/main/java/org/owasp/esapi/PropNames.java +++ b/src/main/java/org/owasp/esapi/PropNames.java @@ -111,6 +111,7 @@ public final class PropNames { public static final String LOG_ENCODING_REQUIRED = "Logger.LogEncodingRequired"; public static final String LOG_APPLICATION_NAME = "Logger.LogApplicationName"; public static final String LOG_SERVER_IP = "Logger.LogServerIP"; + public static final String LOG_PREFIX = "Logger.LogPrefix"; public static final String VALIDATION_PROPERTIES = "Validator.ConfigurationFile"; public static final String VALIDATION_PROPERTIES_MULTIVALUED = "Validator.ConfigurationFile.MultiValued"; diff --git a/src/main/java/org/owasp/esapi/logging/appender/EventTypeLogSupplier.java b/src/main/java/org/owasp/esapi/logging/appender/EventTypeLogSupplier.java index 681839af5..93d3bd416 100644 --- a/src/main/java/org/owasp/esapi/logging/appender/EventTypeLogSupplier.java +++ b/src/main/java/org/owasp/esapi/logging/appender/EventTypeLogSupplier.java @@ -30,18 +30,24 @@ public class EventTypeLogSupplier // implements Supplier { /** EventType reference to supply log representation of. */ private final EventType eventType; + /** Whether to log or not the event type */ + private boolean logEventType = true; /** * Ctr * - * @param evtyp EventType reference to supply log representation for + * @param eventType EventType reference to supply log representation for */ - public EventTypeLogSupplier(EventType evtyp) { - this.eventType = evtyp == null ? Logger.EVENT_UNSPECIFIED : evtyp; + public EventTypeLogSupplier(EventType eventType) { + this.eventType = eventType == null ? Logger.EVENT_UNSPECIFIED : eventType; } // @Override -- Uncomment when we switch to Java 8 as minimal baseline. public String get() { - return eventType.toString(); + return logEventType ? eventType.toString() : ""; + } + + public void setLogEventType(boolean logEventType) { + this.logEventType = logEventType; } } diff --git a/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java b/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java index 20f692ebf..57cddfa26 100644 --- a/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java +++ b/src/main/java/org/owasp/esapi/logging/appender/LogPrefixAppender.java @@ -35,27 +35,47 @@ public class LogPrefixAppender implements LogAppender { private final boolean logApplicationName; /** Application Name to record. */ private final String appName; + /** Whether or not to print the prefix. */ + private final boolean logPrefix; /** - * Ctr. + * Constructor * * @param logUserInfo Whether or not to record user information * @param logClientInfo Whether or not to record client information * @param logServerIp Whether or not to record server ip information * @param logApplicationName Whether or not to record application name * @param appName Application Name to record. + * @param logPrefix is set by default to true */ + @SuppressWarnings("JavadocReference") public LogPrefixAppender(boolean logUserInfo, boolean logClientInfo, boolean logServerIp, boolean logApplicationName, String appName) { + this(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName, true); + } + + /** + * Constructor + * + * @param logUserInfo Whether or not to record user information + * @param logClientInfo Whether or not to record client information + * @param logServerIp Whether or not to record server ip information + * @param logApplicationName Whether or not to record application name + * @param appName Application Name to record. + * @param logPrefix Whether or not to print the prefix + */ + public LogPrefixAppender(boolean logUserInfo, boolean logClientInfo, boolean logServerIp, boolean logApplicationName, String appName, boolean logPrefix) { this.logUserInfo = logUserInfo; this.logClientInfo = logClientInfo; this.logServerIp = logServerIp; this.logApplicationName = logApplicationName; this.appName = appName; + this.logPrefix = logPrefix; } @Override public String appendTo(String logName, EventType eventType, String message) { EventTypeLogSupplier eventTypeSupplier = new EventTypeLogSupplier(eventType); + eventTypeSupplier.setLogEventType(this.logPrefix); UserInfoSupplier userInfoSupplier = new UserInfoSupplier(); userInfoSupplier.setLogUserInfo(logUserInfo); @@ -66,6 +86,7 @@ public String appendTo(String logName, EventType eventType, String message) { ServerInfoSupplier serverInfoSupplier = new ServerInfoSupplier(logName); serverInfoSupplier.setLogServerIp(logServerIp); serverInfoSupplier.setLogApplicationName(logApplicationName, appName); + serverInfoSupplier.setLogLogName(logPrefix); String eventTypeMsg = eventTypeSupplier.get().trim(); String userInfoMsg = userInfoSupplier.get().trim(); @@ -80,17 +101,20 @@ public String appendTo(String logName, EventType eventType, String message) { String[] optionalPrefixContent = new String[] {userInfoMsg + clientInfoMsg, serverInfoMsg}; - StringBuilder logPrefix = new StringBuilder(); - //EventType is always appended - logPrefix.append(eventTypeMsg); + StringBuilder logPrefixBuilder = new StringBuilder(); + //EventType is always appended (unless we specifically asked not to Log Prefix) + if (this.logPrefix) { + logPrefixBuilder.append(eventTypeMsg); + } for (String element : optionalPrefixContent) { if (!element.isEmpty()) { - logPrefix.append(" "); - logPrefix.append(element); + logPrefixBuilder.append(" "); + logPrefixBuilder.append(element); } } - return String.format(RESULT_FORMAT, logPrefix.toString(), message); + String logPrefixContent = logPrefixBuilder.toString(); + return logPrefixContent.trim().isEmpty() ? message : String.format(RESULT_FORMAT, logPrefixContent, message); } } diff --git a/src/main/java/org/owasp/esapi/logging/appender/ServerInfoSupplier.java b/src/main/java/org/owasp/esapi/logging/appender/ServerInfoSupplier.java index 45fb4da55..8d62a58f0 100644 --- a/src/main/java/org/owasp/esapi/logging/appender/ServerInfoSupplier.java +++ b/src/main/java/org/owasp/esapi/logging/appender/ServerInfoSupplier.java @@ -34,7 +34,8 @@ public class ServerInfoSupplier // implements Supplier private boolean logAppName = true; /** The application name to log. */ private String applicationName = ""; - + /** Whether to log the Name */ + private boolean logLogName = true; /** Reference to the associated logname/module name. */ private final String logName; @@ -57,10 +58,14 @@ public String get() { appInfo.append(request.getLocalAddr()).append(":").append(request.getLocalPort()); } } - if (logAppName) { - appInfo.append("/").append(applicationName); + + if (this.logAppName) { + appInfo.append("/").append(this.applicationName); + } + + if (this.logLogName) { + appInfo.append("/").append(logName); } - appInfo.append("/").append(logName); return appInfo.toString(); } @@ -74,6 +79,15 @@ public void setLogServerIp(boolean log) { this.logServerIP = log; } + /** + * Specify whether the instance should record the prefix. + * + * @param logLogName {@code true} to record + */ + public void setLogLogName(boolean logLogName) { + this.logLogName = logLogName; + } + /** * Specify whether the instance should record the application name * diff --git a/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java b/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java index 9ebd52d92..8cca8fb25 100644 --- a/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java +++ b/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java @@ -20,6 +20,7 @@ import static org.owasp.esapi.PropNames.LOG_ENCODING_REQUIRED; import static org.owasp.esapi.PropNames.LOG_SERVER_IP; import static org.owasp.esapi.PropNames.LOG_USER_INFO; +import static org.owasp.esapi.PropNames.LOG_PREFIX; import java.io.IOException; import java.io.InputStream; @@ -79,7 +80,17 @@ public class JavaLogFactory implements LogFactory { boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(LOG_APPLICATION_NAME); String appName = ESAPI.securityConfiguration().getStringProp(APPLICATION_NAME); boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(LOG_SERVER_IP); - JAVA_LOG_APPENDER = createLogAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); + + boolean logPrefix = true; + try { + logPrefix = ESAPI.securityConfiguration().getBooleanProp(LOG_PREFIX); + } catch (ConfigurationException ex) { + System.out.println("ESAPI: Failed to read Log Prefix configuration " + LOG_PREFIX + ". Defaulting to enabled" + + ". Caught " + ex.getClass().getName() + + "; exception message was: " + ex); + } + + JAVA_LOG_APPENDER = createLogAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName, logPrefix); Map levelLookup = new HashMap<>(); levelLookup.put(Logger.ALL, JavaLogLevelHandlers.ALWAYS); @@ -144,6 +155,20 @@ public class JavaLogFactory implements LogFactory { return new LogPrefixAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); } + /** + * Populates the default log appender for use in factory-created loggers. + * @param appName + * @param logApplicationName + * @param logServerIp + * @param logClientInfo + * @param logPrefix + * + * @return LogAppender instance. + */ + /*package*/ static LogAppender createLogAppender(boolean logUserInfo, boolean logClientInfo, boolean logServerIp, boolean logApplicationName, String appName, boolean logPrefix) { + return new LogPrefixAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName, logPrefix); + } + @Override public Logger getLogger(String moduleName) { diff --git a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java index af113b80c..5e1810a93 100644 --- a/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java +++ b/src/main/java/org/owasp/esapi/logging/slf4j/Slf4JLogFactory.java @@ -23,6 +23,7 @@ import org.owasp.esapi.LogFactory; import org.owasp.esapi.Logger; import org.owasp.esapi.codecs.HTMLEntityCodec; +import org.owasp.esapi.errors.ConfigurationException; import org.owasp.esapi.logging.appender.LogAppender; import org.owasp.esapi.logging.appender.LogPrefixAppender; import org.owasp.esapi.logging.cleaning.CodecLogScrubber; @@ -36,6 +37,7 @@ import static org.owasp.esapi.PropNames.LOG_APPLICATION_NAME; import static org.owasp.esapi.PropNames.APPLICATION_NAME; import static org.owasp.esapi.PropNames.LOG_SERVER_IP; +import static org.owasp.esapi.PropNames.LOG_PREFIX; import org.slf4j.LoggerFactory; /** * LogFactory implementation which creates SLF4J supporting Loggers. @@ -69,7 +71,17 @@ public class Slf4JLogFactory implements LogFactory { boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(LOG_APPLICATION_NAME); String appName = ESAPI.securityConfiguration().getStringProp(APPLICATION_NAME); boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(LOG_SERVER_IP); - SLF4J_LOG_APPENDER = createLogAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); + + boolean logPrefix = true; + try { + logPrefix = ESAPI.securityConfiguration().getBooleanProp(LOG_PREFIX); + } catch (ConfigurationException ex) { + System.out.println("ESAPI: Failed to read Log Prefix configuration " + LOG_PREFIX + ". Defaulting to enabled" + + ". Caught " + ex.getClass().getName() + + "; exception message was: " + ex); + } + + SLF4J_LOG_APPENDER = createLogAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName, logPrefix); Map levelLookup = new HashMap<>(); levelLookup.put(Logger.ALL, Slf4JLogLevelHandlers.TRACE); @@ -114,6 +126,19 @@ public class Slf4JLogFactory implements LogFactory { return new LogPrefixAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName); } + /** + * Populates the default log appender for use in factory-created loggers. + * @param appName + * @param logApplicationName + * @param logServerIp + * @param logClientInfo + * @param logPrefix + * + * @return LogAppender instance. + */ + /*package*/ static LogAppender createLogAppender(boolean logUserInfo, boolean logClientInfo, boolean logServerIp, boolean logApplicationName, String appName, boolean logPrefix) { + return new LogPrefixAppender(logUserInfo, logClientInfo, logServerIp, logApplicationName, appName, logPrefix); + } @Override public Logger getLogger(String moduleName) { diff --git a/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java b/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java index 8cba81982..eb561349b 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java @@ -1441,14 +1441,14 @@ public Boolean getBooleanProp(String propertyName) throws ConfigurationException try { return esapiPropertyManager.getBooleanProp(propertyName); } catch (ConfigurationException ex) { - String property = properties.getProperty( propertyName ); + String property = properties.getProperty(propertyName); if ( property == null ) { throw new ConfigurationException( "SecurityConfiguration for " + propertyName + " not found in ESAPI.properties"); } - if ( property.equalsIgnoreCase("true") || property.equalsIgnoreCase("yes" ) ) { + if ( property.equalsIgnoreCase("true") || property.equalsIgnoreCase("yes") ) { return true; } - if ( property.equalsIgnoreCase("false") || property.equalsIgnoreCase( "no" ) ) { + if ( property.equalsIgnoreCase("false") || property.equalsIgnoreCase("no") ) { return false; } throw new ConfigurationException( "SecurityConfiguration for " + propertyName + " has incorrect " + diff --git a/src/test/java/org/owasp/esapi/logging/appender/EventTypeLogSupplierIgnoreEventTypeTest.java b/src/test/java/org/owasp/esapi/logging/appender/EventTypeLogSupplierIgnoreEventTypeTest.java new file mode 100644 index 000000000..3f8858bfa --- /dev/null +++ b/src/test/java/org/owasp/esapi/logging/appender/EventTypeLogSupplierIgnoreEventTypeTest.java @@ -0,0 +1,45 @@ +package org.owasp.esapi.logging.appender; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.owasp.esapi.Logger; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@RunWith(Parameterized.class) +public class EventTypeLogSupplierIgnoreEventTypeTest { + + @Parameterized.Parameters (name="{0} -> {1}") + public static Collection assembleTests() { + List paramSets = new ArrayList<>(); + paramSets.add(new Object[] {Logger.EVENT_FAILURE,""}); + paramSets.add(new Object[] {Logger.EVENT_SUCCESS,""}); + paramSets.add(new Object[] {Logger.EVENT_UNSPECIFIED,""}); + paramSets.add(new Object[] {Logger.SECURITY_AUDIT,""}); + paramSets.add(new Object[] {Logger.SECURITY_FAILURE,""}); + paramSets.add(new Object[] {Logger.SECURITY_SUCCESS,""}); + paramSets.add(new Object[] {null, ""}); + + return paramSets; + } + + private final Logger.EventType eventType; + private final String expectedResult; + + public EventTypeLogSupplierIgnoreEventTypeTest(Logger.EventType eventType, String result) { + this.eventType = eventType; + this.expectedResult = result; + } + + @Test + public void testEventTypeLogIgnoreEventType() { + EventTypeLogSupplier supplier = new EventTypeLogSupplier(eventType); + supplier.setLogEventType(false); + assertEquals(expectedResult, supplier.get()); + } +} diff --git a/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java b/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java index bc733ec2e..cbd368b5e 100644 --- a/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java +++ b/src/test/java/org/owasp/esapi/logging/appender/LogPrefixAppenderTest.java @@ -145,7 +145,6 @@ public void testLogContentWhenUserInfoEmptyAndClientInfoEmptyAndServerInfoEmpty( runTest(ETL_RESULT, EMPTY_RESULT, EMPTY_RESULT, EMPTY_RESULT, "[EVENT_TYPE]"); } - private void runTest(String typeResult, String userResult, String clientResult, String serverResult, String exResult) throws Exception{ when(etlsSpy.get()).thenReturn(typeResult); when(uisSpy.get()).thenReturn(userResult); @@ -163,4 +162,57 @@ private void runTest(String typeResult, String userResult, String clientResult, assertEquals(exResult + " " + testName.getMethodName() + "-MESSAGE", result); } + + @Test + public void testLogContentWhenServerInfoEmptyAndIgnoreLogPrefix() throws Exception { + runTestWithLogPrefixIgnore(ETL_RESULT, UIS_RESULT, CIS_RESULT, EMPTY_RESULT, false, "[ USER_INFO:CLIENT_INFO]"); + } + + @Test + public void testLogContentWhenUserInfoEmptyAndServerInfoEmptyAndIgnoreLogPrefix() throws Exception { + runTestWithLogPrefixIgnore(ETL_RESULT, EMPTY_RESULT, CIS_RESULT, EMPTY_RESULT, false, "[ CLIENT_INFO]"); + } + + @Test + public void testLogContentWhenUserInfoEmptyAndClientInfoEmptyAndIgnoreLogPrefix() throws Exception { + runTestWithLogPrefixIgnore(ETL_RESULT, EMPTY_RESULT, EMPTY_RESULT, SIS_RESULT, false, "[ -> SERVER_INFO]"); + } + + @Test + public void testLogContentWhenClientInfoEmptyAndServerInfoEmptyAndIgnoreLogPrefix() throws Exception { + runTestWithLogPrefixIgnore(ETL_RESULT, UIS_RESULT, EMPTY_RESULT, EMPTY_RESULT, false, "[ USER_INFO]"); + } + + @Test + public void testLogContentWhenUserInfoEmptyAndClientInfoEmptyAndServerInfoEmptyAndIgnoreLogPrefix() throws Exception { + runTestWithLogPrefixIgnore(ETL_RESULT, EMPTY_RESULT, EMPTY_RESULT, EMPTY_RESULT, false, ""); + } + + private void runTestWithLogPrefixIgnore(String typeResult, String userResult, String clientResult, String serverResult, boolean logPrefix, String exResult) throws Exception{ + etlsSpy.setLogEventType(logPrefix); + when(etlsSpy.get()).thenReturn(typeResult); + + when(uisSpy.get()).thenReturn(userResult); + when(cisSpy.get()).thenReturn(clientResult); + + sisSpy.setLogLogName(logPrefix); + when(sisSpy.get()).thenReturn(serverResult); + + whenNew(EventTypeLogSupplier.class).withArguments(testEventType).thenReturn(etlsSpy); + whenNew(UserInfoSupplier.class).withNoArguments().thenReturn(uisSpy); + whenNew(ClientInfoSupplier.class).withNoArguments().thenReturn(cisSpy); + whenNew(ServerInfoSupplier.class).withArguments(testLoggerName).thenReturn(sisSpy); + + //Since everything is mocked these booleans don't much matter aside from the later verifies + LogPrefixAppender lpa = new LogPrefixAppender(false, false, false, false, null, false); + String result = lpa.appendTo(testLoggerName, testEventType, testLogMessage); + + if (exResult.isEmpty()) { + assertEquals( testName.getMethodName() + "-MESSAGE", result); + } + else { + assertEquals(exResult + " " + testName.getMethodName() + "-MESSAGE", result); + } + } + } diff --git a/src/test/java/org/owasp/esapi/logging/appender/ServerInfoSupplierIgnoreLogNameTest.java b/src/test/java/org/owasp/esapi/logging/appender/ServerInfoSupplierIgnoreLogNameTest.java new file mode 100644 index 000000000..5bd3c8335 --- /dev/null +++ b/src/test/java/org/owasp/esapi/logging/appender/ServerInfoSupplierIgnoreLogNameTest.java @@ -0,0 +1,116 @@ +package org.owasp.esapi.logging.appender; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.when; + +import javax.servlet.http.HttpServletRequest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.runner.RunWith; +import org.owasp.esapi.ESAPI; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ ESAPI.class }) +public class ServerInfoSupplierIgnoreLogNameTest { + @Rule + public TestName testName = new TestName(); + + private HttpServletRequest request; + + @Before + public void buildStaticMocks() { + request = mock(HttpServletRequest.class); + mockStatic(ESAPI.class); + } + + @Test + public void verifyFullOutputIgnoreLogName() throws Exception { + when(ESAPI.class, "currentRequest").thenReturn(request); + when(request.getLocalAddr()).thenReturn("LOCAL_ADDR"); + when(request.getLocalPort()).thenReturn(99999); + + ServerInfoSupplier sis = new ServerInfoSupplier(testName.getMethodName()); + sis.setLogApplicationName(true, testName.getMethodName() + "-APPLICATION"); + sis.setLogServerIp(true); + sis.setLogLogName(false); + + String result = sis.get(); + assertEquals("LOCAL_ADDR:99999/" + testName.getMethodName() + "-APPLICATION", + result); + } + + @Test + public void verifyOutputNullRequestIgnoreLogName() throws Exception { + when(ESAPI.class, "currentRequest").thenReturn(null); + ServerInfoSupplier sis = new ServerInfoSupplier(testName.getMethodName()); + sis.setLogApplicationName(true, testName.getMethodName() + "-APPLICATION"); + sis.setLogServerIp(true); + sis.setLogLogName(false); + + String result = sis.get(); + assertEquals("/" + testName.getMethodName() + "-APPLICATION", result); + } + + @Test + public void verifyOutputNoAppNameIgnoreLogName() throws Exception { + when(ESAPI.class, "currentRequest").thenReturn(request); + when(request.getLocalAddr()).thenReturn("LOCAL_ADDR"); + when(request.getLocalPort()).thenReturn(99999); + + ServerInfoSupplier sis = new ServerInfoSupplier(testName.getMethodName()); + sis.setLogApplicationName(false, null); + sis.setLogServerIp(true); + sis.setLogLogName(false); + + String result = sis.get(); + assertEquals("LOCAL_ADDR:99999", result); + } + + @Test + public void verifyOutputNullAppNameIgnoreLogName() throws Exception { + when(ESAPI.class, "currentRequest").thenReturn(request); + when(request.getLocalAddr()).thenReturn("LOCAL_ADDR"); + when(request.getLocalPort()).thenReturn(99999); + + ServerInfoSupplier sis = new ServerInfoSupplier(testName.getMethodName()); + sis.setLogApplicationName(true, null); + sis.setLogServerIp(true); + sis.setLogLogName(false); + + String result = sis.get(); + assertEquals("LOCAL_ADDR:99999/null", result); + } + + @Test + public void verifyOutputNoServerIpIgnoreLogName() { + ServerInfoSupplier sis = new ServerInfoSupplier(testName.getMethodName()); + sis.setLogApplicationName(true, testName.getMethodName() + "-APPLICATION"); + sis.setLogServerIp(false); + sis.setLogLogName(false); + + String result = sis.get(); + assertEquals("/" + testName.getMethodName() + "-APPLICATION", result); + } + + @Test + public void verifyOutputNullRequestNoServerIpNullAppNameIgnoreLogName() throws Exception { + when(ESAPI.class, "currentRequest").thenReturn(null); + ServerInfoSupplier sis = new ServerInfoSupplier(testName.getMethodName()); + sis.setLogApplicationName(false, null); + sis.setLogServerIp(false); + sis.setLogLogName(false); + + String result = sis.get(); + assertEquals("", result); + } + + +} + diff --git a/src/test/resources/esapi/ESAPI.properties b/src/test/resources/esapi/ESAPI.properties index c967bad33..8ffc61f66 100644 --- a/src/test/resources/esapi/ESAPI.properties +++ b/src/test/resources/esapi/ESAPI.properties @@ -439,6 +439,10 @@ Logger.UserInfo=true # Determines whether ESAPI should log the session id and client IP. Logger.ClientInfo=true +# Determines whether ESAPI should log the prefix of [EVENT_TYPE - APPLICATION NAME]. +# If all above Logger entries are set to false, as well as LogPrefix, then the output would be the same as if no ESAPI was used +Logger.LogPrefix=true + #=========================================================================== # ESAPI Intrusion Detection # From cb02efe53cb8ebedb8e0909033008927ce71a511 Mon Sep 17 00:00:00 2001 From: Dario Viva <45972949+DarioViva42@users.noreply.github.com> Date: Sat, 14 Sep 2024 03:16:16 +0200 Subject: [PATCH 129/197] Fix Typos in documentation and comments (#852) * Update README.md rephrase warning message in README.md * EncodingPatternPreservation: fix typo * AbstractCodec: fix typo * AbstractCodec: there is no such thing as a footgun usage * AbstractPushbackSequence: fix typo. see https://languagetool.org/insights/post/regard/ * Base64: fix typo * HashTrie: fix typo * HashTrie: fix typo * HTMLEntityCodec: fix typo * MySQLCodec: fix typo * MySQLCodec: fix typo * PushBackSequenceImpl: fix typo * PushbackString: fix typo * EsapiConfiguration: fix typo * AbstractPrioritizedPropertyLoader: fix typo * AbstractPrioritizedPropertyLoader: fix grammar * CipherText: fix typo * CipherTextSerializer: fix typo * CryptoHelper: fix typo * CryptoHelper: fix typo * CryptoHelper: fix grammar * CryptoToken: fix typo * CryptoToken: fix typo * PlainText: fix typo * RequestRateThrottleFilter: fix typo * SecurityWrapperRequest: fix typo * CompositeLogScrubber: fix typo * JavaLogBridge: fix typo * Authenticator: fix typo * Encoder: fix typo * Encryptor: untangle unclear sentence * ESAPI: fix typo * HTTPUtilities: fix typo * HTTPUtilities: fix typo * Logger: fix typo * Logger: fix typo * SecurityConfiguration: fix typo * StringUtilities: correct javadoc * User: fix typo * Validator: fix typo * Validator: fix typo * CollectionsUtil: fix typo * ObjFactory: fix typo * EncodeForBase64Tag: fix typo * EncodeForCSSTag: fix typo * EncodeForHTMLAttributeTag: fix typo * EncodeForHTMLTag: fix typo * EncodeForJavaScriptTag: fix typo * EncodeForURLTag: fix typo * EncodeForVBScriptTag: fix typo * EncodeForXMLAttributeTag: fix typo * EncodeForXMLTag: fix typo * EncodeForXPathTag: fix typo * AbstractAccessReferenceMap: fix typo * StringUtilities: replaceNull: rephrase javadoc using @code * Encryptor: decrypt: fix typo, use expression from before f5e138c8c15498d82e26c83d1d86a59ac6b8c082 * User: setLastFailedLoginTime: use "authenticate" instead of "log in" --- README.md | 2 +- src/main/java/org/owasp/esapi/Authenticator.java | 2 +- src/main/java/org/owasp/esapi/ESAPI.java | 2 +- src/main/java/org/owasp/esapi/Encoder.java | 2 +- src/main/java/org/owasp/esapi/Encryptor.java | 8 ++++---- src/main/java/org/owasp/esapi/HTTPUtilities.java | 2 +- src/main/java/org/owasp/esapi/Logger.java | 4 ++-- .../java/org/owasp/esapi/SecurityConfiguration.java | 2 +- src/main/java/org/owasp/esapi/StringUtilities.java | 2 +- src/main/java/org/owasp/esapi/User.java | 2 +- src/main/java/org/owasp/esapi/Validator.java | 8 ++++---- .../java/org/owasp/esapi/codecs/AbstractCodec.java | 4 ++-- .../owasp/esapi/codecs/AbstractPushbackSequence.java | 2 +- src/main/java/org/owasp/esapi/codecs/Base64.java | 2 +- .../java/org/owasp/esapi/codecs/HTMLEntityCodec.java | 8 ++++---- src/main/java/org/owasp/esapi/codecs/HashTrie.java | 6 +++--- src/main/java/org/owasp/esapi/codecs/MySQLCodec.java | 4 ++-- .../org/owasp/esapi/codecs/PushBackSequenceImpl.java | 4 ++-- .../java/org/owasp/esapi/codecs/PushbackString.java | 4 ++-- .../esapi/codecs/ref/EncodingPatternPreservation.java | 2 +- .../AbstractPrioritizedPropertyLoader.java | 4 ++-- .../esapi/configuration/consts/EsapiConfiguration.java | 2 +- src/main/java/org/owasp/esapi/crypto/CipherText.java | 2 +- .../org/owasp/esapi/crypto/CipherTextSerializer.java | 6 +++--- src/main/java/org/owasp/esapi/crypto/CryptoHelper.java | 6 +++--- src/main/java/org/owasp/esapi/crypto/CryptoToken.java | 4 ++-- src/main/java/org/owasp/esapi/crypto/PlainText.java | 2 +- .../owasp/esapi/filters/RequestRateThrottleFilter.java | 2 +- .../owasp/esapi/filters/SecurityWrapperRequest.java | 2 +- .../esapi/logging/cleaning/CompositeLogScrubber.java | 2 +- .../org/owasp/esapi/logging/java/JavaLogBridge.java | 2 +- .../esapi/reference/AbstractAccessReferenceMap.java | 10 +++++----- .../java/org/owasp/esapi/tags/EncodeForBase64Tag.java | 2 +- .../java/org/owasp/esapi/tags/EncodeForCSSTag.java | 2 +- .../owasp/esapi/tags/EncodeForHTMLAttributeTag.java | 2 +- .../java/org/owasp/esapi/tags/EncodeForHTMLTag.java | 2 +- .../org/owasp/esapi/tags/EncodeForJavaScriptTag.java | 2 +- .../java/org/owasp/esapi/tags/EncodeForURLTag.java | 2 +- .../org/owasp/esapi/tags/EncodeForVBScriptTag.java | 2 +- .../org/owasp/esapi/tags/EncodeForXMLAttributeTag.java | 2 +- .../java/org/owasp/esapi/tags/EncodeForXMLTag.java | 2 +- .../java/org/owasp/esapi/tags/EncodeForXPathTag.java | 2 +- .../java/org/owasp/esapi/util/CollectionsUtil.java | 10 +++++----- src/main/java/org/owasp/esapi/util/ObjFactory.java | 2 +- 44 files changed, 74 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index ac6dda95e..2956cc916 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ OWASP® ESAPI (The OWASP Enterprise Security API) is a free, open source, web ap # Jakarta EE Support **IMPORTANT:** ESAPI has supported the Jakarta Servlet API (i.e., **jakarta.servlet.api**) since release -2.5.3.0. (Unfortunately, we were just forgot to note that in this **README** file. Duh!) +2.5.3.0. (Unfortunately, this information was previously missing in this **README** file.) Therefore, for release 2.5.3.0 and later versions of ESAPI, ESAPI ought to be able to support Spring Boot 3, Spring 6, Tomcat 10, and other applications or libraries requiring Jarkata EE. (If you find a case where it does diff --git a/src/main/java/org/owasp/esapi/Authenticator.java b/src/main/java/org/owasp/esapi/Authenticator.java index e113b0bdd..4e83903d5 100644 --- a/src/main/java/org/owasp/esapi/Authenticator.java +++ b/src/main/java/org/owasp/esapi/Authenticator.java @@ -148,7 +148,7 @@ public interface Authenticator { *

    * WARNING: The implementation of this method as defined in the * default reference implementation class, {@code FileBasedAuthenticator}, - * uses a password hash algorthim that is known to be weak. You are advised + * uses a password hash algorithm that is known to be weak. You are advised * to replace the default reference implementation class with your own custom * implementation that uses a stronger password hashing algorithm. * See class comments in * {@code FileBasedAuthenticator} for further details. diff --git a/src/main/java/org/owasp/esapi/ESAPI.java b/src/main/java/org/owasp/esapi/ESAPI.java index ef389d020..c42a21ff8 100644 --- a/src/main/java/org/owasp/esapi/ESAPI.java +++ b/src/main/java/org/owasp/esapi/ESAPI.java @@ -93,7 +93,7 @@ public static Authenticator authenticator() { } /** - * The ESAPI Encoder is primarilly used to provide output encoding to + * The ESAPI Encoder is primarily used to provide output encoding to * prevent Cross-Site Scripting (XSS). * @return the current ESAPI Encoder object being used to encode and decode data for this application. */ diff --git a/src/main/java/org/owasp/esapi/Encoder.java b/src/main/java/org/owasp/esapi/Encoder.java index 22ae8f94b..ad4950dc9 100644 --- a/src/main/java/org/owasp/esapi/Encoder.java +++ b/src/main/java/org/owasp/esapi/Encoder.java @@ -519,7 +519,7 @@ public interface Encoder { * * NB: The reference implementation encodes almost everything and may over-encode. * - * The difficulty with XPath encoding is that XPath has no built in mechanism for escaping + * The difficulty with XPath encoding is that XPath has no built-in mechanism for escaping * characters. It is possible to use XQuery in a parameterized way to * prevent injection. * diff --git a/src/main/java/org/owasp/esapi/Encryptor.java b/src/main/java/org/owasp/esapi/Encryptor.java index 28bb896a3..c1729a839 100644 --- a/src/main/java/org/owasp/esapi/Encryptor.java +++ b/src/main/java/org/owasp/esapi/Encryptor.java @@ -162,8 +162,8 @@ CipherText encrypt(SecretKey key, PlainText plaintext) *

    * @param ciphertext The {@code CipherText} object to be decrypted. * @return The {@code PlainText} object resulting from decrypting the specified - * ciphertext. Note that it it is desired to convert the returned - * plaintext byte array to a Java String is should be done using + * ciphertext. Note that if it is desired to convert the returned + * plaintext byte array to a Java String it should be done using * {@code new String(byte[], "UTF-8");} rather than simply using * {@code new String(byte[]);} which uses native encoding and may * not be portable across hardware and/or OS platforms. @@ -186,8 +186,8 @@ CipherText encrypt(SecretKey key, PlainText plaintext) * @param key The {@code SecretKey} to use for encrypting the plaintext. * @param ciphertext The {@code CipherText} object to be decrypted. * @return The {@code PlainText} object resulting from decrypting the specified - * ciphertext. Note that it it is desired to convert the returned - * plaintext byte array to a Java String is should be done using + * ciphertext. Note that if it is desired to convert the returned + * plaintext byte array to a Java String it should be done using * {@code new String(byte[], "UTF-8");} rather than simply using * {@code new String(byte[]);} which uses native encoding and may * not be portable across hardware and/or OS platforms. diff --git a/src/main/java/org/owasp/esapi/HTTPUtilities.java b/src/main/java/org/owasp/esapi/HTTPUtilities.java index 9cdfc36b0..582f1a1b7 100644 --- a/src/main/java/org/owasp/esapi/HTTPUtilities.java +++ b/src/main/java/org/owasp/esapi/HTTPUtilities.java @@ -377,7 +377,7 @@ public interface HTTPUtilities * everything to keey your application and environment secure. Some of the more obvious omissions are the * absence of examining the actual file content to determine the actual file type or running some AV scan * on the uploaded files. You have to add that functionality to you if you want or need that. Some - * reasource that you may find usefule are: + * resource that you may find useful are: *