Merge branch 'master' into swift_support

This commit is contained in:
bjiang
2016-08-12 16:35:12 -04:00
53 changed files with 1778 additions and 536 deletions

View File

@@ -175,7 +175,7 @@ public final class Downloader {
}
LOGGER.debug("Download of {} complete", url.toString());
} catch (IOException ex) {
checkForSslExceptionn(ex);
checkForCommonExceptionTypes(ex);
final String msg = format("Error saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n",
url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding);
throw new DownloadFailedException(msg, ex);
@@ -261,8 +261,9 @@ public final class Downloader {
} catch (URLConnectionFailureException ex) {
throw new DownloadFailedException(format("Error creating URL Connection for HTTP %s request.", httpMethod), ex);
} catch (IOException ex) {
checkForSslExceptionn(ex);
LOGGER.debug("IO Exception: " + ex.getMessage(), ex);
checkForCommonExceptionTypes(ex);
LOGGER.error("IO Exception: " + ex.getMessage());
LOGGER.debug("Exception details", ex);
if (ex.getCause() != null) {
LOGGER.debug("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause());
}
@@ -292,15 +293,21 @@ public final class Downloader {
/**
* Analyzes the IOException, logs the appropriate information for debugging
* purposes, and then throws a DownloadFailedException that wraps the IO
* Exception.
* Exception for common IO Exceptions. This is to provide additional details
* to assist in resolution of the exception.
*
* @param ex the original exception
* @throws DownloadFailedException a wrapper exception that contains the
* original exception as the cause
*/
protected static void checkForSslExceptionn(IOException ex) throws DownloadFailedException {
protected static void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException {
Throwable cause = ex;
while (cause != null) {
if (cause instanceof java.net.UnknownHostException) {
final String msg = String.format("Unable to resolve domain '%s'", cause.getMessage());
LOGGER.error(msg);
throw new DownloadFailedException(msg);
}
if (cause instanceof InvalidAlgorithmParameterException) {
final String keystore = System.getProperty("javax.net.ssl.keyStore");
final String version = System.getProperty("java.version");

View File

@@ -0,0 +1,385 @@
package org.owasp.dependencycheck.utils;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class is used to enable additional ciphers used by the SSL Socket. This
* is specifically because the NVD stopped supporting TLS 1.0 and Java 6 and 7
* clients by default were unable to connect to download the NVD data feeds.
*
* The following code was copied from
* http://stackoverflow.com/questions/1037590/which-cipher-suites-to-enable-for-ssl-socket/23365536#23365536
*
* @author <a href="http://stackoverflow.com/users/608639/jww">jww</a>
*/
public class SSLSocketFactoryEx extends SSLSocketFactory {
/**
* The Logger for use throughout the class.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(SSLSocketFactoryEx.class);
/**
* Constructs a new SSLSocketFactory.
*
* @throws NoSuchAlgorithmException thrown when an algorithm is not
* supported
* @throws KeyManagementException thrown if initialization fails
*/
public SSLSocketFactoryEx() throws NoSuchAlgorithmException, KeyManagementException {
initSSLSocketFactoryEx(null, null, null);
}
/**
* Constructs a new SSLSocketFactory.
*
* @param km the key manager
* @param tm the trust manager
* @param random secure random
* @throws NoSuchAlgorithmException thrown when an algorithm is not
* supported
* @throws KeyManagementException thrown if initialization fails
*/
public SSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException {
initSSLSocketFactoryEx(km, tm, random);
}
/**
* Constructs a new SSLSocketFactory.
*
* @param ctx the SSL context
* @throws NoSuchAlgorithmException thrown when an algorithm is not
* supported
* @throws KeyManagementException thrown if initialization fails
*/
public SSLSocketFactoryEx(SSLContext ctx) throws NoSuchAlgorithmException, KeyManagementException {
initSSLSocketFactoryEx(ctx);
}
/**
* Returns the default cipher suites.
*
* @return the default cipher suites
*/
@Override
public String[] getDefaultCipherSuites() {
return Arrays.copyOf(ciphers, ciphers.length);
}
/**
* Returns the supported cipher suites.
*
* @return the supported cipher suites
*/
@Override
public String[] getSupportedCipherSuites() {
return Arrays.copyOf(ciphers, ciphers.length);
}
/**
* Returns the default protocols.
*
* @return the default protocols
*/
public String[] getDefaultProtocols() {
return Arrays.copyOf(protocols, protocols.length);
}
/**
* Returns the supported protocols.
*
* @return the supported protocols
*/
public String[] getSupportedProtocols() {
return Arrays.copyOf(protocols, protocols.length);
}
/**
* Creates an SSL Socket.
*
* @param s the base socket
* @param host the host
* @param port the port
* @param autoClose if the socket should auto-close
* @return the SSL Socket
* @throws IOException thrown if the creation fails
*/
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
final SSLSocket ss = (SSLSocket) factory.createSocket(s, host, port, autoClose);
ss.setEnabledProtocols(protocols);
ss.setEnabledCipherSuites(ciphers);
return ss;
}
/**
* Creates a new SSL Socket.
*
* @param address the address to connect to
* @param port the port number
* @param localAddress the local address
* @param localPort the local port
* @return the SSL Socket
* @throws IOException thrown if the creation fails
*/
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort);
ss.setEnabledProtocols(protocols);
ss.setEnabledCipherSuites(ciphers);
return ss;
}
/**
* Creates a new SSL Socket.
*
* @param host the host to connect to
* @param port the port to connect to
* @param localHost the local host
* @param localPort the local port
* @return the SSL Socket
* @throws IOException thrown if the creation fails
*/
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort);
ss.setEnabledProtocols(protocols);
ss.setEnabledCipherSuites(ciphers);
return ss;
}
/**
* Creates a new SSL Socket.
*
* @param host the host to connect to
* @param port the port to connect to
* @return the SSL Socket
* @throws IOException thrown if the creation fails
*/
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
ss.setEnabledProtocols(protocols);
ss.setEnabledCipherSuites(ciphers);
return ss;
}
/**
* Creates a new SSL Socket.
*
* @param host the host to connect to
* @param port the port to connect to
* @return the SSL Socket
* @throws IOException thrown if the creation fails
*/
@Override
public Socket createSocket(String host, int port) throws IOException {
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
ss.setEnabledProtocols(protocols);
ss.setEnabledCipherSuites(ciphers);
return ss;
}
/**
* Initializes the SSL Socket Factory Extension.
*
* @param km the key managers
* @param tm the trust managers
* @param random the secure random number generator
* @throws NoSuchAlgorithmException thrown when an algorithm is not
* supported
* @throws KeyManagementException thrown if initialization fails
*/
private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random)
throws NoSuchAlgorithmException, KeyManagementException {
sslCtxt = SSLContext.getInstance("TLS");
sslCtxt.init(km, tm, random);
protocols = getProtocolList();
ciphers = getCipherList();
}
/**
* Initializes the SSL Socket Factory Extension.
*
* @param ctx the SSL context
* @throws NoSuchAlgorithmException thrown when an algorithm is not
* supported
* @throws KeyManagementException thrown if initialization fails
*/
private void initSSLSocketFactoryEx(SSLContext ctx)
throws NoSuchAlgorithmException, KeyManagementException {
sslCtxt = ctx;
protocols = getProtocolList();
ciphers = getCipherList();
}
/**
* Returns the protocol list.
*
* @return the protocol list
*/
protected String[] getProtocolList() {
final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
String[] availableProtocols = null;
SSLSocket socket = null;
try {
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
socket = (SSLSocket) factory.createSocket();
availableProtocols = socket.getSupportedProtocols();
Arrays.sort(availableProtocols);
} catch (Exception ex) {
LOGGER.debug("Error getting protocol list, using TLSv1", ex);
return new String[]{"TLSv1"};
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException ex) {
LOGGER.trace("Error closing socket", ex);
}
}
}
final List<String> aa = new ArrayList<String>();
for (String preferredProtocol : preferredProtocols) {
final int idx = Arrays.binarySearch(availableProtocols, preferredProtocol);
if (idx >= 0) {
aa.add(preferredProtocol);
}
}
return aa.toArray(new String[0]);
}
/**
* Returns the cipher list.
*
* @return the cipher list
*/
protected String[] getCipherList() {
final String[] preferredCiphers = {
// *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites.
// http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html
// Use them if available. Normative names can be found at (TLS spec depends on IPSec spec):
// http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-01
// http://tools.ietf.org/html/draft-mavrogiannopoulos-chacha-tls-02
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_SHA",
"TLS_ECDHE_RSA_WITH_CHACHA20_SHA",
"TLS_DHE_RSA_WITH_CHACHA20_POLY1305",
"TLS_RSA_WITH_CHACHA20_POLY1305",
"TLS_DHE_RSA_WITH_CHACHA20_SHA",
"TLS_RSA_WITH_CHACHA20_SHA",
// Done with bleeding edge, back to TLS v1.2 and below
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
// TLS v1.0 (with some SSLv3 interop)
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
"SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",
// RSA key transport sucks, but they are needed as a fallback.
// For example, microsoft.com fails under all versions of TLS
// if they are not included. If only TLS 1.0 is available at
// the client, then google.com will fail too. TLS v1.3 is
// trying to deprecate them, so it will be interesteng to see
// what happens.
"TLS_RSA_WITH_AES_256_CBC_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA256",
"TLS_RSA_WITH_AES_128_CBC_SHA",
};
String[] availableCiphers;
try {
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
availableCiphers = factory.getSupportedCipherSuites();
Arrays.sort(availableCiphers);
} catch (Exception e) {
LOGGER.debug("Error retrieving ciphers", e);
return new String[]{
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_256_CBC_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA256",
"TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
};
}
final List<String> aa = new ArrayList<String>();
for (String preferredCipher : preferredCiphers) {
final int idx = Arrays.binarySearch(availableCiphers, preferredCipher);
if (idx >= 0) {
aa.add(preferredCipher);
}
}
aa.add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
return aa.toArray(new String[0]);
}
/**
* The SSL context.
*/
private SSLContext sslCtxt;
/**
* The cipher suites.
*/
private String[] ciphers;
/**
* The protocols.
*/
private String[] protocols;
}

