/src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java

http://owasp-esapi-java.googlecode.com/ · Java · 1247 lines · 703 code · 143 blank · 401 comment · 111 complexity · bd57cd74d8b301aa708659d0709afb74 MD5 · raw file

  1. /**
  2. * OWASP Enterprise Security API (ESAPI)
  3. *
  4. * This file is part of the Open Web Application Security Project (OWASP)
  5. * Enterprise Security API (ESAPI) project. For details, please see
  6. * <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
  7. *
  8. * Copyright (c) 2007 - The OWASP Foundation
  9. *
  10. * The ESAPI is published by OWASP under the BSD license. You should read and accept the
  11. * LICENSE before you use, modify, and/or redistribute this software.
  12. *
  13. * @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
  14. * @created 2007
  15. */
  16. package org.owasp.esapi.reference;
  17. import java.io.File;
  18. import java.io.FileInputStream;
  19. import java.io.FileNotFoundException;
  20. import java.io.IOException;
  21. import java.io.InputStream;
  22. import java.net.URL;
  23. import java.util.ArrayList;
  24. import java.util.Arrays;
  25. import java.util.Collections;
  26. import java.util.HashMap;
  27. import java.util.Iterator;
  28. import java.util.List;
  29. import java.util.Map;
  30. import java.util.Properties;
  31. import java.util.regex.Pattern;
  32. import java.util.regex.PatternSyntaxException;
  33. import org.apache.commons.lang.text.StrTokenizer;
  34. import org.owasp.esapi.ESAPI;
  35. import org.owasp.esapi.Logger;
  36. import org.owasp.esapi.SecurityConfiguration;
  37. import org.owasp.esapi.errors.ConfigurationException;
  38. /**
  39. * The reference {@code SecurityConfiguration} manages all the settings used by the ESAPI in a single place. In this reference
  40. * implementation, resources can be put in several locations, which are searched in the following order:
  41. * <p>
  42. * 1) Inside a directory set with a call to SecurityConfiguration.setResourceDirectory( "C:\temp\resources" ).
  43. * <p>
  44. * 2) Inside the System.getProperty( "org.owasp.esapi.resources" ) directory.
  45. * You can set this on the java command line as follows (for example):
  46. * <pre>
  47. * java -Dorg.owasp.esapi.resources="C:\temp\resources"
  48. * </pre>
  49. * You may have to add this to the start-up script that starts your web server. For example, for Tomcat,
  50. * in the "catalina" script that starts Tomcat, you can set the JAVA_OPTS variable to the {@code -D} string above.
  51. * <p>
  52. * 3) Inside the {@code System.getProperty( "user.home" ) + "/.esapi"} directory (supported for backward compatibility) or
  53. * inside the {@code System.getProperty( "user.home" ) + "/esapi"} directory.
  54. * <p>
  55. * 4) The first ".esapi" or "esapi" directory on the classpath. (The former for backward compatibility.)
  56. * <p>
  57. * Once the Configuration is initialized with a resource directory, you can edit it to set things like master
  58. * keys and passwords, logging locations, error thresholds, and allowed file extensions.
  59. * <p>
  60. * WARNING: Do not forget to update ESAPI.properties to change the master key and other security critical settings.
  61. *
  62. * @author Jeff Williams (jeff.williams .at. aspectsecurity.com) <a href="http://www.aspectsecurity.com">Aspect Security</a>
  63. * @author Jim Manico (jim .at. manico.net) <a href="http://www.manico.net">Manico.net</a>
  64. * @author Kevin Wall (kevin.w.wall .at. gmail.com)
  65. */
  66. public class DefaultSecurityConfiguration implements SecurityConfiguration {
  67. private static volatile SecurityConfiguration instance = null;
  68. public static SecurityConfiguration getInstance() {
  69. if ( instance == null ) {
  70. synchronized (DefaultSecurityConfiguration.class) {
  71. if ( instance == null ) {
  72. instance = new DefaultSecurityConfiguration();
  73. }
  74. }
  75. }
  76. return instance;
  77. }
  78. private Properties properties = null;
  79. private String cipherXformFromESAPIProp = null; // New in ESAPI 2.0
  80. private String cipherXformCurrent = null; // New in ESAPI 2.0
  81. /** The name of the ESAPI property file */
  82. public static final String DEFAULT_RESOURCE_FILE = "ESAPI.properties";
  83. public static final String REMEMBER_TOKEN_DURATION = "Authenticator.RememberTokenDuration";
  84. public static final String IDLE_TIMEOUT_DURATION = "Authenticator.IdleTimeoutDuration";
  85. public static final String ABSOLUTE_TIMEOUT_DURATION = "Authenticator.AbsoluteTimeoutDuration";
  86. public static final String ALLOWED_LOGIN_ATTEMPTS = "Authenticator.AllowedLoginAttempts";
  87. public static final String USERNAME_PARAMETER_NAME = "Authenticator.UsernameParameterName";
  88. public static final String PASSWORD_PARAMETER_NAME = "Authenticator.PasswordParameterName";
  89. public static final String MAX_OLD_PASSWORD_HASHES = "Authenticator.MaxOldPasswordHashes";
  90. public static final String ALLOW_MULTIPLE_ENCODING = "Encoder.AllowMultipleEncoding";
  91. public static final String ALLOW_MIXED_ENCODING = "Encoder.AllowMixedEncoding";
  92. public static final String CANONICALIZATION_CODECS = "Encoder.DefaultCodecList";
  93. public static final String DISABLE_INTRUSION_DETECTION = "IntrusionDetector.Disable";
  94. public static final String MASTER_KEY = "Encryptor.MasterKey";
  95. public static final String MASTER_SALT = "Encryptor.MasterSalt";
  96. public static final String KEY_LENGTH = "Encryptor.EncryptionKeyLength";
  97. public static final String ENCRYPTION_ALGORITHM = "Encryptor.EncryptionAlgorithm";
  98. public static final String HASH_ALGORITHM = "Encryptor.HashAlgorithm";
  99. public static final String HASH_ITERATIONS = "Encryptor.HashIterations";
  100. public static final String CHARACTER_ENCODING = "Encryptor.CharacterEncoding";
  101. public static final String RANDOM_ALGORITHM = "Encryptor.RandomAlgorithm";
  102. public static final String DIGITAL_SIGNATURE_ALGORITHM = "Encryptor.DigitalSignatureAlgorithm";
  103. public static final String DIGITAL_SIGNATURE_KEY_LENGTH = "Encryptor.DigitalSignatureKeyLength";
  104. // ==================================//
  105. // New in ESAPI Java 2.0 //
  106. // ================================= //
  107. public static final String PREFERRED_JCE_PROVIDER = "Encryptor.PreferredJCEProvider";
  108. public static final String CIPHER_TRANSFORMATION_IMPLEMENTATION = "Encryptor.CipherTransformation";
  109. public static final String CIPHERTEXT_USE_MAC = "Encryptor.CipherText.useMAC";
  110. public static final String PLAINTEXT_OVERWRITE = "Encryptor.PlainText.overwrite";
  111. public static final String IV_TYPE = "Encryptor.ChooseIVMethod";
  112. public static final String FIXED_IV = "Encryptor.fixedIV";
  113. public static final String COMBINED_CIPHER_MODES = "Encryptor.cipher_modes.combined_modes";
  114. public static final String ADDITIONAL_ALLOWED_CIPHER_MODES = "Encryptor.cipher_modes.additional_allowed";
  115. public static final String KDF_PRF_ALG = "Encryptor.KDF.PRF";
  116. public static final String PRINT_PROPERTIES_WHEN_LOADED = "ESAPI.printProperties";
  117. public static final String WORKING_DIRECTORY = "Executor.WorkingDirectory";
  118. public static final String APPROVED_EXECUTABLES = "Executor.ApprovedExecutables";
  119. public static final String FORCE_HTTPONLYSESSION = "HttpUtilities.ForceHttpOnlySession";
  120. public static final String FORCE_SECURESESSION = "HttpUtilities.SecureSession";
  121. public static final String FORCE_HTTPONLYCOOKIES = "HttpUtilities.ForceHttpOnlyCookies";
  122. public static final String FORCE_SECURECOOKIES = "HttpUtilities.ForceSecureCookies";
  123. public static final String MAX_HTTP_HEADER_SIZE = "HttpUtilities.MaxHeaderSize";
  124. public static final String UPLOAD_DIRECTORY = "HttpUtilities.UploadDir";
  125. public static final String UPLOAD_TEMP_DIRECTORY = "HttpUtilities.UploadTempDir";
  126. public static final String APPROVED_UPLOAD_EXTENSIONS = "HttpUtilities.ApprovedUploadExtensions";
  127. public static final String MAX_UPLOAD_FILE_BYTES = "HttpUtilities.MaxUploadFileBytes";
  128. public static final String RESPONSE_CONTENT_TYPE = "HttpUtilities.ResponseContentType";
  129. public static final String HTTP_SESSION_ID_NAME = "HttpUtilities.HttpSessionIdName";
  130. public static final String APPLICATION_NAME = "Logger.ApplicationName";
  131. public static final String LOG_LEVEL = "Logger.LogLevel";
  132. public static final String LOG_FILE_NAME = "Logger.LogFileName";
  133. public static final String MAX_LOG_FILE_SIZE = "Logger.MaxLogFileSize";
  134. public static final String LOG_ENCODING_REQUIRED = "Logger.LogEncodingRequired";
  135. public static final String LOG_APPLICATION_NAME = "Logger.LogApplicationName";
  136. public static final String LOG_SERVER_IP = "Logger.LogServerIP";
  137. public static final String VALIDATION_PROPERTIES = "Validator.ConfigurationFile";
  138. public static final String VALIDATION_PROPERTIES_MULTIVALUED = "Validator.ConfigurationFile.MultiValued";
  139. public static final String ACCEPT_LENIENT_DATES = "Validator.AcceptLenientDates";
  140. /**
  141. * The default max log file size is set to 10,000,000 bytes (10 Meg). If the current log file exceeds the current
  142. * max log file size, the logger will move the old log data into another log file. There currently is a max of
  143. * 1000 log files of the same name. If that is exceeded it will presumably start discarding the oldest logs.
  144. */
  145. public static final int DEFAULT_MAX_LOG_FILE_SIZE = 10000000;
  146. protected final int MAX_REDIRECT_LOCATION = 1000;
  147. /**
  148. * @deprecated It is not clear whether this is intended to be the max file name length for the basename(1) of
  149. * a file or the max full path name length of a canonical full path name. Since it is not used anywhere
  150. * in the ESAPI code it is being deprecated and scheduled to be removed in release 2.1.
  151. */
  152. protected final int MAX_FILE_NAME_LENGTH = 1000; // DISCUSS: Is this for given directory or refer to canonicalized full path name?
  153. // Too long if the former! (Usually 255 is limit there.) Hard to tell since not used
  154. // here in this class and it's protected, so not sure what it's intent is. It's not
  155. // used anywhere in the ESAPI code base. I am going to deprecate it because of this. -kww
  156. /*
  157. * Implementation Keys
  158. */
  159. public static final String LOG_IMPLEMENTATION = "ESAPI.Logger";
  160. public static final String AUTHENTICATION_IMPLEMENTATION = "ESAPI.Authenticator";
  161. public static final String ENCODER_IMPLEMENTATION = "ESAPI.Encoder";
  162. public static final String ACCESS_CONTROL_IMPLEMENTATION = "ESAPI.AccessControl";
  163. public static final String ENCRYPTION_IMPLEMENTATION = "ESAPI.Encryptor";
  164. public static final String INTRUSION_DETECTION_IMPLEMENTATION = "ESAPI.IntrusionDetector";
  165. public static final String RANDOMIZER_IMPLEMENTATION = "ESAPI.Randomizer";
  166. public static final String EXECUTOR_IMPLEMENTATION = "ESAPI.Executor";
  167. public static final String VALIDATOR_IMPLEMENTATION = "ESAPI.Validator";
  168. public static final String HTTP_UTILITIES_IMPLEMENTATION = "ESAPI.HTTPUtilities";
  169. /*
  170. * Default Implementations
  171. */
  172. public static final String DEFAULT_LOG_IMPLEMENTATION = "org.owasp.esapi.reference.JavaLogFactory";
  173. public static final String DEFAULT_AUTHENTICATION_IMPLEMENTATION = "org.owasp.esapi.reference.FileBasedAuthenticator";
  174. public static final String DEFAULT_ENCODER_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultEncoder";
  175. public static final String DEFAULT_ACCESS_CONTROL_IMPLEMENTATION = "org.owasp.esapi.reference.accesscontrol.DefaultAccessController";
  176. public static final String DEFAULT_ENCRYPTION_IMPLEMENTATION = "org.owasp.esapi.reference.crypto.JavaEncryptor";
  177. public static final String DEFAULT_INTRUSION_DETECTION_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultIntrusionDetector";
  178. public static final String DEFAULT_RANDOMIZER_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultRandomizer";
  179. public static final String DEFAULT_EXECUTOR_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultExecutor";
  180. public static final String DEFAULT_HTTP_UTILITIES_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultHTTPUtilities";
  181. public static final String DEFAULT_VALIDATOR_IMPLEMENTATION = "org.owasp.esapi.reference.DefaultValidator";
  182. private static final Map<String, Pattern> patternCache = new HashMap<String, Pattern>();
  183. /*
  184. * Absolute path to the user.home. No longer includes the ESAPI portion as it used to.
  185. */
  186. private static final String userHome = System.getProperty("user.home" );
  187. /*
  188. * Absolute path to the customDirectory
  189. */ // DISCUSS: Implicit assumption here that there is no SecurityManager installed enforcing the
  190. // prevention of reading system properties. Otherwise this will fail with SecurityException.
  191. private static String customDirectory = System.getProperty("org.owasp.esapi.resources");
  192. /*
  193. * Relative path to the resourceDirectory. Relative to the classpath.
  194. * Specifically, ClassLoader.getResource(resourceDirectory + filename) will
  195. * be used to load the file.
  196. */
  197. private String resourceDirectory = ".esapi"; // For backward compatibility (vs. "esapi")
  198. private final String resourceFile;
  199. // private static long lastModified = -1;
  200. /**
  201. * Instantiates a new configuration, using the provided property file name
  202. *
  203. * @param resourceFile The name of the property file to load
  204. */
  205. DefaultSecurityConfiguration(String resourceFile) {
  206. this.resourceFile = resourceFile;
  207. // load security configuration
  208. try {
  209. loadConfiguration();
  210. this.setCipherXProperties();
  211. } catch( IOException e ) {
  212. logSpecial("Failed to load security configuration", e );
  213. throw new ConfigurationException("Failed to load security configuration", e);
  214. }
  215. }
  216. /**
  217. * Instantiates a new configuration with the supplied properties.
  218. *
  219. * Warning - if the setResourceDirectory() method is invoked the properties will
  220. * be re-loaded, replacing the supplied properties.
  221. *
  222. * @param properties
  223. */
  224. public DefaultSecurityConfiguration(Properties properties) {
  225. resourceFile = DEFAULT_RESOURCE_FILE;
  226. this.properties = properties;
  227. this.setCipherXProperties();
  228. }
  229. /**
  230. * Instantiates a new configuration.
  231. */
  232. public DefaultSecurityConfiguration(){
  233. this(DEFAULT_RESOURCE_FILE);
  234. }
  235. private void setCipherXProperties() {
  236. // TODO: FUTURE: Replace by future CryptoControls class???
  237. // See SecurityConfiguration.setCipherTransformation() for
  238. // explanation of this.
  239. // (Propose this in 2.1 via future email to ESAPI-DEV list.)
  240. cipherXformFromESAPIProp =
  241. getESAPIProperty(CIPHER_TRANSFORMATION_IMPLEMENTATION,
  242. "AES/CBC/PKCS5Padding");
  243. cipherXformCurrent = cipherXformFromESAPIProp;
  244. }
  245. /**
  246. * {@inheritDoc}
  247. */
  248. public String getApplicationName() {
  249. return getESAPIProperty(APPLICATION_NAME, "DefaultName");
  250. }
  251. /**
  252. * {@inheritDoc}
  253. */
  254. public String getLogImplementation() {
  255. return getESAPIProperty(LOG_IMPLEMENTATION, DEFAULT_LOG_IMPLEMENTATION);
  256. }
  257. /**
  258. * {@inheritDoc}
  259. */
  260. public String getAuthenticationImplementation() {
  261. return getESAPIProperty(AUTHENTICATION_IMPLEMENTATION, DEFAULT_AUTHENTICATION_IMPLEMENTATION);
  262. }
  263. /**
  264. * {@inheritDoc}
  265. */
  266. public String getEncoderImplementation() {
  267. return getESAPIProperty(ENCODER_IMPLEMENTATION, DEFAULT_ENCODER_IMPLEMENTATION);
  268. }
  269. /**
  270. * {@inheritDoc}
  271. */
  272. public String getAccessControlImplementation() {
  273. return getESAPIProperty(ACCESS_CONTROL_IMPLEMENTATION, DEFAULT_ACCESS_CONTROL_IMPLEMENTATION);
  274. }
  275. /**
  276. * {@inheritDoc}
  277. */
  278. public String getEncryptionImplementation() {
  279. return getESAPIProperty(ENCRYPTION_IMPLEMENTATION, DEFAULT_ENCRYPTION_IMPLEMENTATION);
  280. }
  281. /**
  282. * {@inheritDoc}
  283. */
  284. public String getIntrusionDetectionImplementation() {
  285. return getESAPIProperty(INTRUSION_DETECTION_IMPLEMENTATION, DEFAULT_INTRUSION_DETECTION_IMPLEMENTATION);
  286. }
  287. /**
  288. * {@inheritDoc}
  289. */
  290. public String getRandomizerImplementation() {
  291. return getESAPIProperty(RANDOMIZER_IMPLEMENTATION, DEFAULT_RANDOMIZER_IMPLEMENTATION);
  292. }
  293. /**
  294. * {@inheritDoc}
  295. */
  296. public String getExecutorImplementation() {
  297. return getESAPIProperty(EXECUTOR_IMPLEMENTATION, DEFAULT_EXECUTOR_IMPLEMENTATION);
  298. }
  299. /**
  300. * {@inheritDoc}
  301. */
  302. public String getHTTPUtilitiesImplementation() {
  303. return getESAPIProperty(HTTP_UTILITIES_IMPLEMENTATION, DEFAULT_HTTP_UTILITIES_IMPLEMENTATION);
  304. }
  305. /**
  306. * {@inheritDoc}
  307. */
  308. public String getValidationImplementation() {
  309. return getESAPIProperty(VALIDATOR_IMPLEMENTATION, DEFAULT_VALIDATOR_IMPLEMENTATION);
  310. }
  311. /**
  312. * {@inheritDoc}
  313. */
  314. public byte[] getMasterKey() {
  315. byte[] key = getESAPIPropertyEncoded( MASTER_KEY, null );
  316. if ( key == null || key.length == 0 ) {
  317. throw new ConfigurationException("Property '" + MASTER_KEY +
  318. "' missing or empty in ESAPI.properties file.");
  319. }
  320. return key;
  321. }
  322. /**
  323. * {@inheritDoc}
  324. */
  325. public void setResourceDirectory( String dir ) {
  326. resourceDirectory = dir;
  327. logSpecial( "Reset resource directory to: " + dir, null );
  328. // reload configuration if necessary
  329. try {
  330. this.loadConfiguration();
  331. } catch( IOException e ) {
  332. logSpecial("Failed to load security configuration from " + dir, e);
  333. }
  334. }
  335. public int getEncryptionKeyLength() {
  336. return getESAPIProperty(KEY_LENGTH, 128 );
  337. }
  338. /**
  339. * {@inheritDoc}
  340. */
  341. public byte[] getMasterSalt() {
  342. byte[] salt = getESAPIPropertyEncoded( MASTER_SALT, null );
  343. if ( salt == null || salt.length == 0 ) {
  344. throw new ConfigurationException("Property '" + MASTER_SALT +
  345. "' missing or empty in ESAPI.properties file.");
  346. }
  347. return salt;
  348. }
  349. /**
  350. * {@inheritDoc}
  351. */
  352. public List<String> getAllowedExecutables() {
  353. String def = "";
  354. String[] exList = getESAPIProperty(APPROVED_EXECUTABLES,def).split(",");
  355. return Arrays.asList(exList);
  356. }
  357. /**
  358. * {@inheritDoc}
  359. */
  360. public List<String> getAllowedFileExtensions() {
  361. String def = ".zip,.pdf,.tar,.gz,.xls,.properties,.txt,.xml";
  362. String[] extList = getESAPIProperty(APPROVED_UPLOAD_EXTENSIONS,def).split(",");
  363. return Arrays.asList(extList);
  364. }
  365. /**
  366. * {@inheritDoc}
  367. */
  368. public int getAllowedFileUploadSize() {
  369. return getESAPIProperty(MAX_UPLOAD_FILE_BYTES, 5000000);
  370. }
  371. private Properties loadPropertiesFromStream( InputStream is, String name ) throws IOException {
  372. Properties config = new Properties();
  373. try {
  374. config.load(is);
  375. logSpecial("Loaded '" + name + "' properties file", null);
  376. } finally {
  377. if ( is != null ) try { is.close(); } catch( Exception e ) {}
  378. }
  379. return config;
  380. }
  381. /**
  382. * Load configuration. Never prints properties.
  383. *
  384. * @throws java.io.IOException
  385. * if the file is inaccessible
  386. */
  387. protected void loadConfiguration() throws IOException {
  388. try {
  389. //first attempt file IO loading of properties
  390. logSpecial("Attempting to load " + resourceFile + " via file I/O.");
  391. properties = loadPropertiesFromStream(getResourceStream(resourceFile), resourceFile);
  392. } catch (Exception iae) {
  393. //if file I/O loading fails, attempt classpath based loading next
  394. logSpecial("Loading " + resourceFile + " via file I/O failed. Exception was: " + iae);
  395. logSpecial("Attempting to load " + resourceFile + " via the classpath.");
  396. try {
  397. properties = loadConfigurationFromClasspath(resourceFile);
  398. } catch (Exception e) {
  399. logSpecial(resourceFile + " could not be loaded by any means. Fail.", e);
  400. throw new ConfigurationException(resourceFile + " could not be loaded by any means. Fail.", e);
  401. }
  402. }
  403. // if properties loaded properly above, get validation properties and merge them into the main properties
  404. if (properties != null) {
  405. final Iterator<String> validationPropFileNames;
  406. //defaults to single-valued for backwards compatibility
  407. final boolean multivalued= getESAPIProperty(VALIDATION_PROPERTIES_MULTIVALUED, false);
  408. final String validationPropValue = getESAPIProperty(VALIDATION_PROPERTIES, "validation.properties");
  409. if(multivalued){
  410. // the following cast warning goes away if the apache commons lib is updated to current version
  411. validationPropFileNames = StrTokenizer.getCSVInstance(validationPropValue);
  412. } else {
  413. validationPropFileNames = Collections.singletonList(validationPropValue).iterator();
  414. }
  415. //clear any cached validation patterns so they can be reloaded from validation.properties
  416. patternCache.clear();
  417. while(validationPropFileNames.hasNext()){
  418. String validationPropFileName = validationPropFileNames.next();
  419. Properties validationProperties = null;
  420. try {
  421. //first attempt file IO loading of properties
  422. logSpecial("Attempting to load " + validationPropFileName + " via file I/O.");
  423. validationProperties = loadPropertiesFromStream(getResourceStream(validationPropFileName), validationPropFileName);
  424. } catch (Exception iae) {
  425. //if file I/O loading fails, attempt classpath based loading next
  426. logSpecial("Loading " + validationPropFileName + " via file I/O failed.");
  427. logSpecial("Attempting to load " + validationPropFileName + " via the classpath.");
  428. try {
  429. validationProperties = loadConfigurationFromClasspath(validationPropFileName);
  430. } catch (Exception e) {
  431. logSpecial(validationPropFileName + " could not be loaded by any means. fail.", e);
  432. }
  433. }
  434. if (validationProperties != null) {
  435. Iterator<?> i = validationProperties.keySet().iterator();
  436. while( i.hasNext() ) {
  437. String key = (String)i.next();
  438. String value = validationProperties.getProperty(key);
  439. properties.put( key, value);
  440. }
  441. }
  442. if ( shouldPrintProperties() ) {
  443. //FIXME - make this chunk configurable
  444. /*
  445. logSpecial(" ========Master Configuration========", null);
  446. //logSpecial( " ResourceDirectory: " + DefaultSecurityConfiguration.resourceDirectory );
  447. Iterator j = new TreeSet( properties.keySet() ).iterator();
  448. while (j.hasNext()) {
  449. String key = (String)j.next();
  450. // print out properties, but not sensitive ones like MasterKey and MasterSalt
  451. if ( !key.contains( "Master" ) ) {
  452. logSpecial(" | " + key + "=" + properties.get(key), null);
  453. }
  454. }
  455. */
  456. }
  457. }
  458. }
  459. }
  460. /**
  461. * @param filename
  462. * @return An {@code InputStream} associated with the specified file name as
  463. * a resource stream.
  464. * @throws IOException
  465. * If the file cannot be found or opened for reading.
  466. */
  467. public InputStream getResourceStream(String filename) throws IOException {
  468. if (filename == null) {
  469. return null;
  470. }
  471. try {
  472. File f = getResourceFile(filename);
  473. if (f != null && f.exists()) {
  474. return new FileInputStream(f);
  475. }
  476. } catch (Exception e) {
  477. }
  478. throw new FileNotFoundException();
  479. }
  480. /**
  481. * {@inheritDoc}
  482. */
  483. public File getResourceFile(String filename) {
  484. logSpecial("Attempting to load " + filename + " as resource file via file I/O.");
  485. if (filename == null) {
  486. logSpecial("Failed to load properties via FileIO. Filename is null.");
  487. return null; // not found.
  488. }
  489. File f = null;
  490. // first, allow command line overrides. -Dorg.owasp.esapi.resources
  491. // directory
  492. f = new File(customDirectory, filename);
  493. if (customDirectory != null && f.canRead()) {
  494. logSpecial("Found in 'org.owasp.esapi.resources' directory: " + f.getAbsolutePath());
  495. return f;
  496. } else {
  497. logSpecial("Not found in 'org.owasp.esapi.resources' directory or file not readable: " + f.getAbsolutePath());
  498. }
  499. // if not found, then try the programmatically set resource directory
  500. // (this defaults to SystemResource directory/resourceFile
  501. URL fileUrl = ClassLoader.getSystemResource(resourceDirectory + "/" + filename);
  502. if ( fileUrl == null ) {
  503. fileUrl = ClassLoader.getSystemResource("esapi/" + filename);
  504. }
  505. if (fileUrl != null) {
  506. String fileLocation = fileUrl.getFile();
  507. f = new File(fileLocation);
  508. if (f.exists()) {
  509. logSpecial("Found in SystemResource Directory/resourceDirectory: " + f.getAbsolutePath());
  510. return f;
  511. } else {
  512. logSpecial("Not found in SystemResource Directory/resourceDirectory (this should never happen): " + f.getAbsolutePath());
  513. }
  514. } else {
  515. logSpecial("Not found in SystemResource Directory/resourceDirectory: " + resourceDirectory + File.separator + filename);
  516. }
  517. // If not found, then try immediately under user's home directory first in
  518. // userHome + "/.esapi" and secondly under
  519. // userHome + "/esapi"
  520. // We look in that order because of backward compatibility issues.
  521. String homeDir = userHome;
  522. if ( homeDir == null ) {
  523. homeDir = ""; // Without this, homeDir + "/.esapi" would produce
  524. // the string "null/.esapi" which surely is not intended.
  525. }
  526. // First look under ".esapi" (for reasons of backward compatibility).
  527. f = new File(homeDir + "/.esapi", filename);
  528. if ( f.canRead() ) {
  529. logSpecial("[Compatibility] Found in 'user.home' directory: " + f.getAbsolutePath());
  530. return f;
  531. } else {
  532. // Didn't find it under old directory ".esapi" so now look under the "esapi" directory.
  533. f = new File(homeDir + "/esapi", filename);
  534. if ( f.canRead() ) {
  535. logSpecial("Found in 'user.home' directory: " + f.getAbsolutePath());
  536. return f;
  537. } else {
  538. logSpecial("Not found in 'user.home' (" + homeDir + ") directory: " + f.getAbsolutePath());
  539. }
  540. }
  541. // return null if not found
  542. return null;
  543. }
  544. /**
  545. * Used to load ESAPI.properties from a variety of different classpath locations.
  546. *
  547. * @param fileName The properties file filename.
  548. */
  549. private Properties loadConfigurationFromClasspath(String fileName) throws IllegalArgumentException {
  550. Properties result = null;
  551. InputStream in = null;
  552. ClassLoader[] loaders = new ClassLoader[] {
  553. Thread.currentThread().getContextClassLoader(),
  554. ClassLoader.getSystemClassLoader(),
  555. getClass().getClassLoader()
  556. };
  557. String[] classLoaderNames = {
  558. "current thread context class loader",
  559. "system class loader",
  560. "class loader for DefaultSecurityConfiguration class"
  561. };
  562. ClassLoader currentLoader = null;
  563. for (int i = 0; i < loaders.length; i++) {
  564. if (loaders[i] != null) {
  565. currentLoader = loaders[i];
  566. try {
  567. // try root
  568. String currentClasspathSearchLocation = "/ (root)";
  569. in = loaders[i].getResourceAsStream(fileName);
  570. // try resourceDirectory folder
  571. if (in == null) {
  572. currentClasspathSearchLocation = resourceDirectory + "/";
  573. in = currentLoader.getResourceAsStream(resourceDirectory + "/" + fileName);
  574. }
  575. // try .esapi folder. Look here first for backward compatibility.
  576. if (in == null) {
  577. currentClasspathSearchLocation = ".esapi/";
  578. in = currentLoader.getResourceAsStream(".esapi/" + fileName);
  579. }
  580. // try esapi folder (new directory)
  581. if (in == null) {
  582. currentClasspathSearchLocation = "esapi/";
  583. in = currentLoader.getResourceAsStream("esapi/" + fileName);
  584. }
  585. // try resources folder
  586. if (in == null) {
  587. currentClasspathSearchLocation = "resources/";
  588. in = currentLoader.getResourceAsStream("resources/" + fileName);
  589. }
  590. // now load the properties
  591. if (in != null) {
  592. result = new Properties();
  593. result.load(in); // Can throw IOException
  594. logSpecial("SUCCESSFULLY LOADED " + fileName + " via the CLASSPATH from '" +
  595. currentClasspathSearchLocation + "' using " + classLoaderNames[i] + "!");
  596. break; // Outta here since we've found and loaded it.
  597. }
  598. } catch (Exception e) {
  599. result = null;
  600. } finally {
  601. try {
  602. in.close();
  603. } catch (Exception e) {
  604. }
  605. }
  606. }
  607. }
  608. if (result == null) {
  609. // CHECKME: This is odd...why not ConfigurationException?
  610. throw new IllegalArgumentException("Failed to load " + resourceFile + " as a classloader resource.");
  611. }
  612. return result;
  613. }
  614. /**
  615. * Used to log errors to the console during the loading of the properties file itself. Can't use
  616. * standard logging in this case, since the Logger may not be initialized yet. Output is sent to
  617. * {@code PrintStream} {@code System.out}.
  618. *
  619. * @param message The message to send to the console.
  620. * @param e The error that occurred. (This value printed via {@code e.toString()}.)
  621. */
  622. private void logSpecial(String message, Throwable e) {
  623. StringBuffer msg = new StringBuffer(message);
  624. if (e != null) {
  625. msg.append(" Exception was: ").append( e.toString() );
  626. }
  627. System.out.println( msg.toString() );
  628. // if ( e != null) e.printStackTrace(); // TODO ??? Do we want this?
  629. }
  630. /**
  631. * Used to log errors to the console during the loading of the properties file itself. Can't use
  632. * standard logging in this case, since the Logger may not be initialized yet. Output is sent to
  633. * {@code PrintStream} {@code System.out}.
  634. *
  635. * @param message The message to send to the console.
  636. */
  637. private void logSpecial(String message) {
  638. System.out.println(message);
  639. }
  640. /**
  641. * {@inheritDoc}
  642. */
  643. public String getPasswordParameterName() {
  644. return getESAPIProperty(PASSWORD_PARAMETER_NAME, "password");
  645. }
  646. /**
  647. * {@inheritDoc}
  648. */
  649. public String getUsernameParameterName() {
  650. return getESAPIProperty(USERNAME_PARAMETER_NAME, "username");
  651. }
  652. /**
  653. * {@inheritDoc}
  654. */
  655. public String getEncryptionAlgorithm() {
  656. return getESAPIProperty(ENCRYPTION_ALGORITHM, "AES");
  657. }
  658. /**
  659. * {@inheritDoc}
  660. */
  661. public String getCipherTransformation() {
  662. assert cipherXformCurrent != null : "Current cipher transformation is null";
  663. return cipherXformCurrent;
  664. }
  665. /**
  666. * {@inheritDoc}
  667. */
  668. public String setCipherTransformation(String cipherXform) {
  669. String previous = getCipherTransformation();
  670. if ( cipherXform == null ) {
  671. // Special case... means set it to original value from ESAPI.properties
  672. cipherXformCurrent = cipherXformFromESAPIProp;
  673. } else {
  674. assert ! cipherXform.trim().equals("") :
  675. "Cipher transformation cannot be just white space or empty string";
  676. cipherXformCurrent = cipherXform; // Note: No other sanity checks!!!
  677. }
  678. return previous;
  679. }
  680. /**
  681. * {@inheritDoc}
  682. */
  683. public boolean useMACforCipherText() {
  684. return getESAPIProperty(CIPHERTEXT_USE_MAC, true);
  685. }
  686. /**
  687. * {@inheritDoc}
  688. */
  689. public boolean overwritePlainText() {
  690. return getESAPIProperty(PLAINTEXT_OVERWRITE, true);
  691. }
  692. /**
  693. * {@inheritDoc}
  694. */
  695. public String getIVType() {
  696. String value = getESAPIProperty(IV_TYPE, "random");
  697. if ( value.equalsIgnoreCase("fixed") || value.equalsIgnoreCase("random") ) {
  698. return value;
  699. } else if ( value.equalsIgnoreCase("specified") ) {
  700. // This is planned for future implementation where setting
  701. // Encryptor.ChooseIVMethod=specified will require setting some
  702. // other TBD property that will specify an implementation class that
  703. // will generate appropriate IVs. The intent of this would be to use
  704. // such a class with various feedback modes where it is imperative
  705. // that for a given key, any particular IV is *NEVER* reused. For
  706. // now, we will assume that generating a random IV is usually going
  707. // to be sufficient to prevent this.
  708. throw new ConfigurationException("'" + IV_TYPE + "=specified' is not yet implemented. Use 'fixed' or 'random'");
  709. } else {
  710. // TODO: Once 'specified' is legal, adjust exception msg, below.
  711. // DISCUSS: Could just log this and then silently return "random" instead.
  712. throw new ConfigurationException(value + " is illegal value for " + IV_TYPE +
  713. ". Use 'random' (preferred) or 'fixed'.");
  714. }
  715. }
  716. /**
  717. * {@inheritDoc}
  718. */
  719. public String getFixedIV() {
  720. if ( getIVType().equalsIgnoreCase("fixed") ) {
  721. String ivAsHex = getESAPIProperty(FIXED_IV, ""); // No default
  722. if ( ivAsHex == null || ivAsHex.trim().equals("") ) {
  723. throw new ConfigurationException("Fixed IV requires property " +
  724. FIXED_IV + " to be set, but it is not.");
  725. }
  726. return ivAsHex; // We do no further checks here as we have no context.
  727. } else {
  728. // DISCUSS: Should we just log a warning here and return null instead?
  729. // If so, may cause NullPointException somewhere later.
  730. throw new ConfigurationException("IV type not 'fixed' (set to '" +
  731. getIVType() + "'), so no fixed IV applicable.");
  732. }
  733. }
  734. /**
  735. * {@inheritDoc}
  736. */
  737. public String getHashAlgorithm() {
  738. return getESAPIProperty(HASH_ALGORITHM, "SHA-512");
  739. }
  740. /**
  741. * {@inheritDoc}
  742. */
  743. public int getHashIterations() {
  744. return getESAPIProperty(HASH_ITERATIONS, 1024);
  745. }
  746. /**
  747. * {@inheritDoc}
  748. */
  749. public String getKDFPseudoRandomFunction() {
  750. return getESAPIProperty(KDF_PRF_ALG, "HmacSHA256"); // NSA recommended SHA2 or better.
  751. }
  752. /**
  753. * {@inheritDoc}
  754. */
  755. public String getCharacterEncoding() {
  756. return getESAPIProperty(CHARACTER_ENCODING, "UTF-8");
  757. }
  758. /**
  759. * {@inheritDoc}
  760. */
  761. public boolean getAllowMultipleEncoding() {
  762. return getESAPIProperty( ALLOW_MULTIPLE_ENCODING, false );
  763. }
  764. /**
  765. * {@inheritDoc}
  766. */
  767. public boolean getAllowMixedEncoding() {
  768. return getESAPIProperty( ALLOW_MIXED_ENCODING, false );
  769. }
  770. /**
  771. * {@inheritDoc}
  772. */
  773. public List<String> getDefaultCanonicalizationCodecs() {
  774. List<String> def = new ArrayList<String>();
  775. def.add( "org.owasp.esapi.codecs.HTMLEntityCodec" );
  776. def.add( "org.owasp.esapi.codecs.PercentCodec" );
  777. def.add( "org.owasp.esapi.codecs.JavaScriptCodec" );
  778. return getESAPIProperty( CANONICALIZATION_CODECS, def );
  779. }
  780. /**
  781. * {@inheritDoc}
  782. */
  783. public String getDigitalSignatureAlgorithm() {
  784. return getESAPIProperty(DIGITAL_SIGNATURE_ALGORITHM, "SHAwithDSA");
  785. }
  786. /**
  787. * {@inheritDoc}
  788. */
  789. public int getDigitalSignatureKeyLength() {
  790. return getESAPIProperty(DIGITAL_SIGNATURE_KEY_LENGTH, 1024);
  791. }
  792. /**
  793. * {@inheritDoc}
  794. */
  795. public String getRandomAlgorithm() {
  796. return getESAPIProperty(RANDOM_ALGORITHM, "SHA1PRNG");
  797. }
  798. /**
  799. * {@inheritDoc}
  800. */
  801. public int getAllowedLoginAttempts() {
  802. return getESAPIProperty(ALLOWED_LOGIN_ATTEMPTS, 5);
  803. }
  804. /**
  805. * {@inheritDoc}
  806. */
  807. public int getMaxOldPasswordHashes() {
  808. return getESAPIProperty(MAX_OLD_PASSWORD_HASHES, 12);
  809. }
  810. /**
  811. * {@inheritDoc}
  812. */
  813. public File getUploadDirectory() {
  814. String dir = getESAPIProperty( UPLOAD_DIRECTORY, "UploadDir");
  815. return new File( dir );
  816. }
  817. /**
  818. * {@inheritDoc}
  819. */
  820. public File getUploadTempDirectory() {
  821. String dir = getESAPIProperty(UPLOAD_TEMP_DIRECTORY,
  822. System.getProperty("java.io.tmpdir","UploadTempDir"));
  823. return new File( dir );
  824. }
  825. /**
  826. * {@inheritDoc}
  827. */
  828. public boolean getDisableIntrusionDetection() {
  829. String value = properties.getProperty( DISABLE_INTRUSION_DETECTION );
  830. if ("true".equalsIgnoreCase(value)) return true;
  831. return false; // Default result
  832. }
  833. /**
  834. * {@inheritDoc}
  835. */
  836. public Threshold getQuota(String eventName) {
  837. int count = getESAPIProperty("IntrusionDetector." + eventName + ".count", 0);
  838. int interval = getESAPIProperty("IntrusionDetector." + eventName + ".interval", 0);
  839. List<String> actions = new ArrayList<String>();
  840. String actionString = getESAPIProperty("IntrusionDetector." + eventName + ".actions", "");
  841. if (actionString != null) {
  842. String[] actionList = actionString.split(",");
  843. actions = Arrays.asList(actionList);
  844. }
  845. if ( count > 0 && interval > 0 && actions.size() > 0 ) {
  846. return new Threshold(eventName, count, interval, actions);
  847. }
  848. return null;
  849. }
  850. /**
  851. * {@inheritDoc}
  852. */
  853. public int getLogLevel() {
  854. String level = getESAPIProperty(LOG_LEVEL, "WARNING" );
  855. if (level.equalsIgnoreCase("OFF"))
  856. return Logger.OFF;
  857. if (level.equalsIgnoreCase("FATAL"))
  858. return Logger.FATAL;
  859. if (level.equalsIgnoreCase("ERROR"))
  860. return Logger.ERROR ;
  861. if (level.equalsIgnoreCase("WARNING"))
  862. return Logger.WARNING;
  863. if (level.equalsIgnoreCase("INFO"))
  864. return Logger.INFO;
  865. if (level.equalsIgnoreCase("DEBUG"))
  866. return Logger.DEBUG;
  867. if (level.equalsIgnoreCase("TRACE"))
  868. return Logger.TRACE;
  869. if (level.equalsIgnoreCase("ALL"))
  870. return Logger.ALL;
  871. // This error is NOT logged the normal way because the logger constructor calls getLogLevel() and if this error occurred it would cause
  872. // an infinite loop.
  873. logSpecial("The LOG-LEVEL property in the ESAPI properties file has the unrecognized value: " + level + ". Using default: WARNING", null);
  874. return Logger.WARNING; // Note: The default logging level is WARNING.
  875. }
  876. /**
  877. * {@inheritDoc}
  878. */
  879. public String getLogFileName() {
  880. return getESAPIProperty( LOG_FILE_NAME, "ESAPI_logging_file" );
  881. }
  882. /**
  883. * {@inheritDoc}
  884. */
  885. public int getMaxLogFileSize() {
  886. return getESAPIProperty( MAX_LOG_FILE_SIZE, DEFAULT_MAX_LOG_FILE_SIZE );
  887. }
  888. /**
  889. * {@inheritDoc}
  890. */
  891. public boolean getLogEncodingRequired() {
  892. return getESAPIProperty( LOG_ENCODING_REQUIRED, false );
  893. }
  894. /**
  895. * {@inheritDoc}
  896. */
  897. public boolean getLogApplicationName() {
  898. return getESAPIProperty( LOG_APPLICATION_NAME, true );
  899. }
  900. /**
  901. * {@inheritDoc}
  902. */
  903. public boolean getLogServerIP() {
  904. return getESAPIProperty( LOG_SERVER_IP, true );
  905. }
  906. /**
  907. * {@inheritDoc}
  908. */
  909. public boolean getForceHttpOnlySession() {
  910. return getESAPIProperty( FORCE_HTTPONLYSESSION, true );
  911. }
  912. /**
  913. * {@inheritDoc}
  914. */
  915. public boolean getForceSecureSession() {
  916. return getESAPIProperty( FORCE_SECURESESSION, true );
  917. }
  918. /**
  919. * {@inheritDoc}
  920. */
  921. public boolean getForceHttpOnlyCookies() {
  922. return getESAPIProperty( FORCE_HTTPONLYCOOKIES, true );
  923. }
  924. /**
  925. * {@inheritDoc}
  926. */
  927. public boolean getForceSecureCookies() {
  928. return getESAPIProperty( FORCE_SECURECOOKIES, true );
  929. }
  930. /**
  931. * {@inheritDoc}
  932. */
  933. public int getMaxHttpHeaderSize() {
  934. return getESAPIProperty( MAX_HTTP_HEADER_SIZE, 4096 );
  935. }
  936. /**
  937. * {@inheritDoc}
  938. */
  939. public String getResponseContentType() {
  940. return getESAPIProperty( RESPONSE_CONTENT_TYPE, "text/html; charset=UTF-8" );
  941. }
  942. /**
  943. * {@inheritDoc}
  944. */
  945. public String getHttpSessionIdName() {
  946. return getESAPIProperty( HTTP_SESSION_ID_NAME, "JSESSIONID" );
  947. }
  948. /**
  949. * {@inheritDoc}
  950. */
  951. public long getRememberTokenDuration() {
  952. int days = getESAPIProperty( REMEMBER_TOKEN_DURATION, 14 );
  953. return (long) (1000 * 60 * 60 * 24 * days);
  954. }
  955. /**
  956. * {@inheritDoc}
  957. */
  958. public int getSessionIdleTimeoutLength() {
  959. int minutes = getESAPIProperty( IDLE_TIMEOUT_DURATION, 20 );
  960. return 1000 * 60 * minutes;
  961. }
  962. /**
  963. * {@inheritDoc}
  964. */
  965. public int getSessionAbsoluteTimeoutLength() {
  966. int minutes = getESAPIProperty(ABSOLUTE_TIMEOUT_DURATION, 20 );
  967. return 1000 * 60 * minutes;
  968. }
  969. /**
  970. * getValidationPattern returns a single pattern based upon key
  971. *
  972. * @param key
  973. * validation pattern name you'd like
  974. * @return
  975. * if key exists, the associated validation pattern, null otherwise
  976. */
  977. public Pattern getValidationPattern( String key ) {
  978. String value = getESAPIProperty( "Validator." + key, "" );
  979. // check cache
  980. Pattern p = patternCache.get( value );
  981. if ( p != null ) return p;
  982. // compile a new pattern
  983. if ( value == null || value.equals( "" ) ) return null;
  984. try {
  985. Pattern q = Pattern.compile(value);
  986. patternCache.put( value, q );
  987. return q;
  988. } catch ( PatternSyntaxException e ) {
  989. logSpecial( "SecurityConfiguration for " + key + " not a valid regex in ESAPI.properties. Returning null", null );
  990. return null;
  991. }
  992. }
  993. /**
  994. * getWorkingDirectory returns the default directory where processes will be executed
  995. * by the Executor.
  996. */
  997. public File getWorkingDirectory() {
  998. String dir = getESAPIProperty( WORKING_DIRECTORY, System.getProperty( "user.dir") );
  999. if ( dir != null ) {
  1000. return new File( dir );
  1001. }
  1002. return null;
  1003. }
  1004. /**
  1005. * {@inheritDoc}
  1006. */
  1007. public String getPreferredJCEProvider() {
  1008. return properties.getProperty(PREFERRED_JCE_PROVIDER); // No default!
  1009. }
  1010. /**
  1011. * {@inheritDoc}
  1012. */
  1013. public List<String> getCombinedCipherModes()
  1014. {
  1015. List<String> empty = new ArrayList<String>(); // Default is empty list
  1016. return getESAPIProperty(COMBINED_CIPHER_MODES, empty);
  1017. }
  1018. /**
  1019. * {@inheritDoc}
  1020. */
  1021. public List<String> getAdditionalAllowedCipherModes()
  1022. {
  1023. List<String> empty = new ArrayList<String>(); // Default is empty list
  1024. return getESAPIProperty(ADDITIONAL_ALLOWED_CIPHER_MODES, empty);
  1025. }
  1026. /**
  1027. * {@inheritDoc}
  1028. */
  1029. public boolean getLenientDatesAccepted() {
  1030. return getESAPIProperty( ACCEPT_LENIENT_DATES, false);
  1031. }
  1032. protected String getESAPIProperty( String key, String def ) {
  1033. String value = properties.getProperty(key);
  1034. if ( value == null ) {
  1035. logSpecial( "SecurityConfiguration for " + key + " not found in ESAPI.properties. Using default: " + def, null );
  1036. return def;
  1037. }
  1038. return value;
  1039. }
  1040. protected boolean getESAPIProperty( String key, boolean def ) {
  1041. String property = properties.getProperty(key);
  1042. if ( property == null ) {
  1043. logSpecial( "SecurityConfiguration for " + key + " not found in ESAPI.properties. Using default: " + def, null );
  1044. return def;
  1045. }
  1046. if ( property.equalsIgnoreCase("true") || property.equalsIgnoreCase("yes" ) ) {
  1047. return true;
  1048. }
  1049. if ( property.equalsIgnoreCase("false") || property.equalsIgnoreCase( "no" ) ) {
  1050. return false;
  1051. }
  1052. logSpecial( "SecurityConfiguration for " + key + " not either \"true\" or \"false\" in ESAPI.properties. Using default: " + def, null );
  1053. return def;
  1054. }
  1055. protected byte[] getESAPIPropertyEncoded( String key, byte[] def ) {
  1056. String property = properties.getProperty(key);
  1057. if ( property == null ) {
  1058. logSpecial( "SecurityConfiguration for " + key + " not found in ESAPI.properties. Using default: " + def, null );
  1059. return def;
  1060. }
  1061. try {
  1062. return ESAPI.encoder().decodeFromBase64(property);
  1063. } catch( IOException e ) {
  1064. logSpecial( "SecurityConfiguration for " + key + " not properly Base64 encoded in ESAPI.properties. Using default: " + def, null );
  1065. return null;
  1066. }
  1067. }
  1068. protected int getESAPIProperty( String key, int def ) {
  1069. String property = properties.getProperty(key);
  1070. if ( property == null ) {
  1071. logSpecial( "SecurityConfiguration for " + key + " not found in ESAPI.properties. Using default: " + def, null );
  1072. return def;
  1073. }
  1074. try {
  1075. return Integer.parseInt( property );
  1076. } catch( NumberFormatException e ) {
  1077. logSpecial( "SecurityConfiguration for " + key + " not an integer in ESAPI.properties. Using default: " + def, null );
  1078. return def;
  1079. }
  1080. }
  1081. /**
  1082. * Returns a {@code List} representing the parsed, comma-separated property.
  1083. *
  1084. * @param key The specified property name
  1085. * @param def A default value for the property name to return if the property
  1086. * is not set.
  1087. * @return A list of strings.
  1088. */
  1089. protected List<String> getESAPIProperty( String key, List<String> def ) {
  1090. String property = properties.getProperty( key );
  1091. if ( property == null ) {
  1092. logSpecial( "SecurityConfiguration for " + key + " not found in ESAPI.properties. Using default: " + def, null );
  1093. return def;
  1094. }
  1095. String[] parts = property.split(",");
  1096. return Arrays.asList( parts );
  1097. }
  1098. protected boolean shouldPrintProperties() {
  1099. return getESAPIProperty(PRINT_PROPERTIES_WHEN_LOADED, false);
  1100. }
  1101. protected Properties getESAPIProperties() {
  1102. return properties;
  1103. }
  1104. }