mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-15 16:23:37 +01:00
renamed modules and fixed errors with various lifecycle stages
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Includes methods to generate the MD5 and SHA1 checksum.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*
|
||||
*/
|
||||
public final class Checksum {
|
||||
|
||||
/**
|
||||
* Hex code characters used in getHex.
|
||||
*/
|
||||
private static final String HEXES = "0123456789abcdef";
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Checksum.class);
|
||||
|
||||
/**
|
||||
* Private constructor for a utility class.
|
||||
*/
|
||||
private Checksum() {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Creates the cryptographic checksum of a given file using the specified
|
||||
* algorithm.</p>
|
||||
*
|
||||
* @param algorithm the algorithm to use to calculate the checksum
|
||||
* @param file the file to calculate the checksum for
|
||||
* @return the checksum
|
||||
* @throws IOException when the file does not exist
|
||||
* @throws NoSuchAlgorithmException when an algorithm is specified that does
|
||||
* not exist
|
||||
*/
|
||||
public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException {
|
||||
final MessageDigest md = MessageDigest.getInstance(algorithm);
|
||||
try (FileInputStream fis = new FileInputStream(file);
|
||||
FileChannel ch = fis.getChannel()) {
|
||||
final ByteBuffer buf = ByteBuffer.allocateDirect(8192);
|
||||
int b = ch.read(buf);
|
||||
while (b != -1 && b != 0) {
|
||||
buf.flip();
|
||||
final byte[] bytes = new byte[b];
|
||||
buf.get(bytes);
|
||||
md.update(bytes, 0, b);
|
||||
buf.clear();
|
||||
b = ch.read(buf);
|
||||
}
|
||||
return md.digest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the MD5 checksum of a specified file.
|
||||
*
|
||||
* @param file the file to generate the MD5 checksum
|
||||
* @return the hex representation of the MD5 hash
|
||||
* @throws IOException when the file passed in does not exist
|
||||
* @throws NoSuchAlgorithmException when the MD5 algorithm is not available
|
||||
*/
|
||||
public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException {
|
||||
final byte[] b = getChecksum("MD5", file);
|
||||
return getHex(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the SHA1 checksum of a specified file.
|
||||
*
|
||||
* @param file the file to generate the MD5 checksum
|
||||
* @return the hex representation of the SHA1 hash
|
||||
* @throws IOException when the file passed in does not exist
|
||||
* @throws NoSuchAlgorithmException when the SHA1 algorithm is not available
|
||||
*/
|
||||
public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException {
|
||||
final byte[] b = getChecksum("SHA1", file);
|
||||
return getHex(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the MD5 checksum of a specified bytes.
|
||||
*
|
||||
* @param algorithm the algorithm to use (md5, sha1, etc.) to calculate the
|
||||
* message digest
|
||||
* @param bytes the bytes to generate the MD5 checksum
|
||||
* @return the hex representation of the MD5 hash
|
||||
*/
|
||||
public static String getChecksum(String algorithm, byte[] bytes) {
|
||||
MessageDigest digest = getMessageDigest(algorithm);
|
||||
final byte[] b = digest.digest(bytes);
|
||||
return getHex(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the MD5 checksum of the specified text.
|
||||
*
|
||||
* @param text the text to generate the MD5 checksum
|
||||
* @return the hex representation of the MD5
|
||||
*/
|
||||
public static String getMD5Checksum(String text) {
|
||||
final byte[] data = stringToBytes(text);
|
||||
return getChecksum("MD5", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the SHA1 checksum of the specified text.
|
||||
*
|
||||
* @param text the text to generate the SHA1 checksum
|
||||
* @return the hex representation of the SHA1
|
||||
*/
|
||||
public static String getSHA1Checksum(String text) {
|
||||
final byte[] data = stringToBytes(text);
|
||||
return getChecksum("SHA1", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given text into bytes.
|
||||
*
|
||||
* @param text the text to convert
|
||||
* @return the bytes
|
||||
*/
|
||||
private static byte[] stringToBytes(String text) {
|
||||
byte[] data;
|
||||
try {
|
||||
data = text.getBytes(Charset.forName("UTF-8"));
|
||||
} catch (UnsupportedCharsetException ex) {
|
||||
data = text.getBytes(Charset.defaultCharset());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Converts a byte array into a hex string.</p>
|
||||
*
|
||||
* <p>
|
||||
* This method was copied from <a
|
||||
* href="http://www.rgagnon.com/javadetails/java-0596.html">http://www.rgagnon.com/javadetails/java-0596.html</a></p>
|
||||
*
|
||||
* @param raw a byte array
|
||||
* @return the hex representation of the byte array
|
||||
*/
|
||||
public static String getHex(byte[] raw) {
|
||||
if (raw == null) {
|
||||
return null;
|
||||
}
|
||||
final StringBuilder hex = new StringBuilder(2 * raw.length);
|
||||
for (final byte b : raw) {
|
||||
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt(b & 0x0F));
|
||||
}
|
||||
return hex.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message digest.
|
||||
*
|
||||
* @param algorithm the algorithm for the message digest
|
||||
* @return the message digest
|
||||
*/
|
||||
private static MessageDigest getMessageDigest(String algorithm) {
|
||||
try {
|
||||
return MessageDigest.getInstance(algorithm);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
final String msg = String.format("Failed to obtain the %s message digest.", algorithm);
|
||||
throw new IllegalStateException(msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An exception used when a download fails.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class DownloadFailedException extends IOException {
|
||||
|
||||
/**
|
||||
* The serial version UID.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new DownloadFailedException.
|
||||
*/
|
||||
public DownloadFailedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DownloadFailedException.
|
||||
*
|
||||
* @param msg a message for the exception.
|
||||
*/
|
||||
public DownloadFailedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DownloadFailedException.
|
||||
*
|
||||
* @param ex the cause of the download failure.
|
||||
*/
|
||||
public DownloadFailedException(Throwable ex) {
|
||||
super(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DownloadFailedException.
|
||||
*
|
||||
* @param msg a message for the exception.
|
||||
* @param ex the cause of the download failure.
|
||||
*/
|
||||
public DownloadFailedException(String msg, Throwable ex) {
|
||||
super(msg, ex);
|
||||
}
|
||||
}
|
||||
368
utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java
Executable file
368
utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java
Executable file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
import static java.lang.String.format;
|
||||
|
||||
/**
|
||||
* A utility to download files from the Internet.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public final class Downloader {
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Downloader.class);
|
||||
/**
|
||||
* The maximum number of redirects that will be followed when attempting to
|
||||
* download a file.
|
||||
*/
|
||||
private static final int MAX_REDIRECT_ATTEMPTS = 5;
|
||||
|
||||
/**
|
||||
* The default HTTP request method for query timestamp
|
||||
*/
|
||||
private static final String HEAD = "HEAD";
|
||||
|
||||
/**
|
||||
* The HTTP request method which can be used by query timestamp
|
||||
*/
|
||||
private static final String GET = "GET";
|
||||
|
||||
/**
|
||||
* The configured settings.
|
||||
*/
|
||||
private final Settings settings;
|
||||
|
||||
/**
|
||||
* The URL connection facctory.
|
||||
*/
|
||||
private final URLConnectionFactory connFactory;
|
||||
|
||||
/**
|
||||
* Constructs a new downloader object.
|
||||
*
|
||||
* @param settings the configured settings
|
||||
*/
|
||||
public Downloader(Settings settings) {
|
||||
this.settings = settings;
|
||||
this.connFactory = new URLConnectionFactory(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a file from a given URL and saves it to the outputPath.
|
||||
*
|
||||
* @param url the URL of the file to download
|
||||
* @param outputPath the path to the save the file to
|
||||
* @throws DownloadFailedException is thrown if there is an error
|
||||
* downloading the file
|
||||
*/
|
||||
public void fetchFile(URL url, File outputPath) throws DownloadFailedException {
|
||||
fetchFile(url, outputPath, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a file from a given URL and saves it to the outputPath.
|
||||
*
|
||||
* @param url the URL of the file to download
|
||||
* @param outputPath the path to the save the file to
|
||||
* @param useProxy whether to use the configured proxy when downloading
|
||||
* files
|
||||
* @throws DownloadFailedException is thrown if there is an error
|
||||
* downloading the file
|
||||
*/
|
||||
public void fetchFile(URL url, File outputPath, boolean useProxy) throws DownloadFailedException {
|
||||
if ("file".equalsIgnoreCase(url.getProtocol())) {
|
||||
File file;
|
||||
try {
|
||||
file = new File(url.toURI());
|
||||
} catch (URISyntaxException ex) {
|
||||
final String msg = format("Download failed, unable to locate '%s'", url.toString());
|
||||
throw new DownloadFailedException(msg);
|
||||
}
|
||||
if (file.exists()) {
|
||||
try {
|
||||
org.apache.commons.io.FileUtils.copyFile(file, outputPath);
|
||||
} catch (IOException ex) {
|
||||
final String msg = format("Download failed, unable to copy '%s' to '%s'", url.toString(), outputPath.getAbsolutePath());
|
||||
throw new DownloadFailedException(msg, ex);
|
||||
}
|
||||
} else {
|
||||
final String msg = format("Download failed, file ('%s') does not exist", url.toString());
|
||||
throw new DownloadFailedException(msg);
|
||||
}
|
||||
} else {
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
LOGGER.debug("Attempting download of {}", url.toString());
|
||||
conn = connFactory.createHttpURLConnection(url, useProxy);
|
||||
conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
|
||||
conn.connect();
|
||||
int status = conn.getResponseCode();
|
||||
int redirectCount = 0;
|
||||
while ((status == HttpURLConnection.HTTP_MOVED_TEMP
|
||||
|| status == HttpURLConnection.HTTP_MOVED_PERM
|
||||
|| status == HttpURLConnection.HTTP_SEE_OTHER)
|
||||
&& MAX_REDIRECT_ATTEMPTS > redirectCount++) {
|
||||
final String location = conn.getHeaderField("Location");
|
||||
try {
|
||||
conn.disconnect();
|
||||
} finally {
|
||||
conn = null;
|
||||
}
|
||||
LOGGER.debug("Download is being redirected from {} to {}", url.toString(), location);
|
||||
conn = connFactory.createHttpURLConnection(new URL(location), useProxy);
|
||||
conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
|
||||
conn.connect();
|
||||
status = conn.getResponseCode();
|
||||
}
|
||||
if (status != 200) {
|
||||
try {
|
||||
conn.disconnect();
|
||||
} finally {
|
||||
conn = null;
|
||||
}
|
||||
final String msg = format("Error downloading file %s; received response code %s.", url.toString(), status);
|
||||
throw new DownloadFailedException(msg);
|
||||
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
try {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
} finally {
|
||||
conn = null;
|
||||
}
|
||||
if ("Connection reset".equalsIgnoreCase(ex.getMessage())) {
|
||||
final String msg = format("TLS Connection Reset%nPlease see "
|
||||
+ "http://jeremylong.github.io/DependencyCheck/data/tlsfailure.html "
|
||||
+ "for more information regarding how to resolve the issue.");
|
||||
LOGGER.error(msg);
|
||||
throw new DownloadFailedException(msg, ex);
|
||||
}
|
||||
final String msg = format("Error downloading file %s; unable to connect.", url.toString());
|
||||
throw new DownloadFailedException(msg, ex);
|
||||
}
|
||||
|
||||
final String encoding = conn.getContentEncoding();
|
||||
InputStream reader = null;
|
||||
try (OutputStream out = new FileOutputStream(outputPath);
|
||||
BufferedOutputStream writer = new BufferedOutputStream(out)) {
|
||||
if (encoding != null && "gzip".equalsIgnoreCase(encoding)) {
|
||||
reader = new GZIPInputStream(conn.getInputStream());
|
||||
} else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) {
|
||||
reader = new InflaterInputStream(conn.getInputStream());
|
||||
} else {
|
||||
reader = conn.getInputStream();
|
||||
}
|
||||
|
||||
final byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = reader.read(buffer)) > 0) {
|
||||
writer.write(buffer, 0, bytesRead);
|
||||
}
|
||||
LOGGER.debug("Download of {} complete", url.toString());
|
||||
} catch (IOException 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);
|
||||
} catch (Exception ex) {
|
||||
final String msg = format("Unexpected exception saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n",
|
||||
url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding);
|
||||
throw new DownloadFailedException(msg, ex);
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException ex) {
|
||||
LOGGER.trace("Error closing the reader in Downloader.", ex);
|
||||
}
|
||||
}
|
||||
try {
|
||||
conn.disconnect();
|
||||
} finally {
|
||||
conn = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an HTTP Head request to retrieve the last modified date of the
|
||||
* given URL. If the file:// protocol is specified, then the lastTimestamp
|
||||
* of the file is returned.
|
||||
*
|
||||
* @param url the URL to retrieve the timestamp from
|
||||
* @return an epoch timestamp
|
||||
* @throws DownloadFailedException is thrown if an exception occurs making
|
||||
* the HTTP request
|
||||
*/
|
||||
public long getLastModified(URL url) throws DownloadFailedException {
|
||||
return getLastModified(url, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an HTTP Head request to retrieve the last modified date of the
|
||||
* given URL. If the file:// protocol is specified, then the lastTimestamp
|
||||
* of the file is returned.
|
||||
*
|
||||
* @param url the URL to retrieve the timestamp from
|
||||
* @param isRetry indicates if this is a retry - to prevent endless loop and
|
||||
* stack overflow
|
||||
* @return an epoch timestamp
|
||||
* @throws DownloadFailedException is thrown if an exception occurs making
|
||||
* the HTTP request
|
||||
*/
|
||||
private long getLastModified(URL url, boolean isRetry) throws DownloadFailedException {
|
||||
long timestamp = 0;
|
||||
//TODO add the FTP protocol?
|
||||
if ("file".equalsIgnoreCase(url.getProtocol())) {
|
||||
File lastModifiedFile;
|
||||
try {
|
||||
lastModifiedFile = new File(url.toURI());
|
||||
} catch (URISyntaxException ex) {
|
||||
final String msg = format("Unable to locate '%s'", url.toString());
|
||||
throw new DownloadFailedException(msg, ex);
|
||||
}
|
||||
timestamp = lastModifiedFile.lastModified();
|
||||
} else {
|
||||
final String httpMethod = determineHttpMethod();
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
conn = connFactory.createHttpURLConnection(url);
|
||||
conn.setRequestMethod(httpMethod);
|
||||
conn.connect();
|
||||
final int t = conn.getResponseCode();
|
||||
if (t >= 200 && t < 300) {
|
||||
timestamp = conn.getLastModified();
|
||||
} else {
|
||||
throw new DownloadFailedException(format("%s request returned a non-200 status code", httpMethod));
|
||||
}
|
||||
} catch (URLConnectionFailureException ex) {
|
||||
throw new DownloadFailedException(format("Error creating URL Connection for HTTP %s request.", httpMethod), ex);
|
||||
} catch (IOException 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());
|
||||
}
|
||||
try {
|
||||
//retry
|
||||
if (!isRetry && settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP)) {
|
||||
settings.setBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, false);
|
||||
return getLastModified(url, true);
|
||||
}
|
||||
} catch (InvalidSettingException ex1) {
|
||||
LOGGER.debug("invalid setting?", ex1);
|
||||
}
|
||||
throw new DownloadFailedException(format("Error making HTTP %s request.", httpMethod), ex);
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.disconnect();
|
||||
} finally {
|
||||
conn = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes the IOException, logs the appropriate information for debugging
|
||||
* purposes, and then throws a DownloadFailedException that wraps the IO
|
||||
* 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 synchronized void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException {
|
||||
Throwable cause = ex;
|
||||
while (cause != null) {
|
||||
if (cause instanceof java.net.UnknownHostException) {
|
||||
final String msg = 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");
|
||||
final String vendor = System.getProperty("java.vendor");
|
||||
LOGGER.info("Error making HTTPS request - InvalidAlgorithmParameterException");
|
||||
LOGGER.info("There appears to be an issue with the installation of Java and the cacerts."
|
||||
+ "See closed issue #177 here: https://github.com/jeremylong/DependencyCheck/issues/177");
|
||||
LOGGER.info("Java Info:\njavax.net.ssl.keyStore='{}'\njava.version='{}'\njava.vendor='{}'",
|
||||
keystore, version, vendor);
|
||||
throw new DownloadFailedException("Error making HTTPS request. Please see the log for more details.");
|
||||
}
|
||||
cause = cause.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HEAD or GET HTTP method. HEAD is the default.
|
||||
*
|
||||
* @return the HTTP method to use
|
||||
*/
|
||||
private String determineHttpMethod() {
|
||||
return isQuickQuery() ? HEAD : GET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the HTTP method GET or HEAD should be used to check the
|
||||
* timestamp on external resources.
|
||||
*
|
||||
* @return true if configured to use HEAD requests
|
||||
*/
|
||||
private boolean isQuickQuery() {
|
||||
boolean quickQuery;
|
||||
|
||||
try {
|
||||
quickQuery = settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, true);
|
||||
} catch (InvalidSettingException e) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Invalid settings : {}", e.getMessage(), e);
|
||||
}
|
||||
quickQuery = true;
|
||||
}
|
||||
return quickQuery;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2016 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InvalidClassException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
/**
|
||||
* An ObjectInputStream that will only deserialize expected classes.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class ExpectedObjectInputStream extends ObjectInputStream {
|
||||
|
||||
/**
|
||||
* The list of fully qualified class names that are able to be deserialized.
|
||||
*/
|
||||
private final List<String> expected = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs a new ExpectedOjectInputStream that can be used to securely deserialize an object by restricting the classes
|
||||
* that can deserialized to a known set of expected classes.
|
||||
*
|
||||
* @param inputStream the input stream that contains the object to deserialize
|
||||
* @param expected the fully qualified class names of the classes that can be deserialized
|
||||
* @throws IOException thrown if there is an error reading from the stream
|
||||
*/
|
||||
public ExpectedObjectInputStream(InputStream inputStream, String... expected) throws IOException {
|
||||
super(inputStream);
|
||||
this.expected.addAll(Arrays.asList(expected));
|
||||
}
|
||||
|
||||
/**
|
||||
* Only deserialize instances of expected classes by validating the class name prior to deserialization.
|
||||
*
|
||||
* @param desc the class from the object stream to validate
|
||||
* @return the resolved class
|
||||
* @throws java.io.IOException thrown if the class being read is not one of the expected classes or if there is an error
|
||||
* reading from the stream
|
||||
* @throws java.lang.ClassNotFoundException thrown if there is an error finding the class to deserialize
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
|
||||
if (!this.expected.contains(desc.getName())) {
|
||||
throw new InvalidClassException("Unexpected deserialization ", desc.getName());
|
||||
}
|
||||
return super.resolveClass(desc);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An exception used when a file is unable to be un-zipped.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class ExtractionException extends IOException {
|
||||
|
||||
/**
|
||||
* The serial version UID.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new ExtractionException.
|
||||
*/
|
||||
public ExtractionException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ExtractionException.
|
||||
*
|
||||
* @param msg a message for the exception.
|
||||
*/
|
||||
public ExtractionException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ExtractionException.
|
||||
*
|
||||
* @param ex the cause of the download failure.
|
||||
*/
|
||||
public ExtractionException(Throwable ex) {
|
||||
super(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ExtractionException.
|
||||
*
|
||||
* @param msg a message for the exception.
|
||||
* @param ex the cause of the download failure.
|
||||
*/
|
||||
public ExtractionException(String msg, Throwable ex) {
|
||||
super(msg, ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.Closeable;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.UUID;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
/**
|
||||
* A collection of utilities for processing information about files.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public final class FileUtils {
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);
|
||||
/**
|
||||
* Bit bucket for non-Windows systems
|
||||
*/
|
||||
private static final String BIT_BUCKET_UNIX = "/dev/null";
|
||||
|
||||
/**
|
||||
* Bit bucket for Windows systems (yes, only one 'L')
|
||||
*/
|
||||
private static final String BIT_BUCKET_WIN = "NUL";
|
||||
|
||||
/**
|
||||
* Private constructor for a utility class.
|
||||
*/
|
||||
private FileUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (lowercase) file extension for a specified file.
|
||||
*
|
||||
* @param fileName the file name to retrieve the file extension from.
|
||||
* @return the file extension.
|
||||
*/
|
||||
public static String getFileExtension(String fileName) {
|
||||
final String fileExt = FilenameUtils.getExtension(fileName);
|
||||
return null == fileExt || fileExt.isEmpty() ? null : fileExt.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a file. If the File is a directory it will recursively delete the
|
||||
* contents.
|
||||
*
|
||||
* @param file the File to delete
|
||||
* @return true if the file was deleted successfully, otherwise false
|
||||
*/
|
||||
public static boolean delete(File file) {
|
||||
final boolean success = org.apache.commons.io.FileUtils.deleteQuietly(file);
|
||||
if (!success) {
|
||||
LOGGER.debug("Failed to delete file: {}; attempting to delete on exit.", file.getPath());
|
||||
file.deleteOnExit();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unique temporary directory in the given directory.
|
||||
*
|
||||
* @param base the base directory to create a temporary directory within
|
||||
* @return the temporary directory
|
||||
* @throws IOException thrown when a directory cannot be created within the
|
||||
* base directory
|
||||
*/
|
||||
public static File createTempDirectory(File base) throws IOException {
|
||||
final File tempDir = new File(base, "dctemp" + UUID.randomUUID().toString());
|
||||
if (tempDir.exists()) {
|
||||
return createTempDirectory(base);
|
||||
}
|
||||
if (!tempDir.mkdirs()) {
|
||||
throw new IOException("Could not create temp directory `" + tempDir.getAbsolutePath() + "`");
|
||||
}
|
||||
LOGGER.debug("Temporary directory is `{}`", tempDir.getAbsolutePath());
|
||||
return tempDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for
|
||||
* Windows
|
||||
*
|
||||
* @return a String containing the bit bucket
|
||||
*/
|
||||
public static String getBitBucket() {
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
return BIT_BUCKET_WIN;
|
||||
} else {
|
||||
return BIT_BUCKET_UNIX;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given {@link Closeable} instance, ignoring nulls, and logging
|
||||
* any thrown {@link IOException}.
|
||||
*
|
||||
* @param closeable to be closed
|
||||
*/
|
||||
public static void close(Closeable closeable) {
|
||||
if (null != closeable) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (IOException ex) {
|
||||
LOGGER.trace("", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link InputStream} for this resource.
|
||||
*
|
||||
* @param resource path
|
||||
* @return the input stream for the given resource
|
||||
*/
|
||||
public static InputStream getResourceAsStream(String resource) {
|
||||
return FileUtils.class.getClassLoader() != null
|
||||
? FileUtils.class.getClassLoader().getResourceAsStream(resource)
|
||||
: ClassLoader.getSystemResourceAsStream(resource);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An exception used when an error occurs reading a setting.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class InvalidSettingException extends IOException {
|
||||
|
||||
/**
|
||||
* The serial version UID.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new InvalidSettingException.
|
||||
*/
|
||||
public InvalidSettingException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new InvalidSettingException.
|
||||
*
|
||||
* @param msg a message for the exception.
|
||||
*/
|
||||
public InvalidSettingException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new InvalidSettingException.
|
||||
*
|
||||
* @param ex the cause of the setting exception.
|
||||
*/
|
||||
public InvalidSettingException(Throwable ex) {
|
||||
super(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new InvalidSettingException.
|
||||
*
|
||||
* @param msg a message for the exception.
|
||||
* @param ex the cause of the setting exception.
|
||||
*/
|
||||
public InvalidSettingException(String msg, Throwable ex) {
|
||||
super(msg, ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
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);
|
||||
|
||||
/**
|
||||
* The SSL context.
|
||||
*/
|
||||
private SSLContext sslCtxt;
|
||||
/**
|
||||
* The protocols.
|
||||
*/
|
||||
private String[] protocols;
|
||||
/**
|
||||
* The configured settings.
|
||||
*/
|
||||
private final Settings settings;
|
||||
|
||||
/**
|
||||
* Constructs a new SSLSocketFactory.
|
||||
*
|
||||
* @param settings reference to the configured settings
|
||||
* @throws NoSuchAlgorithmException thrown when an algorithm is not
|
||||
* supported
|
||||
* @throws KeyManagementException thrown if initialization fails
|
||||
*/
|
||||
public SSLSocketFactoryEx(Settings settings) throws NoSuchAlgorithmException, KeyManagementException {
|
||||
this.settings = settings;
|
||||
initSSLSocketFactoryEx(null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new SSLSocketFactory.
|
||||
*
|
||||
* @param km the key manager
|
||||
* @param tm the trust manager
|
||||
* @param random secure random
|
||||
* @param settings reference to the configured settings
|
||||
* @throws NoSuchAlgorithmException thrown when an algorithm is not
|
||||
* supported
|
||||
* @throws KeyManagementException thrown if initialization fails
|
||||
*/
|
||||
public SSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random, Settings settings)
|
||||
throws NoSuchAlgorithmException, KeyManagementException {
|
||||
this.settings = settings;
|
||||
initSSLSocketFactoryEx(km, tm, random);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new SSLSocketFactory.
|
||||
*
|
||||
* @param ctx the SSL context
|
||||
* @param settings reference to the configured settings
|
||||
* @throws NoSuchAlgorithmException thrown when an algorithm is not
|
||||
* supported
|
||||
* @throws KeyManagementException thrown if initialization fails
|
||||
*/
|
||||
public SSLSocketFactoryEx(SSLContext ctx, Settings settings) throws NoSuchAlgorithmException, KeyManagementException {
|
||||
this.settings = settings;
|
||||
initSSLSocketFactoryEx(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default cipher suites.
|
||||
*
|
||||
* @return the default cipher suites
|
||||
*/
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return sslCtxt.getSocketFactory().getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the supported cipher suites.
|
||||
*
|
||||
* @return the supported cipher suites
|
||||
*/
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return sslCtxt.getSocketFactory().getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol list.
|
||||
*
|
||||
* @return the protocol list
|
||||
*/
|
||||
protected String[] getProtocolList() {
|
||||
SSLSocket socket = null;
|
||||
String[] availableProtocols = null;
|
||||
final String[] preferredProtocols = settings.getString(
|
||||
Settings.KEYS.DOWNLOADER_TLS_PROTOCOL_LIST,
|
||||
"TLSv1,TLSv1.1,TLSv1.2,TLSv1.3")
|
||||
.split(",");
|
||||
try {
|
||||
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
|
||||
socket = (SSLSocket) factory.createSocket();
|
||||
|
||||
availableProtocols = socket.getSupportedProtocols();
|
||||
Arrays.sort(availableProtocols);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Available Protocols:");
|
||||
for (String p : availableProtocols) {
|
||||
LOGGER.debug(p);
|
||||
}
|
||||
}
|
||||
} 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<>();
|
||||
for (String preferredProtocol : preferredProtocols) {
|
||||
final int idx = Arrays.binarySearch(availableProtocols, preferredProtocol);
|
||||
if (idx >= 0) {
|
||||
aa.add(preferredProtocol);
|
||||
}
|
||||
}
|
||||
|
||||
return aa.toArray(new String[0]);
|
||||
}
|
||||
}
|
||||
1024
utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java
Normal file
1024
utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Authenticator;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.Proxy;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
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.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public final class URLConnectionFactory {
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(URLConnectionFactory.class);
|
||||
/**
|
||||
* The configured settings.
|
||||
*/
|
||||
private final Settings settings;
|
||||
|
||||
/**
|
||||
* Private constructor for this factory.
|
||||
*
|
||||
* @param settings reference to the configured settings
|
||||
*/
|
||||
public URLConnectionFactory(Settings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @throws URLConnectionFailureException thrown if there is an exception
|
||||
*/
|
||||
@SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE", justification = "Just being extra safe")
|
||||
public HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException {
|
||||
HttpURLConnection conn = null;
|
||||
final String proxyHost = settings.getString(Settings.KEYS.PROXY_SERVER);
|
||||
|
||||
try {
|
||||
if (proxyHost != null && !matchNonProxy(url)) {
|
||||
final int proxyPort = settings.getInt(Settings.KEYS.PROXY_PORT);
|
||||
final SocketAddress address = new InetSocketAddress(proxyHost, proxyPort);
|
||||
|
||||
final String username = settings.getString(Settings.KEYS.PROXY_USERNAME);
|
||||
final String password = settings.getString(Settings.KEYS.PROXY_PASSWORD);
|
||||
|
||||
if (username != null && password != null) {
|
||||
final Authenticator auth = new Authenticator() {
|
||||
@Override
|
||||
public PasswordAuthentication getPasswordAuthentication() {
|
||||
if (proxyHost.equals(getRequestingHost()) || getRequestorType().equals(Authenticator.RequestorType.PROXY)) {
|
||||
LOGGER.debug("Using the configured proxy username and password");
|
||||
try {
|
||||
if (settings.getBoolean(Settings.KEYS.PROXY_DISABLE_SCHEMAS, true)) {
|
||||
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
|
||||
}
|
||||
} catch (InvalidSettingException ex) {
|
||||
LOGGER.trace("This exception can be ignored", ex);
|
||||
}
|
||||
return new PasswordAuthentication(username, password.toCharArray());
|
||||
}
|
||||
return super.getPasswordAuthentication();
|
||||
}
|
||||
};
|
||||
Authenticator.setDefault(auth);
|
||||
}
|
||||
|
||||
final Proxy proxy = new Proxy(Proxy.Type.HTTP, address);
|
||||
conn = (HttpURLConnection) url.openConnection(proxy);
|
||||
} else {
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
}
|
||||
final int connectionTimeout = settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000);
|
||||
conn.setConnectTimeout(connectionTimeout);
|
||||
conn.setInstanceFollowRedirects(true);
|
||||
} catch (IOException ex) {
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.disconnect();
|
||||
} finally {
|
||||
conn = null;
|
||||
}
|
||||
}
|
||||
throw new URLConnectionFailureException("Error getting connection.", ex);
|
||||
}
|
||||
configureTLS(url, conn);
|
||||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if hostname matches nonProxy settings
|
||||
*
|
||||
* @param url the url to connect to
|
||||
* @return matching result. true: match nonProxy
|
||||
*/
|
||||
private boolean matchNonProxy(final URL url) {
|
||||
final String host = url.getHost();
|
||||
|
||||
// code partially from org.apache.maven.plugins.site.AbstractDeployMojo#getProxyInfo
|
||||
final String nonProxyHosts = settings.getString(Settings.KEYS.PROXY_NON_PROXY_HOSTS);
|
||||
if (null != nonProxyHosts) {
|
||||
final String[] nonProxies = nonProxyHosts.split("(,)|(;)|(\\|)");
|
||||
for (final String nonProxyHost : nonProxies) {
|
||||
//if ( StringUtils.contains( nonProxyHost, "*" ) )
|
||||
if (null != nonProxyHost && nonProxyHost.contains("*")) {
|
||||
// Handle wildcard at the end, beginning or middle of the nonProxyHost
|
||||
final int pos = nonProxyHost.indexOf('*');
|
||||
final String nonProxyHostPrefix = nonProxyHost.substring(0, pos);
|
||||
final String nonProxyHostSuffix = nonProxyHost.substring(pos + 1);
|
||||
// prefix*
|
||||
if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && StringUtils.isEmpty(nonProxyHostSuffix)) {
|
||||
return true;
|
||||
}
|
||||
// *suffix
|
||||
if (StringUtils.isEmpty(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix) && host.endsWith(nonProxyHostSuffix)) {
|
||||
return true;
|
||||
}
|
||||
// prefix*suffix
|
||||
if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix)
|
||||
&& host.endsWith(nonProxyHostSuffix)) {
|
||||
return true;
|
||||
}
|
||||
} else if (host.equals(nonProxyHost)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
* @return a newly constructed HttpURLConnection
|
||||
* @throws URLConnectionFailureException thrown if there is an exception
|
||||
*/
|
||||
public HttpURLConnection createHttpURLConnection(URL url, boolean proxy) throws URLConnectionFailureException {
|
||||
if (proxy) {
|
||||
return createHttpURLConnection(url);
|
||||
}
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
final int timeout = settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000);
|
||||
conn.setConnectTimeout(timeout);
|
||||
conn.setInstanceFollowRedirects(true);
|
||||
} 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 void configureTLS(URL url, URLConnection conn) {
|
||||
if ("https".equals(url.getProtocol())) {
|
||||
try {
|
||||
final HttpsURLConnection secCon = (HttpsURLConnection) conn;
|
||||
final SSLSocketFactoryEx factory = new SSLSocketFactoryEx(settings);
|
||||
secCon.setSSLSocketFactory(factory);
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
LOGGER.debug("Unsupported algorithm in SSLSocketFactoryEx", ex);
|
||||
} catch (KeyManagementException ex) {
|
||||
LOGGER.debug("Key management exception in SSLSocketFactoryEx", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An exception used when the creation of an URLConnection fails.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class URLConnectionFailureException extends IOException {
|
||||
|
||||
/**
|
||||
* The serial version UID.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new URLConnectionFailureException.
|
||||
*/
|
||||
public URLConnectionFailureException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new URLConnectionFailureException.
|
||||
*
|
||||
* @param msg a message for the exception.
|
||||
*/
|
||||
public URLConnectionFailureException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new URLConnectionFailureException.
|
||||
*
|
||||
* @param ex the cause of the download failure.
|
||||
*/
|
||||
public URLConnectionFailureException(Throwable ex) {
|
||||
super(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new URLConnectionFailureException.
|
||||
*
|
||||
* @param msg a message for the exception.
|
||||
* @param ex the cause of the download failure.
|
||||
*/
|
||||
public URLConnectionFailureException(String msg, Throwable ex) {
|
||||
super(msg, ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2016 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXNotSupportedException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
/**
|
||||
* Collection of XML related code.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public final class XmlUtils {
|
||||
|
||||
/**
|
||||
* JAXP Schema Language. Source:
|
||||
* http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
|
||||
*/
|
||||
public static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
|
||||
/**
|
||||
* W3C XML Schema. Source:
|
||||
* http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
|
||||
*/
|
||||
public static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
|
||||
/**
|
||||
* JAXP Schema Source. Source:
|
||||
* http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
|
||||
*/
|
||||
public static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
|
||||
|
||||
/**
|
||||
* Private constructor for a utility class.
|
||||
*/
|
||||
private XmlUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a validating secure SAX Parser.
|
||||
*
|
||||
* @param schemaStream One or more inputStreams with the schema(s) that the
|
||||
* parser should be able to validate the XML against, one InputStream per
|
||||
* schema
|
||||
* @return a SAX Parser
|
||||
* @throws ParserConfigurationException is thrown if there is a parser
|
||||
* configuration exception
|
||||
* @throws SAXNotRecognizedException thrown if there is an unrecognized
|
||||
* feature
|
||||
* @throws SAXNotSupportedException thrown if there is a non-supported
|
||||
* feature
|
||||
* @throws SAXException is thrown if there is a SAXException
|
||||
*/
|
||||
public static SAXParser buildSecureSaxParser(InputStream... schemaStream) throws ParserConfigurationException,
|
||||
SAXNotRecognizedException, SAXNotSupportedException, SAXException {
|
||||
final SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setValidating(true);
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
//setting the following unfortunately breaks reading the old suppression files (version 1).
|
||||
//factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
|
||||
final SAXParser saxParser = factory.newSAXParser();
|
||||
saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
|
||||
saxParser.setProperty(JAXP_SCHEMA_SOURCE, schemaStream);
|
||||
return saxParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an attribute value representing an xsd:boolean value to a
|
||||
* boolean using the rules as stated in the XML specification.
|
||||
*
|
||||
* @param lexicalXSDBoolean The string-value of the boolean
|
||||
* @return the boolean value represented by {@code lexicalXSDBoolean}
|
||||
* @throws IllegalArgumentException When {@code lexicalXSDBoolean} does fit
|
||||
* the lexical space of the XSD boolean datatype
|
||||
*/
|
||||
public static boolean parseBoolean(String lexicalXSDBoolean) {
|
||||
final boolean result;
|
||||
switch (lexicalXSDBoolean) {
|
||||
case "true":
|
||||
case "1":
|
||||
result = true;
|
||||
break;
|
||||
case "false":
|
||||
case "0":
|
||||
result = false;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("'" + lexicalXSDBoolean + "' is not a valid xs:boolean value");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a secure SAX Parser.
|
||||
*
|
||||
* @return a SAX Parser
|
||||
* @throws ParserConfigurationException thrown if there is a parser
|
||||
* configuration exception
|
||||
* @throws SAXNotRecognizedException thrown if there is an unrecognized
|
||||
* feature
|
||||
* @throws SAXNotSupportedException thrown if there is a non-supported
|
||||
* feature
|
||||
* @throws SAXException is thrown if there is a SAXException
|
||||
*/
|
||||
public static SAXParser buildSecureSaxParser() throws ParserConfigurationException,
|
||||
SAXNotRecognizedException, SAXNotSupportedException, SAXException {
|
||||
final SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
return factory.newSAXParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new document builder with security features enabled.
|
||||
*
|
||||
* @return a new document builder
|
||||
* @throws ParserConfigurationException thrown if there is a parser
|
||||
* configuration exception
|
||||
*/
|
||||
public static DocumentBuilder buildSecureDocumentBuilder() throws ParserConfigurationException {
|
||||
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
return factory.newDocumentBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a prettier exception message.
|
||||
*
|
||||
* @param ex the SAXParseException
|
||||
* @return an easier to read exception message
|
||||
*/
|
||||
public static String getPrettyParseExceptionInfo(SAXParseException ex) {
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (ex.getSystemId() != null) {
|
||||
sb.append("systemId=").append(ex.getSystemId()).append(", ");
|
||||
}
|
||||
if (ex.getPublicId() != null) {
|
||||
sb.append("publicId=").append(ex.getPublicId()).append(", ");
|
||||
}
|
||||
if (ex.getLineNumber() > 0) {
|
||||
sb.append("Line=").append(ex.getLineNumber());
|
||||
}
|
||||
if (ex.getColumnNumber() > 0) {
|
||||
sb.append(", Column=").append(ex.getColumnNumber());
|
||||
}
|
||||
sb.append(": ").append(ex.getMessage());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Includes various utility classes such as a Settings wrapper, utilities to make URL Connections, etc.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
4
utils/src/site/markdown/index.md
Normal file
4
utils/src/site/markdown/index.md
Normal file
@@ -0,0 +1,4 @@
|
||||
About
|
||||
=====
|
||||
OWASP dependency-check-utils is a collection of common utility classes used within dependency-check
|
||||
that might be useful in other projects.
|
||||
1
utils/src/site/resources/images/dc-utils.svg
Normal file
1
utils/src/site/resources/images/dc-utils.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 11 KiB |
32
utils/src/site/site.xml
Normal file
32
utils/src/site/site.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!--
|
||||
This file is part of dependency-check-ant.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||
-->
|
||||
<project name="dependency-check-utils">
|
||||
<bannerLeft>
|
||||
<name>OWASP dependency-check-utils</name>
|
||||
<alt>OWASP dependency-check-utils</alt>
|
||||
<src>./images/dc-utils.svg</src>
|
||||
</bannerLeft>
|
||||
<body>
|
||||
<breadcrumbs>
|
||||
<item name="dependency-check" href="../index.html"/>
|
||||
</breadcrumbs>
|
||||
<menu ref="Project Documentation" />
|
||||
<menu ref="reports" />
|
||||
</body>
|
||||
</project>
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2014 OWASP.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class BaseTest {
|
||||
|
||||
/**
|
||||
* The configured settings.
|
||||
*/
|
||||
private Settings settings;
|
||||
|
||||
/**
|
||||
* Initialize the {@link Settings}.
|
||||
*/
|
||||
@Before
|
||||
public void setUp() {
|
||||
settings = new Settings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the {@link Settings}.
|
||||
*/
|
||||
@After
|
||||
public void tearDown() {
|
||||
settings.cleanup(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the settings for the test cases.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class ChecksumTest {
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
/**
|
||||
* Test of getChecksum method, of class Checksum.
|
||||
*
|
||||
* @throws Exception thrown when an exception occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testGetChecksum() throws Exception {
|
||||
String algorithm = "MD5";
|
||||
File file = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath());
|
||||
byte[] expResult = {-16, -111, 92, 95, 70, -72, -49, -94, -125, -27, -83, 103, -96, -101, 55, -109};
|
||||
byte[] result = Checksum.getChecksum(algorithm, file);
|
||||
assertArrayEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getChecksum method, of class Checksum. This checks that an exception is thrown when an invalid path is specified.
|
||||
*
|
||||
* @throws Exception is thrown when an exception occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testGetChecksum_FileNotFound() throws Exception {
|
||||
String algorithm = "MD5";
|
||||
File file = new File("not a valid file");
|
||||
|
||||
expectedException.expect(IOException.class);
|
||||
Checksum.getChecksum(algorithm, file);
|
||||
fail("exception should be thrown");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getChecksum method, of class Checksum. This checks that an exception is thrown when an invalid algorithm is
|
||||
* specified.
|
||||
*
|
||||
* @throws Exception is thrown when an exception occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testGetChecksum_NoSuchAlgorithm() throws Exception {
|
||||
String algorithm = "some unknown algorithm";
|
||||
File file = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").getPath());
|
||||
|
||||
expectedException.expect(NoSuchAlgorithmException.class);
|
||||
Checksum.getChecksum(algorithm, file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getMD5Checksum method, of class Checksum.
|
||||
*
|
||||
* @throws Exception is thrown when an exception occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testGetMD5Checksum() throws Exception {
|
||||
File file = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath());
|
||||
//String expResult = "F0915C5F46B8CFA283E5AD67A09B3793";
|
||||
String expResult = "f0915c5f46b8cfa283e5ad67a09b3793";
|
||||
String result = Checksum.getMD5Checksum(file);
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getSHA1Checksum method, of class Checksum.
|
||||
*
|
||||
* @throws Exception is thrown when an exception occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testGetSHA1Checksum() throws Exception {
|
||||
File file = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath());
|
||||
//String expResult = "B8A9FF28B21BCB1D0B50E24A5243D8B51766851A";
|
||||
String expResult = "b8a9ff28b21bcb1d0b50e24a5243d8b51766851a";
|
||||
String result = Checksum.getSHA1Checksum(file);
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getHex method, of class Checksum.
|
||||
*/
|
||||
@Test
|
||||
public void testGetHex() {
|
||||
byte[] raw = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
|
||||
//String expResult = "000102030405060708090A0B0C0D0E0F10";
|
||||
String expResult = "000102030405060708090a0b0c0d0e0f10";
|
||||
String result = Checksum.getHex(raw);
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getChecksum method, of class Checksum.
|
||||
*/
|
||||
@Test
|
||||
public void testGetChecksum_String_File() throws Exception {
|
||||
String algorithm = "MD5";
|
||||
File file = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath());
|
||||
byte[] expResult = {-16, -111, 92, 95, 70, -72, -49, -94, -125, -27, -83, 103, -96, -101, 55, -109};
|
||||
byte[] result = Checksum.getChecksum(algorithm, file);
|
||||
assertArrayEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getMD5Checksum method, of class Checksum.
|
||||
*/
|
||||
@Test
|
||||
public void testGetMD5Checksum_File() throws Exception {
|
||||
File file = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath());
|
||||
String expResult = "f0915c5f46b8cfa283e5ad67a09b3793";
|
||||
String result = Checksum.getMD5Checksum(file);
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getSHA1Checksum method, of class Checksum.
|
||||
*/
|
||||
@Test
|
||||
public void testGetSHA1Checksum_File() throws Exception {
|
||||
File file = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath());
|
||||
String expResult = "b8a9ff28b21bcb1d0b50e24a5243d8b51766851a";
|
||||
String result = Checksum.getSHA1Checksum(file);
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getChecksum method, of class Checksum.
|
||||
*/
|
||||
@Test
|
||||
public void testGetChecksum_String_byteArr() {
|
||||
String algorithm = "SHA1";
|
||||
byte[] bytes = {-16, -111, 92, 95, 70, -72, -49, -94, -125, -27, -83, 103, -96, -101, 55, -109};
|
||||
String expResult = "89268a389a97f0bfba13d3ff2370d8ad436e36f6";
|
||||
String result = Checksum.getChecksum(algorithm, bytes);
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getMD5Checksum method, of class Checksum.
|
||||
*/
|
||||
@Test
|
||||
public void testGetMD5Checksum_String() {
|
||||
String text = "test string";
|
||||
String expResult = "6f8db599de986fab7a21625b7916589c";
|
||||
String result = Checksum.getMD5Checksum(text);
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getSHA1Checksum method, of class Checksum.
|
||||
*/
|
||||
@Test
|
||||
public void testGetSHA1Checksum_String() {
|
||||
String text = "test string";
|
||||
String expResult = "661295c9cbf9d6b2f6428414504a8deed3020641";
|
||||
String result = Checksum.getSHA1Checksum(text);
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class DownloaderIT extends BaseTest {
|
||||
|
||||
/**
|
||||
* Test of fetchFile method, of class Downloader.
|
||||
*
|
||||
* @throws Exception thrown when an exception occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testFetchFile() throws Exception {
|
||||
|
||||
// Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, "1000");
|
||||
// Settings.setString(Settings.KEYS.PROXY_PORT, "8080");
|
||||
// Settings.setString(Settings.KEYS.PROXY_SERVER, "127.0.0.1");
|
||||
URL url = new URL(getSettings().getString(Settings.KEYS.CVE_MODIFIED_20_URL));
|
||||
File outputPath = new File("target/downloaded_cve.xml");
|
||||
Downloader downloader = new Downloader(getSettings());
|
||||
downloader.fetchFile(url, outputPath);
|
||||
assertTrue(outputPath.isFile());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLastModified() throws Exception {
|
||||
URL url = new URL(getSettings().getString(Settings.KEYS.CVE_MODIFIED_20_URL));
|
||||
Downloader downloader = new Downloader(getSettings());
|
||||
long timestamp = downloader.getLastModified(url);
|
||||
assertTrue("timestamp equal to zero?", timestamp > 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.File;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class DownloaderTest extends BaseTest {
|
||||
|
||||
@Test
|
||||
public void testGetLastModified_file() throws Exception {
|
||||
Downloader instance = new Downloader(getSettings());
|
||||
long timestamp = instance.getLastModified(new File("target/test-classes/dependencycheck.properties").toURI().toURL());
|
||||
assertTrue("timestamp equal to zero?", timestamp > 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2016 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeremy
|
||||
*/
|
||||
public class ExpectedObjectInputStreamTest {
|
||||
|
||||
/**
|
||||
* Test of resolveClass method, of class ExpectedObjectInputStream.
|
||||
*/
|
||||
@Test
|
||||
public void testResolveClass() {
|
||||
List<SimplePojo> data = new ArrayList<>();
|
||||
data.add(new SimplePojo());
|
||||
try (ByteArrayOutputStream mem = new ByteArrayOutputStream();
|
||||
ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(mem))) {
|
||||
out.writeObject(data);
|
||||
out.flush();
|
||||
byte[] buf = mem.toByteArray();
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(buf);
|
||||
ExpectedObjectInputStream instance = new ExpectedObjectInputStream(in, "java.util.ArrayList", "org.owasp.dependencycheck.utils.SimplePojo", "java.lang.Integer", "java.lang.Number");
|
||||
instance.readObject();
|
||||
} catch (IOException | ClassNotFoundException ex) {
|
||||
fail(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of resolveClass method, of class ExpectedObjectInputStream.
|
||||
*/
|
||||
@Test(expected = java.io.InvalidClassException.class)
|
||||
public void testResolveClassException() throws Exception {
|
||||
List<SimplePojo> data = new ArrayList<>();
|
||||
data.add(new SimplePojo());
|
||||
|
||||
ByteArrayOutputStream mem = new ByteArrayOutputStream();
|
||||
byte[] buf;
|
||||
try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(mem))) {
|
||||
out.writeObject(data);
|
||||
out.flush();
|
||||
buf = mem.toByteArray();
|
||||
}
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(buf);
|
||||
|
||||
ExpectedObjectInputStream instance = new ExpectedObjectInputStream(in, "java.util.ArrayList", "org.owasp.dependencycheck.utils.SimplePojo");
|
||||
instance.readObject();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.File;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class FileUtilsTest extends BaseTest {
|
||||
|
||||
/**
|
||||
* Test of getFileExtension method, of class FileUtils.
|
||||
*/
|
||||
@Test
|
||||
public void testGetFileExtension() {
|
||||
String[] fileName = {"something-0.9.5.jar", "lib2-1.1.js", "dir.tmp/noext"};
|
||||
String[] expResult = {"jar", "js", null};
|
||||
|
||||
for (int i = 0; i < fileName.length; i++) {
|
||||
String result = FileUtils.getFileExtension(fileName[i]);
|
||||
assertEquals("Failed extraction on \"" + fileName[i] + "\".", expResult[i], result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of delete method, of class FileUtils.
|
||||
*/
|
||||
@Test
|
||||
public void testDelete() throws Exception {
|
||||
|
||||
File file = File.createTempFile("tmp", "deleteme", getSettings().getTempDirectory());
|
||||
if (!file.exists()) {
|
||||
fail("Unable to create a temporary file.");
|
||||
}
|
||||
boolean status = FileUtils.delete(file);
|
||||
assertTrue("delete returned a failed status", status);
|
||||
assertFalse("Temporary file exists after attempting deletion", file.exists());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* This file is part of dependency-check-core.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.hamcrest.core.IsNull.notNullValue;
|
||||
import static org.hamcrest.core.IsNull.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class SettingsTest extends BaseTest {
|
||||
|
||||
/**
|
||||
* Test of getString method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testGetString() {
|
||||
String key = Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS;
|
||||
String expResult = "7";
|
||||
String result = getSettings().getString(key);
|
||||
Assert.assertTrue(result.endsWith(expResult));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getDataFile method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testGetDataFile() throws IOException {
|
||||
String key = Settings.KEYS.DATA_DIRECTORY;
|
||||
String expResult = "data";
|
||||
File result = getSettings().getDataFile(key);
|
||||
Assert.assertTrue(result.getAbsolutePath().endsWith(expResult));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of mergeProperties method, of class Settings.
|
||||
* @throws java.io.IOException thrown when the test fails
|
||||
* @throws java.net.URISyntaxException thrown when the test fails
|
||||
*/
|
||||
@Test
|
||||
public void testMergeProperties_String() throws IOException, URISyntaxException {
|
||||
String key = Settings.KEYS.PROXY_PORT;
|
||||
String expResult = getSettings().getString(key);
|
||||
File f = new File(this.getClass().getClassLoader().getResource("test.properties").toURI());
|
||||
//InputStream in = this.getClass().getClassLoader().getResourceAsStream("test.properties");
|
||||
getSettings().mergeProperties(f.getAbsolutePath());
|
||||
String result = getSettings().getString(key);
|
||||
Assert.assertTrue("setting didn't change?", (expResult == null && result != null) || !expResult.equals(result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of setString method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testSetString() {
|
||||
String key = "newProperty";
|
||||
String value = "someValue";
|
||||
getSettings().setString(key, value);
|
||||
String expResults = getSettings().getString(key);
|
||||
Assert.assertEquals(expResults, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of setStringIfNotNull method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testSetStringIfNotNull() {
|
||||
String key = "nullableProperty";
|
||||
String value = "someValue";
|
||||
getSettings().setString(key, value);
|
||||
getSettings().setStringIfNotNull(key, null); // NO-OP
|
||||
String expResults = getSettings().getString(key);
|
||||
Assert.assertEquals(expResults, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of setStringIfNotNull method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testSetStringIfNotEmpty() {
|
||||
String key = "optionalProperty";
|
||||
String value = "someValue";
|
||||
getSettings().setString(key, value);
|
||||
getSettings().setStringIfNotEmpty(key, ""); // NO-OP
|
||||
String expResults = getSettings().getString(key);
|
||||
Assert.assertEquals(expResults, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getString method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testGetString_String_String() {
|
||||
String key = "key That Doesn't Exist";
|
||||
String defaultValue = "blue bunny";
|
||||
String expResult = "blue bunny";
|
||||
String result = getSettings().getString(key);
|
||||
Assert.assertTrue(result == null);
|
||||
result = getSettings().getString(key, defaultValue);
|
||||
Assert.assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getString method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testGetString_String() {
|
||||
String key = Settings.KEYS.CONNECTION_TIMEOUT;
|
||||
String result = getSettings().getString(key);
|
||||
Assert.assertTrue(result == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getInt method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testGetInt() throws InvalidSettingException {
|
||||
String key = "SomeNumber";
|
||||
int expResult = 85;
|
||||
getSettings().setString(key, "85");
|
||||
int result = getSettings().getInt(key);
|
||||
Assert.assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getInt method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testGetIntDefault() throws InvalidSettingException {
|
||||
String key = "SomeKey";
|
||||
int expResult = 85;
|
||||
getSettings().setString(key, "blue");
|
||||
int result = getSettings().getInt(key, expResult);
|
||||
Assert.assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getLong method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testGetLong() throws InvalidSettingException {
|
||||
String key = "SomeNumber";
|
||||
long expResult = 300L;
|
||||
getSettings().setString(key, "300");
|
||||
long result = getSettings().getLong(key);
|
||||
Assert.assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getBoolean method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testGetBoolean() throws InvalidSettingException {
|
||||
String key = "SomeBoolean";
|
||||
getSettings().setString(key, "false");
|
||||
boolean expResult = false;
|
||||
boolean result = getSettings().getBoolean(key);
|
||||
Assert.assertEquals(expResult, result);
|
||||
|
||||
key = "something that does not exist";
|
||||
expResult = true;
|
||||
result = getSettings().getBoolean(key, true);
|
||||
Assert.assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of removeProperty method, of class Settings.
|
||||
*/
|
||||
@Test
|
||||
public void testRemoveProperty() {
|
||||
String key = "SomeKey";
|
||||
String value = "value";
|
||||
String dfault = "default";
|
||||
getSettings().setString(key, value);
|
||||
String ret = getSettings().getString(key);
|
||||
Assert.assertEquals(value, ret);
|
||||
getSettings().removeProperty(key);
|
||||
ret = getSettings().getString(key, dfault);
|
||||
Assert.assertEquals(dfault, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getConnectionString.
|
||||
*/
|
||||
@Test
|
||||
public void testGetConnectionString() throws Exception {
|
||||
String value = getSettings().getConnectionString(Settings.KEYS.DB_CONNECTION_STRING, Settings.KEYS.DB_FILE_NAME);
|
||||
Assert.assertNotNull(value);
|
||||
String msg = null;
|
||||
try {
|
||||
value = getSettings().getConnectionString("invalidKey", null);
|
||||
} catch (InvalidSettingException e) {
|
||||
msg = e.getMessage();
|
||||
}
|
||||
Assert.assertNotNull(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getTempDirectory.
|
||||
*/
|
||||
@Test
|
||||
public void testGetTempDirectory() throws Exception {
|
||||
File tmp = getSettings().getTempDirectory();
|
||||
Assert.assertTrue(tmp.exists());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert {@link Settings#getArray(String)} from a delimited string returns
|
||||
* multiple values in an array.
|
||||
*/
|
||||
@Test
|
||||
public void testGetArrayFromADelimitedString() {
|
||||
// GIVEN a delimited string
|
||||
final String delimitedString = "value1,value2";
|
||||
getSettings().setString("key", delimitedString);
|
||||
|
||||
// WHEN getting the array
|
||||
final String[] array = getSettings().getArray("key");
|
||||
|
||||
// THEN the split array is returned
|
||||
assertThat("Expected the array to be non-null", array, notNullValue());
|
||||
assertThat("Expected the array to have two values", array.length, is(2));
|
||||
assertThat("Expected the first array value to be value1", array[0], is("value1"));
|
||||
assertThat("Expected the second array value to be value2", array[1], is("value2"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert {@link Settings#getArray(String)} returns {@code null} if the
|
||||
* property is not set.
|
||||
*/
|
||||
@Test
|
||||
public void testGetArrayWhereThePropertyIsNotSet() {
|
||||
// WHEN getting the array
|
||||
final String[] array = getSettings().getArray("key");
|
||||
|
||||
// THEN null is returned
|
||||
assertThat("Expected the array to be null", array, nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert {@link Settings#setArrayIfNotEmpty(String, String[])} with an
|
||||
* empty array is ignored.
|
||||
*/
|
||||
@Test
|
||||
public void testSetArrayNotEmptyIgnoresAnEmptyArray() {
|
||||
// GIVEN an empty array
|
||||
final String[] array = {};
|
||||
|
||||
// WHEN setting the array
|
||||
getSettings().setArrayIfNotEmpty("key", array);
|
||||
|
||||
// THEN the property was not set
|
||||
assertThat("Expected the property to not be set", getSettings().getString("key"), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert {@link Settings#setArrayIfNotEmpty(String, String[])} with a null
|
||||
* array is ignored.
|
||||
*/
|
||||
@Test
|
||||
public void testSetArrayNotEmptyIgnoresAnNullArray() {
|
||||
// GIVEN a null array
|
||||
final String[] array = null;
|
||||
|
||||
// WHEN setting the array
|
||||
getSettings().setArrayIfNotEmpty("key", array);
|
||||
|
||||
// THEN the property was not set
|
||||
assertThat("Expected the property to not be set", getSettings().getString("key"), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert {@link Settings#setArrayIfNotEmpty(String, String[])} with
|
||||
* multiple values sets a delimited string.
|
||||
*/
|
||||
@Test
|
||||
public void testSetArrayNotEmptySetsADelimitedString() {
|
||||
// GIVEN an array with values
|
||||
final String[] array = {"value1", "value2"};
|
||||
|
||||
// WHEN setting the array
|
||||
getSettings().setArrayIfNotEmpty("key", array);
|
||||
|
||||
// THEN the property is set
|
||||
assertThat("Expected the property to be set", getSettings().getString("key"), is("value1,value2"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert {@link Settings#setArrayIfNotEmpty(String, String[])} with a
|
||||
* single values sets a string.
|
||||
*/
|
||||
@Test
|
||||
public void testSetArrayNotEmptyWithSingleValueSetsAString() {
|
||||
// GIVEN an array with a value
|
||||
final String[] array = {"value1"};
|
||||
|
||||
// WHEN setting the array
|
||||
getSettings().setArrayIfNotEmpty("key", array);
|
||||
|
||||
// THEN the property is set
|
||||
assertThat("Expected the property to be set", getSettings().getString("key"), is("value1"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2016 OWASP.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Simple pojo used to test the ExpectedObjectInputStream.
|
||||
*
|
||||
* @author jeremy
|
||||
*/
|
||||
public class SimplePojo implements Serializable {
|
||||
/**
|
||||
* The serial version UID for serialization.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public String s = "3";
|
||||
public Integer i = 3;
|
||||
}
|
||||
1
utils/src/test/resources/checkSumTest.file
Normal file
1
utils/src/test/resources/checkSumTest.file
Normal file
@@ -0,0 +1 @@
|
||||
this is a test file used to check the checksums.
|
||||
70
utils/src/test/resources/dependencycheck.properties
Normal file
70
utils/src/test/resources/dependencycheck.properties
Normal file
@@ -0,0 +1,70 @@
|
||||
application.name=${pom.name}
|
||||
application.version=${pom.version}
|
||||
autoupdate=true
|
||||
|
||||
# the url to obtain the current engine version from
|
||||
engine.version.url=http://jeremylong.github.io/DependencyCheck/current.txt
|
||||
|
||||
#temp.directory defaults to System.getProperty("java.io.tmpdir")
|
||||
#temp.directory=[path to temp directory]
|
||||
|
||||
# the path to the data directory; the [JAR] signifies to use the relative path
|
||||
# to the dependency-check-core JAR file. This path is only used to construct
|
||||
# the connection string for the H2 driver (or other drivers that require a file path
|
||||
# to be supplied. If you are using another database (MySQL, Oracle, etc.) this property
|
||||
# will not be used. The data.directory will be resolved and if the connection string
|
||||
# below contains a %s then the data.directory will replace the %s.
|
||||
data.directory=[JAR]/data
|
||||
data.file_name=dc.h2.db
|
||||
data.version=3.0
|
||||
data.connection_string=jdbc:h2:file:%s;MV_STORE=FALSE;AUTOCOMMIT=ON;
|
||||
#data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;AUTOCOMMIT=ON;
|
||||
#data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
|
||||
|
||||
# user name and password for the database connection. The inherent case is to use H2.
|
||||
# As such, this unsecure username/password exist.
|
||||
data.user=dcuser
|
||||
data.password=DC-Pass1337!
|
||||
# The following are only used if the DB Driver is not JDBC4 compliant and/or the driver
|
||||
# is not in the current classpath. Setting these properties will add the give path(s) to
|
||||
# the class loader and then register the driver with the DriverManager. If the class is
|
||||
# not in the path you must specify both the driver name (aka the fully qualified driver name)
|
||||
# and the driver path. The driver path can be a semi-colon separated list of files/directories
|
||||
# to ensure any and all needed files can be added to the classpath to load the driver.
|
||||
# For non-JDBC4 drivers in the classpath only the driver_name needs to be set.
|
||||
# For MOST situations these properties likely do not need to be set.
|
||||
data.driver_name=org.h2.Driver
|
||||
data.driver_path=
|
||||
|
||||
proxy.disableSchemas=true
|
||||
# the path to the cpe xml file
|
||||
cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.xml.gz
|
||||
# the path to the cpe meta data file.
|
||||
cpe.meta.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.meta
|
||||
|
||||
# the number of days that the modified nvd cve data holds data for. We don't need
|
||||
# to update the other files if we are within this timespan. Per NIST this file
|
||||
# holds 8 days of updates, we are using 7 just to be safe.
|
||||
cve.url.modified.validfordays=7
|
||||
|
||||
# the path to the modified nvd cve xml file.
|
||||
cve.startyear=2014
|
||||
cve.url-1.2.modified=https://nvd.nist.gov/download/nvdcve-Modified.xml.gz
|
||||
#cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
|
||||
cve.url-2.0.modified=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz
|
||||
#cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
|
||||
cve.url-1.2.base=https://nvd.nist.gov/download/nvdcve-%d.xml.gz
|
||||
#cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
|
||||
cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz
|
||||
#cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
|
||||
|
||||
# the URL for searching Nexus for SHA-1 hashes and whether it's enabled
|
||||
analyzer.nexus.enabled=true
|
||||
analyzer.nexus.url=https://repository.sonatype.org/service/local/
|
||||
# If set to true, the proxy will still ONLY be used if the proxy properties (proxy.url, proxy.port)
|
||||
# are configured
|
||||
analyzer.nexus.proxy=true
|
||||
|
||||
# use HEAD (default) or GET as HTTP request method for query timestamp
|
||||
downloader.quick.query.timestamp=true
|
||||
downloader.tls.protocols=TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
|
||||
13
utils/src/test/resources/logback-test.xml
Normal file
13
utils/src/test/resources/logback-test.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<configuration>
|
||||
<contextName>dependency-check</contextName>
|
||||
<!-- Logging configuration -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<Target>System.out</Target>
|
||||
<encoder>
|
||||
<pattern>[%level] %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<root level="INFO">
|
||||
<appender-ref ref="console"/>
|
||||
</root>
|
||||
</configuration>
|
||||
1
utils/src/test/resources/test.properties
Normal file
1
utils/src/test/resources/test.properties
Normal file
@@ -0,0 +1 @@
|
||||
proxy.port=80
|
||||
Reference in New Issue
Block a user