View File

@@ -46,7 +46,8 @@ public final class Settings {
public static final class KEYS {
/**
* private constructor because this is a "utility" class containing constants
* private constructor because this is a "utility" class containing
* constants
*/
private KEYS() {
//do nothing
@@ -54,29 +55,34 @@ public final class Settings {
/**
* The key to obtain the application name.
*/
public static final String APPLICATION_VAME = "application.name";
public static final String APPLICATION_NAME = "application.name";
/**
* The key to obtain the application version.
*/
public static final String APPLICATION_VERSION = "application.version";
/**
* The key to obtain the URL to retrieve the current release version from.
* The key to obtain the URL to retrieve the current release version
* from.
*/
public static final String ENGINE_VERSION_CHECK_URL = "engine.version.url";
/**
* The properties key indicating whether or not the cached data sources should be updated.
* The properties key indicating whether or not the cached data sources
* should be updated.
*/
public static final String AUTO_UPDATE = "autoupdate";
/**
* The database driver class name. If this is not in the properties file the embedded database is used.
* The database driver class name. If this is not in the properties file
* the embedded database is used.
*/
public static final String DB_DRIVER_NAME = "data.driver_name";
/**
* The database driver class name. If this is not in the properties file the embedded database is used.
* The database driver class name. If this is not in the properties file
* the embedded database is used.
*/
public static final String DB_DRIVER_PATH = "data.driver_path";
/**
* The database connection string. If this is not in the properties file the embedded database is used.
* The database connection string. If this is not in the properties file
* the embedded database is used.
*/
public static final String DB_CONNECTION_STRING = "data.connection_string";
/**
@@ -101,36 +107,41 @@ public final class Settings {
public static final String DB_VERSION = "data.version";
/**
* The starts with filter used to exclude CVE entries from the database.
* By default this is set to 'cpe:/a:' which limits the CVEs imported to
* just those that are related to applications. If this were set to just
* 'cpe:' the OS, hardware, and application related CVEs would be imported.
* By default this is set to 'cpe:/a:' which limits the CVEs imported to
* just those that are related to applications. If this were set to just
* 'cpe:' the OS, hardware, and application related CVEs would be
* imported.
*/
public static final String CVE_CPE_STARTS_WITH_FILTER = "cve.cpe.startswith.filter";
/**
* The properties key for the URL to retrieve the "meta" data from about the CVE entries.
* The properties key for the URL to retrieve the "meta" data from about
* the CVE entries.
*/
public static final String CVE_META_URL = "cve.url.meta";
/**
* The properties key for the URL to retrieve the recently modified and added CVE entries (last 8 days) using the 2.0
* schema.
* The properties key for the URL to retrieve the recently modified and
* added CVE entries (last 8 days) using the 2.0 schema.
*/
public static final String CVE_MODIFIED_20_URL = "cve.url-2.0.modified";
/**
* The properties key for the URL to retrieve the recently modified and added CVE entries (last 8 days) using the 1.2
* schema.
* The properties key for the URL to retrieve the recently modified and
* added CVE entries (last 8 days) using the 1.2 schema.
*/
public static final String CVE_MODIFIED_12_URL = "cve.url-1.2.modified";
/**
* The properties key for the URL to retrieve the recently modified and added CVE entries (last 8 days).
* The properties key for the URL to retrieve the recently modified and
* added CVE entries (last 8 days).
*/
public static final String CVE_MODIFIED_VALID_FOR_DAYS = "cve.url.modified.validfordays";
/**
* The properties key to control the skipping of the check for CVE updates.
* The properties key to control the skipping of the check for CVE
* updates.
*/
public static final String CVE_CHECK_VALID_FOR_HOURS = "cve.check.validforhours";
/**
* The properties key for the telling us how many cve.url.* URLs exists. This is used in combination with CVE_BASE_URL to
* be able to retrieve the URLs for all of the files that make up the NVD CVE listing.
* The properties key for the telling us how many cve.url.* URLs exists.
* This is used in combination with CVE_BASE_URL to be able to retrieve
* the URLs for all of the files that make up the NVD CVE listing.
*/
public static final String CVE_START_YEAR = "cve.startyear";
/**
@@ -142,7 +153,8 @@ public final class Settings {
*/
public static final String CVE_SCHEMA_2_0 = "cve.url-2.0.base";
/**
* The properties key that indicates how often the CPE data needs to be updated.
* The properties key that indicates how often the CPE data needs to be
* updated.
*/
public static final String CPE_MODIFIED_VALID_FOR_DAYS = "cpe.validfordays";
/**
@@ -152,7 +164,9 @@ public final class Settings {
/**
* The properties key for the proxy server.
*
* @deprecated use {@link org.owasp.dependencycheck.utils.Settings.KEYS#PROXY_SERVER} instead.
* @deprecated use
* {@link org.owasp.dependencycheck.utils.Settings.KEYS#PROXY_SERVER}
* instead.
*/
@Deprecated
public static final String PROXY_URL = "proxy.server";
@@ -161,7 +175,8 @@ public final class Settings {
*/
public static final String PROXY_SERVER = "proxy.server";
/**
* The properties key for the proxy port - this must be an integer value.
* The properties key for the proxy port - this must be an integer
* value.
*/
public static final String PROXY_PORT = "proxy.port";
/**
@@ -209,19 +224,23 @@ public final class Settings {
*/
public static final String ANALYZER_ARCHIVE_ENABLED = "analyzer.archive.enabled";
/**
* The properties key for whether the node.js package analyzer is enabled.
* The properties key for whether the node.js package analyzer is
* enabled.
*/
public static final String ANALYZER_NODE_PACKAGE_ENABLED = "analyzer.node.package.enabled";
/**
* The properties key for whether the composer lock file analyzer is enabled.
* The properties key for whether the composer lock file analyzer is
* enabled.
*/
public static final String ANALYZER_COMPOSER_LOCK_ENABLED = "analyzer.composer.lock.enabled";
/**
* The properties key for whether the Python Distribution analyzer is enabled.
* The properties key for whether the Python Distribution analyzer is
* enabled.
*/
public static final String ANALYZER_PYTHON_DISTRIBUTION_ENABLED = "analyzer.python.distribution.enabled";
/**
* The properties key for whether the Python Package analyzer is enabled.
* The properties key for whether the Python Package analyzer is
* enabled.
*/
public static final String ANALYZER_PYTHON_PACKAGE_ENABLED = "analyzer.python.package.enabled";
/**
@@ -237,7 +256,8 @@ public final class Settings {
*/
public static final String ANALYZER_CMAKE_ENABLED = "analyzer.cmake.enabled";
/**
* The properties key for whether the Ruby Bundler Audit analyzer is enabled.
* The properties key for whether the Ruby Bundler Audit analyzer is
* enabled.
*/
public static final String ANALYZER_BUNDLE_AUDIT_ENABLED = "analyzer.bundle.audit.enabled";
/**
@@ -339,7 +359,8 @@ public final class Settings {
private Properties props = null;
/**
* Private constructor for the Settings class. This class loads the properties files.
* Private constructor for the Settings class. This class loads the
* properties files.
*
* @param propertiesFilePath the path to the base properties file to load
*/
@@ -365,16 +386,18 @@ public final class Settings {
}
/**
* Initializes the thread local settings object. Note, to use the settings object you must call this method. However, you must
* also call Settings.cleanup() to properly release resources.
* Initializes the thread local settings object. Note, to use the settings
* object you must call this method. However, you must also call
* Settings.cleanup() to properly release resources.
*/
public static void initialize() {
LOCAL_SETTINGS.set(new Settings(PROPERTIES_FILE));
}
/**
* Initializes the thread local settings object. Note, to use the settings object you must call this method. However, you must
* also call Settings.cleanup() to properly release resources.
* Initializes the thread local settings object. Note, to use the settings
* object you must call this method. However, you must also call
* Settings.cleanup() to properly release resources.
*
* @param propertiesFilePath the path to the base properties file to load
*/
@@ -393,7 +416,8 @@ public final class Settings {
/**
* Cleans up resources to prevent memory leaks.
*
* @param deleteTemporary flag indicating whether any temporary directories generated should be removed
* @param deleteTemporary flag indicating whether any temporary directories
* generated should be removed
*/
public static void cleanup(boolean deleteTemporary) {
if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) {
@@ -433,7 +457,8 @@ public final class Settings {
}
/**
* Logs the properties. This will not log any properties that contain 'password' in the key.
* Logs the properties. This will not log any properties that contain
* 'password' in the key.
*
* @param header the header to print with the log message
* @param properties the properties to log
@@ -549,13 +574,16 @@ public final class Settings {
}
/**
* Merges a new properties file into the current properties. This method allows for the loading of a user provided properties
* file.<br><br>
* <b>Note</b>: even if using this method - system properties will be loaded before properties loaded from files.
* Merges a new properties file into the current properties. This method
* allows for the loading of a user provided properties file.<br><br>
* <b>Note</b>: even if using this method - system properties will be loaded
* before properties loaded from files.
*
* @param filePath the path to the properties file to merge.
* @throws FileNotFoundException is thrown when the filePath points to a non-existent file
* @throws IOException is thrown when there is an exception loading/merging the properties
* @throws FileNotFoundException is thrown when the filePath points to a
* non-existent file
* @throws IOException is thrown when there is an exception loading/merging
* the properties
*/
public static void mergeProperties(File filePath) throws FileNotFoundException, IOException {
FileInputStream fis = null;
@@ -574,13 +602,16 @@ public final class Settings {
}
/**
* Merges a new properties file into the current properties. This method allows for the loading of a user provided properties
* file.<br><br>
* Note: even if using this method - system properties will be loaded before properties loaded from files.
* Merges a new properties file into the current properties. This method
* allows for the loading of a user provided properties file.<br><br>
* Note: even if using this method - system properties will be loaded before
* properties loaded from files.
*
* @param filePath the path to the properties file to merge.
* @throws FileNotFoundException is thrown when the filePath points to a non-existent file
* @throws IOException is thrown when there is an exception loading/merging the properties
* @throws FileNotFoundException is thrown when the filePath points to a
* non-existent file
* @throws IOException is thrown when there is an exception loading/merging
* the properties
*/
public static void mergeProperties(String filePath) throws FileNotFoundException, IOException {
FileInputStream fis = null;
@@ -599,12 +630,14 @@ public final class Settings {
}
/**
* Merges a new properties file into the current properties. This method allows for the loading of a user provided properties
* file.<br><br>
* <b>Note</b>: even if using this method - system properties will be loaded before properties loaded from files.
* Merges a new properties file into the current properties. This method
* allows for the loading of a user provided properties file.<br><br>
* <b>Note</b>: even if using this method - system properties will be loaded
* before properties loaded from files.
*
* @param stream an Input Stream pointing at a properties file to merge
* @throws IOException is thrown when there is an exception loading/merging the properties
* @throws IOException is thrown when there is an exception loading/merging
* the properties
*/
public static void mergeProperties(InputStream stream) throws IOException {
LOCAL_SETTINGS.get().props.load(stream);
@@ -612,9 +645,10 @@ public final class Settings {
}
/**
* Returns a value from the properties file as a File object. If the value was specified as a system property or passed in via
* the -Dprop=value argument - this method will return the value from the system properties before the values in the contained
* configuration file.
* Returns a value from the properties file as a File object. If the value
* was specified as a system property or passed in via the -Dprop=value
* argument - this method will return the value from the system properties
* before the values in the contained configuration file.
*
* @param key the key to lookup within the properties file
* @return the property from the properties file converted to a File object
@@ -628,13 +662,15 @@ public final class Settings {
}
/**
* Returns a value from the properties file as a File object. If the value was specified as a system property or passed in via
* the -Dprop=value argument - this method will return the value from the system properties before the values in the contained
* configuration file.
* Returns a value from the properties file as a File object. If the value
* was specified as a system property or passed in via the -Dprop=value
* argument - this method will return the value from the system properties
* before the values in the contained configuration file.
*
* This method will check the configured base directory and will use this as the base of the file path. Additionally, if the
* base directory begins with a leading "[JAR]\" sequence with the path to the folder containing the JAR file containing this
* class.
* This method will check the configured base directory and will use this as
* the base of the file path. Additionally, if the base directory begins
* with a leading "[JAR]\" sequence with the path to the folder containing
* the JAR file containing this class.
*
* @param key the key to lookup within the properties file
* @return the property from the properties file converted to a File object
@@ -657,7 +693,8 @@ public final class Settings {
}
/**
* Attempts to retrieve the folder containing the Jar file containing the Settings class.
* Attempts to retrieve the folder containing the Jar file containing the
* Settings class.
*
* @return a File object
*/
@@ -679,9 +716,10 @@ public final class Settings {
}
/**
* Returns a value from the properties file. If the value was specified as a system property or passed in via the -Dprop=value
* argument - this method will return the value from the system properties before the values in the contained configuration
* file.
* Returns a value from the properties file. If the value was specified as a
* system property or passed in via the -Dprop=value argument - this method
* will return the value from the system properties before the values in the
* contained configuration file.
*
* @param key the key to lookup within the properties file
* @param defaultValue the default value for the requested property
@@ -693,7 +731,8 @@ public final class Settings {
}
/**
* A reference to the temporary directory; used incase it needs to be deleted during cleanup.
* A reference to the temporary directory; used incase it needs to be
* deleted during cleanup.
*/
private static File tempDirectory = null;
@@ -701,7 +740,8 @@ public final class Settings {
* Returns the temporary directory.
*
* @return the temporary directory
* @throws java.io.IOException thrown if the temporary directory does not exist and cannot be created
* @throws java.io.IOException thrown if the temporary directory does not
* exist and cannot be created
*/
public static File getTempDirectory() throws IOException {
final File tmpDir = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")), "dctemp");
@@ -714,9 +754,10 @@ public final class Settings {
}
/**
* Returns a value from the properties file. If the value was specified as a system property or passed in via the -Dprop=value
* argument - this method will return the value from the system properties before the values in the contained configuration
* file.
* Returns a value from the properties file. If the value was specified as a
* system property or passed in via the -Dprop=value argument - this method
* will return the value from the system properties before the values in the
* contained configuration file.
*
* @param key the key to lookup within the properties file
* @return the property from the properties file
@@ -726,7 +767,8 @@ public final class Settings {
}
/**
* Removes a property from the local properties collection. This is mainly used in test cases.
* Removes a property from the local properties collection. This is mainly
* used in test cases.
*
* @param key the property key to remove
*/
@@ -735,13 +777,15 @@ public final class Settings {
}
/**
* Returns an int value from the properties file. If the value was specified as a system property or passed in via the
* -Dprop=value argument - this method will return the value from the system properties before the values in the contained
* configuration file.
* Returns an int value from the properties file. If the value was specified
* as a system property or passed in via the -Dprop=value argument - this
* method will return the value from the system properties before the values
* in the contained configuration file.
*
* @param key the key to lookup within the properties file
* @return the property from the properties file
* @throws InvalidSettingException is thrown if there is an error retrieving the setting
* @throws InvalidSettingException is thrown if there is an error retrieving
* the setting
*/
public static int getInt(String key) throws InvalidSettingException {
try {
@@ -752,14 +796,15 @@ public final class Settings {
}
/**
* Returns an int value from the properties file. If the value was specified as a system property or passed in via the
* -Dprop=value argument - this method will return the value from the system properties before the values in the contained
* configuration file.
* Returns an int value from the properties file. If the value was specified
* as a system property or passed in via the -Dprop=value argument - this
* method will return the value from the system properties before the values
* in the contained configuration file.
*
* @param key the key to lookup within the properties file
* @param defaultValue the default value to return
* @return the property from the properties file or the defaultValue if the property does not exist or cannot be converted to
* an integer
* @return the property from the properties file or the defaultValue if the
* property does not exist or cannot be converted to an integer
*/
public static int getInt(String key, int defaultValue) {
int value;
@@ -775,13 +820,15 @@ public final class Settings {
}
/**
* Returns a long value from the properties file. If the value was specified as a system property or passed in via the
* -Dprop=value argument - this method will return the value from the system properties before the values in the contained
* configuration file.
* Returns a long value from the properties file. If the value was specified
* as a system property or passed in via the -Dprop=value argument - this
* method will return the value from the system properties before the values
* in the contained configuration file.
*
* @param key the key to lookup within the properties file
* @return the property from the properties file
* @throws InvalidSettingException is thrown if there is an error retrieving the setting
* @throws InvalidSettingException is thrown if there is an error retrieving
* the setting
*/
public static long getLong(String key) throws InvalidSettingException {
try {
@@ -792,38 +839,47 @@ public final class Settings {
}
/**
* Returns a boolean value from the properties file. If the value was specified as a system property or passed in via the
* <code>-Dprop=value</code> argument this method will return the value from the system properties before the values in the
* contained configuration file.
* Returns a boolean value from the properties file. If the value was
* specified as a system property or passed in via the
* <code>-Dprop=value</code> argument this method will return the value from
* the system properties before the values in the contained configuration
* file.
*
* @param key the key to lookup within the properties file
* @return the property from the properties file
* @throws InvalidSettingException is thrown if there is an error retrieving the setting
* @throws InvalidSettingException is thrown if there is an error retrieving
* the setting
*/
public static boolean getBoolean(String key) throws InvalidSettingException {
return Boolean.parseBoolean(Settings.getString(key));
}
/**
* Returns a boolean value from the properties file. If the value was specified as a system property or passed in via the
* <code>-Dprop=value</code> argument this method will return the value from the system properties before the values in the
* contained configuration file.
* Returns a boolean value from the properties file. If the value was
* specified as a system property or passed in via the
* <code>-Dprop=value</code> argument this method will return the value from
* the system properties before the values in the contained configuration
* file.
*
* @param key the key to lookup within the properties file
* @param defaultValue the default value to return if the setting does not exist
* @param defaultValue the default value to return if the setting does not
* exist
* @return the property from the properties file
* @throws InvalidSettingException is thrown if there is an error retrieving the setting
* @throws InvalidSettingException is thrown if there is an error retrieving
* the setting
*/
public static boolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException {
return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue)));
}
/**
* Returns a connection string from the configured properties. If the connection string contains a %s, this method will
* determine the 'data' directory and replace the %s with the path to the data directory. If the data directory does not
* exists it will be created.
* Returns a connection string from the configured properties. If the
* connection string contains a %s, this method will determine the 'data'
* directory and replace the %s with the path to the data directory. If the
* data directory does not exists it will be created.
*
* @param connectionStringKey the property file key for the connection string
* @param connectionStringKey the property file key for the connection
* string
* @param dbFileNameKey the settings key for the db filename
* @return the connection string
* @throws IOException thrown the data directory cannot be created
@@ -860,8 +916,9 @@ public final class Settings {
}
/**
* Retrieves the directory that the JAR file exists in so that we can ensure we always use a common data directory for the
* embedded H2 database. This is public solely for some unit tests; otherwise this should be private.
* Retrieves the directory that the JAR file exists in so that we can ensure
* we always use a common data directory for the embedded H2 database. This
* is public solely for some unit tests; otherwise this should be private.
*
* @return the data directory to store data files
* @throws IOException is thrown if an IOException occurs of course...

View File

@@ -28,15 +28,28 @@ import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.HttpsURLConnection;
import org.apache.commons.lang3.JavaVersion;
import org.apache.commons.lang3.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A URLConnection Factory to create new connections. This encapsulates several configuration checks to ensure that the connection
* uses the correct proxy settings.
* A URLConnection Factory to create new connections. This encapsulates several
* configuration checks to ensure that the connection uses the correct proxy
* settings.
*
* @author Jeremy Long
*/
public final class URLConnectionFactory {
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(URLConnectionFactory.class);
/**
* Private constructor for this factory.
*/
@@ -44,8 +57,9 @@ public final class URLConnectionFactory {
}
/**
* Utility method to create an HttpURLConnection. If the application is configured to use a proxy this method will retrieve
* the proxy settings and use them when setting up the connection.
* Utility method to create an HttpURLConnection. If the application is
* configured to use a proxy this method will retrieve the proxy settings
* and use them when setting up the connection.
*
* @param url the url to connect to
* @return an HttpURLConnection
@@ -95,6 +109,7 @@ public final class URLConnectionFactory {
}
throw new URLConnectionFailureException("Error getting connection.", ex);
}
configureTLS(url, conn);
return conn;
}
@@ -140,8 +155,10 @@ public final class URLConnectionFactory {
}
/**
* Utility method to create an HttpURLConnection. The use of a proxy here is optional as there may be cases where a proxy is
* configured but we don't want to use it (for example, if there's an internal repository configured)
* Utility method to create an HttpURLConnection. The use of a proxy here is
* optional as there may be cases where a proxy is configured but we don't
* want to use it (for example, if there's an internal repository
* configured)
*
* @param url the URL to connect to
* @param proxy whether to use the proxy (if configured)
@@ -161,6 +178,29 @@ public final class URLConnectionFactory {
} catch (IOException ioe) {
throw new URLConnectionFailureException("Error getting connection.", ioe);
}
configureTLS(url, conn);
return conn;
}
/**
* If the protocol is HTTPS, this will configure the cipher suites so that
* connections can be made to the NVD, and others, using older versions of
* Java.
*
* @param url the URL
* @param conn the connection
*/
private static void configureTLS(URL url, HttpURLConnection conn) {
if ("https".equals(url.getProtocol()) && !SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8)) {
try {
final HttpsURLConnection secCon = (HttpsURLConnection) conn;
final SSLSocketFactoryEx factory = new SSLSocketFactoryEx();
secCon.setSSLSocketFactory(factory);
} catch (NoSuchAlgorithmException ex) {
LOGGER.debug("Unsupported algorithm in SSLSocketFactoryEx", ex);
} catch (KeyManagementException ex) {
LOGGER.debug("Key mnagement eception in SSLSocketFactoryEx", ex);
}
}
}
}