Skip to content

Commit 21105d9

Browse files
committed
Added new static method 'isMethodExplicityEnabled' abd other minor Javadoc tweaks.
1 parent 31e221a commit 21105d9

File tree

1 file changed

+87
-3
lines changed

1 file changed

+87
-3
lines changed

src/main/java/org/owasp/esapi/ESAPI.java

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@
1616
*/
1717
package org.owasp.esapi;
1818

19+
import java.util.Arrays;
20+
1921
import javax.servlet.http.HttpServletRequest;
2022
import javax.servlet.http.HttpServletResponse;
2123

2224
import org.owasp.esapi.util.ObjFactory;
25+
import org.owasp.esapi.errors.ConfigurationException;
2326

2427
/**
2528
* ESAPI locator class is provided to make it easy to gain access to the current ESAPI classes in use.
@@ -93,16 +96,18 @@ public static Authenticator authenticator() {
9396
}
9497

9598
/**
96-
* The ESAPI Encoder is primarily used to provide <i>output</i> encoding to
99+
* The ESAPI {@code Encoder} is primarily used to provide <i>output</i> encoding to
97100
* prevent Cross-Site Scripting (XSS).
98-
* @return the current ESAPI Encoder object being used to encode and decode data for this application.
101+
* @return the current ESAPI {@code Encoder} object being used to encode and decode data for this application.
99102
*/
100103
public static Encoder encoder() {
101104
return ObjFactory.make( securityConfiguration().getEncoderImplementation(), "Encoder" );
102105
}
103106

104107
/**
105-
* @return the current ESAPI Encryptor object being used to encrypt and decrypt data for this application.
108+
* ESAPI {@code Encryptor} provides a set of methods for performing common encryption, random number, and
109+
* hashing operations.
110+
* @return the current ESAPI {@code Encryptor} object being used to encrypt and decrypt data for this application.
106111
*/
107112
public static Encryptor encryptor() {
108113
return ObjFactory.make( securityConfiguration().getEncryptionImplementation(), "Encryptor" );
@@ -221,4 +226,83 @@ public static String initialize( String impl ) {
221226
public static void override( SecurityConfiguration config ) {
222227
overrideConfig = config;
223228
}
229+
230+
// KWW - OPEN ISSUE: I don't like placing this here, but it's convenient and I
231+
// don't really know a better place for it and would rather not create
232+
// a whole new utility class just to use it.
233+
/**
234+
* Determine if a given fully qualified (ESAPI) method name has been explicitly
235+
* enabled in the <b>ESAPI.properties</b>'s file via the property name
236+
* <b>ESAPI.dangerouslyAllowUnsafeMethods.methodNames</b>. Note that there
237+
* is no real reason for an ESAPI client to use this, It is intended for
238+
* interal use,
239+
* </p><p>
240+
* The reason this method exists is because certain (other) ESAPI method names
241+
* are considered "unsafe" and therefore should be used with extra caution.
242+
* These "unsafe" methods may include methods that are:
243+
* <ul>
244+
* <li>Deprecated and thus no longer suggested for long term use.</li>
245+
* <li>Methods where the programming contract is not in itself sufficient to ensure safety alone
246+
* and developers are expected to take addional actions on their own to secure their application.</li>
247+
* <li>Methods that are using some unpatched transitive dependency that we haven't firmly
248+
* established grounds for it not being exploitable in the manner that ESAPI uses it.</li>
249+
* <li>Methods whose reference implementations are not scalable to the enterprise level.</li>
250+
* </ul>
251+
* <i>Public</i> methods that are not in that list for the above ESAPI property
252+
* are generally are considered enabled and okay to use unless their Javadoc
253+
* indicates otherwise.
254+
* </p><p>
255+
* Note that this method is intended primarilly for internal ESAPI use and if we were
256+
* using Java Modules (in JDK 9 and later), this method would not be exported.
257+
* </p><p>
258+
* For further details, please see the ESAPI GitHub wiki article,
259+
* <a href="https://github.com/ESAPI/esapi-java-legacy/wiki/Reducing-the-ESAPI-Library's-Attack-Surface">"Reducing the ESAPI Library's Attack Surface"</a>.
260+
* @param fullyQualifiedMethodName A fully qualified ESAPI class name (so, should start
261+
* "org.owasp.esapi.") followed by the method name (but without
262+
* parenthesis or any parameter signature information.
263+
* @return {@code true} if the parameter {@code fullyQualifiedMethodName} is in the comma-separated
264+
* list of values in the ESAPI property <b>ESAPI.dangerouslyAllowUnsafeMethods.methodNames</b>,
265+
* otherwise {@code false} is returned.
266+
*/
267+
public static boolean isMethodExplicityEnabled(String fullyQualifiedMethodName) {
268+
if ( fullyQualifiedMethodName != null && fullyQualifiedMethodName.trim().isEmpty() ) {
269+
throw new IllegalArgumentException("Program error: fullyQualifiedMethodName parameter cannot be null or empty");
270+
}
271+
String desiredMethodName = fullyQualifiedMethodName.trim();
272+
// This regex is too liberal to be anything more than just a trivial
273+
// sanity test to protect against typos.
274+
if ( !desiredMethodName.matches("^org\\.owasp\\.esapi\\.(\\p{Alnum}|\\.)*$") ) {
275+
throw new IllegalArgumentException("Program error: fullyQualifiedMethodName must start with " +
276+
"'org.owasp.esapi.' and be a valid method name.");
277+
}
278+
279+
String enabledMethods = null;
280+
try {
281+
// Need to do this w/in a try/catch because if the property is not
282+
// found, getStringProp will throw a ConfigurationException rather
283+
// than returning a null.
284+
enabledMethods = securityConfiguration().getStringProp("ESAPI.dangerouslyAllowUnsafeMethods.methodNames");
285+
} catch( ConfigurationException cex ) {
286+
return false; // Property not found at all.
287+
}
288+
289+
if ( enabledMethods == null || enabledMethods.trim().isEmpty() ) {
290+
// TODO: Log something here? Maybe at DEBUG level?
291+
return false; // No methods in the list, so no match possible.
292+
}
293+
294+
// Split it up by ',' and then filter it by finding the first on that
295+
// matches the desired method name passed in as the method parameter.
296+
// If no matches, return the empty string.
297+
String result = Arrays.stream( enabledMethods.trim().split(",") )
298+
.filter(methodName -> methodName.trim().equals( desiredMethodName ) )
299+
.findFirst()
300+
.orElse("");
301+
302+
if ( result.isEmpty() ) {
303+
return false; // No match, so method not enabled
304+
} else {
305+
return true; // Method found, thus enabled
306+
}
307+
}
224308
}

0 commit comments

Comments
 (0)