mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-03-09 09:30:19 +01:00
continued work on threading and code improvement
This commit is contained in:
@@ -20,6 +20,7 @@ package org.owasp.dependencycheck.taskdefs;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.Project;
|
||||
@@ -46,6 +47,7 @@ import org.slf4j.impl.StaticLoggerBinder;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class Check extends Update {
|
||||
|
||||
/**
|
||||
@@ -161,6 +163,7 @@ public class Check extends Update {
|
||||
/**
|
||||
* Suppression file paths.
|
||||
*/
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
private List<String> suppressionFiles = new ArrayList<>();
|
||||
|
||||
/**
|
||||
@@ -1065,7 +1068,7 @@ public class Check extends Update {
|
||||
* @throws BuildException thrown if a CVSS score is found that is higher
|
||||
* than the threshold set
|
||||
*/
|
||||
private void checkForFailure(List<Dependency> dependencies) throws BuildException {
|
||||
private void checkForFailure(Dependency[] dependencies) throws BuildException {
|
||||
final StringBuilder ids = new StringBuilder();
|
||||
for (Dependency d : dependencies) {
|
||||
for (Vulnerability v : d.getVulnerabilities()) {
|
||||
@@ -1092,7 +1095,7 @@ public class Check extends Update {
|
||||
*
|
||||
* @param dependencies a list of dependency objects
|
||||
*/
|
||||
private void showSummary(List<Dependency> dependencies) {
|
||||
private void showSummary(Dependency[] dependencies) {
|
||||
final StringBuilder summary = new StringBuilder();
|
||||
for (Dependency d : dependencies) {
|
||||
boolean firstEntry = true;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class StaticLoggerBinder implements LoggerFactoryBinder {
|
||||
*
|
||||
* @return the StaticLoggerBinder singleton
|
||||
*/
|
||||
public static final StaticLoggerBinder getSingleton() {
|
||||
public static StaticLoggerBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
|
||||
@@ -312,7 +312,6 @@ public class App {
|
||||
* @param excludes an array of ant style excludes
|
||||
* @return returns the set of identified files
|
||||
* @throws InvalidScanPathException thrown when the scan path is invalid
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
private Set<File> scanAntStylePaths(List<String> antStylePaths, int symLinkDepth, String[] excludes)
|
||||
throws InvalidScanPathException {
|
||||
|
||||
@@ -21,12 +21,12 @@ import org.owasp.dependencycheck.analyzer.Analyzer;
|
||||
import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Task to support parallelism of dependency-check analysis. Analyses a single
|
||||
@@ -34,6 +34,7 @@ import java.util.concurrent.Callable;
|
||||
*
|
||||
* @author Stefan Neuhaus
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class AnalysisTask implements Callable<Void> {
|
||||
|
||||
/**
|
||||
@@ -57,10 +58,6 @@ public class AnalysisTask implements Callable<Void> {
|
||||
* The list of exceptions that may occur during analysis.
|
||||
*/
|
||||
private final List<Throwable> exceptions;
|
||||
/**
|
||||
* A reference to the global settings object.
|
||||
*/
|
||||
private final Settings settings;
|
||||
|
||||
/**
|
||||
* Creates a new analysis task.
|
||||
@@ -70,16 +67,12 @@ public class AnalysisTask implements Callable<Void> {
|
||||
* @param engine the dependency-check engine
|
||||
* @param exceptions exceptions that occur during analysis will be added to
|
||||
* this collection of exceptions
|
||||
* @param settings a reference to the global settings object; this is
|
||||
* necessary so that when the thread is started the dependencies have a
|
||||
* correct reference to the global settings.
|
||||
*/
|
||||
AnalysisTask(Analyzer analyzer, Dependency dependency, Engine engine, List<Throwable> exceptions, Settings settings) {
|
||||
AnalysisTask(Analyzer analyzer, Dependency dependency, Engine engine, List<Throwable> exceptions) {
|
||||
this.analyzer = analyzer;
|
||||
this.dependency = dependency;
|
||||
this.engine = engine;
|
||||
this.exceptions = exceptions;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,6 +57,7 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
import static org.owasp.dependencycheck.analyzer.AnalysisPhase.*;
|
||||
|
||||
@@ -68,6 +69,7 @@ import static org.owasp.dependencycheck.analyzer.AnalysisPhase.*;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class Engine implements FileFilter, AutoCloseable {
|
||||
|
||||
/**
|
||||
@@ -170,7 +172,7 @@ public class Engine implements FileFilter, AutoCloseable {
|
||||
* The ClassLoader to use when dynamically loading Analyzer and Update
|
||||
* services.
|
||||
*/
|
||||
private ClassLoader serviceClassLoader;
|
||||
private final ClassLoader serviceClassLoader;
|
||||
/**
|
||||
* A reference to the database.
|
||||
*/
|
||||
@@ -304,8 +306,42 @@ public class Engine implements FileFilter, AutoCloseable {
|
||||
* @see Collections#synchronizedList(List)
|
||||
* @see Analyzer#supportsParallelProcessing()
|
||||
*/
|
||||
public synchronized List<Dependency> getDependencies() {
|
||||
return dependencies;
|
||||
// public synchronized List<Dependency> getDependencies() {
|
||||
// return dependencies;
|
||||
// }
|
||||
/**
|
||||
* Adds a dependency.
|
||||
*
|
||||
* @param dependency the dependency to add
|
||||
*/
|
||||
public synchronized void addDependency(Dependency dependency) {
|
||||
dependencies.add(dependency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the dependency list.
|
||||
*/
|
||||
public synchronized void sortDependencies() {
|
||||
//TODO - is this actually necassary????
|
||||
Collections.sort(dependencies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the dependency.
|
||||
*
|
||||
* @param dependency the dependency to remove.
|
||||
*/
|
||||
public synchronized void removeDependency(Dependency dependency) {
|
||||
dependencies.remove(dependency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the dependencies as an array.
|
||||
*
|
||||
* @return the dependencies identified
|
||||
*/
|
||||
public synchronized Dependency[] getDependencies() {
|
||||
return dependencies.toArray(new Dependency[dependencies.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -750,7 +786,7 @@ public class Engine implements FileFilter, AutoCloseable {
|
||||
final List<AnalysisTask> result = new ArrayList<>();
|
||||
synchronized (dependencies) {
|
||||
for (final Dependency dependency : dependencies) {
|
||||
final AnalysisTask task = new AnalysisTask(analyzer, dependency, this, exceptions, settings);
|
||||
final AnalysisTask task = new AnalysisTask(analyzer, dependency, this, exceptions);
|
||||
result.add(task);
|
||||
}
|
||||
}
|
||||
@@ -907,9 +943,9 @@ public class Engine implements FileFilter, AutoCloseable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns
|
||||
* Returns the configured settings.
|
||||
*
|
||||
* @return
|
||||
* @return the configured settings
|
||||
*/
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.owasp.dependencycheck.agent;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
@@ -59,6 +60,7 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Steve Springett
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@NotThreadSafe
|
||||
public class DependencyCheckScanAgent {
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="private fields">
|
||||
@@ -938,7 +940,7 @@ public class DependencyCheckScanAgent {
|
||||
* @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if
|
||||
* there is an exception executing the scan.
|
||||
*/
|
||||
private void checkForFailure(List<Dependency> dependencies) throws ScanAgentException {
|
||||
private void checkForFailure(Dependency[] dependencies) throws ScanAgentException {
|
||||
final StringBuilder ids = new StringBuilder();
|
||||
for (Dependency d : dependencies) {
|
||||
boolean addName = true;
|
||||
@@ -969,7 +971,7 @@ public class DependencyCheckScanAgent {
|
||||
*
|
||||
* @param dependencies a list of dependency objects
|
||||
*/
|
||||
private void showSummary(List<Dependency> dependencies) {
|
||||
private void showSummary(Dependency[] dependencies) {
|
||||
final StringBuilder summary = new StringBuilder();
|
||||
for (Dependency d : dependencies) {
|
||||
boolean firstEntry = true;
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -32,6 +33,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public abstract class AbstractAnalyzer implements Analyzer {
|
||||
|
||||
/**
|
||||
@@ -153,7 +155,7 @@ public abstract class AbstractAnalyzer implements Analyzer {
|
||||
try {
|
||||
this.setEnabled(settings.getBoolean(key, true));
|
||||
} catch (InvalidSettingException ex) {
|
||||
String msg = String.format("Invalid setting for property '{}'", key);
|
||||
final String msg = String.format("Invalid setting for property '%s'", key);
|
||||
LOGGER.warn(msg);
|
||||
LOGGER.debug(msg, ex);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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) 2017 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This analyzer ensures dependencies that should be grouped together, to remove
|
||||
* excess noise from the report, are grouped. An example would be Spring, Spring
|
||||
* Beans, Spring MVC, etc. If they are all for the same version and have the
|
||||
* same relative path then these should be grouped into a single dependency
|
||||
* under the core/main library.</p>
|
||||
* <p>
|
||||
* Note, this grouping only works on dependencies with identified CVE
|
||||
* entries</p>
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public abstract class AbstractDependencyComparingAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
/**
|
||||
* The Logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDependencyComparingAnalyzer.class);
|
||||
|
||||
/**
|
||||
* a flag indicating if this analyzer has run. This analyzer only runs once.
|
||||
*/
|
||||
private boolean analyzed = false;
|
||||
|
||||
/**
|
||||
* Returns a flag indicating if this analyzer has run. This analyzer only
|
||||
* runs once. Note this is currently only used in the unit tests.
|
||||
*
|
||||
* @return a flag indicating if this analyzer has run. This analyzer only
|
||||
* runs once
|
||||
*/
|
||||
protected synchronized boolean getAnalyzed() {
|
||||
return analyzed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not support parallel processing as it only runs once and then
|
||||
* operates on <em>all</em> dependencies.
|
||||
*
|
||||
* @return whether or not parallel processing is enabled
|
||||
* @see #analyze(Dependency, Engine)
|
||||
*/
|
||||
@Override
|
||||
public final boolean supportsParallelProcessing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes a set of dependencies. If they have been found to have the same
|
||||
* base path and the same set of identifiers they are likely related. The
|
||||
* related dependencies are bundled into a single reportable item.
|
||||
*
|
||||
* @param ignore this analyzer ignores the dependency being analyzed
|
||||
* @param engine the engine that is scanning the dependencies
|
||||
* @throws AnalysisException is thrown if there is an error reading the JAR
|
||||
* file.
|
||||
*/
|
||||
@Override
|
||||
protected synchronized void analyzeDependency(Dependency ignore, Engine engine) throws AnalysisException {
|
||||
if (!analyzed) {
|
||||
analyzed = true;
|
||||
final Set<Dependency> dependenciesToRemove = new HashSet<>();
|
||||
|
||||
final Dependency[] dependencies = engine.getDependencies();
|
||||
if (dependencies.length < 2) {
|
||||
return;
|
||||
}
|
||||
for (int x = 0; x < dependencies.length - 1; x++) {
|
||||
final Dependency dependency = dependencies[x];
|
||||
if (!dependenciesToRemove.contains(dependency)) {
|
||||
for (int y = x + 1; y < dependencies.length; y++) {
|
||||
final Dependency nextDependency = dependencies[y];
|
||||
if (evaluateDependencies(dependency, nextDependency, dependenciesToRemove)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Dependency d : dependenciesToRemove) {
|
||||
engine.removeDependency(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the dependencies
|
||||
*
|
||||
* @param dependency a dependency to compare
|
||||
* @param nextDependency a dependency to compare
|
||||
* @param dependenciesToRemove a set of dependencies that will be removed
|
||||
* @return true if a dependency is removed; otherwise false
|
||||
*/
|
||||
protected abstract boolean evaluateDependencies(final Dependency dependency,
|
||||
final Dependency nextDependency, final Set<Dependency> dependenciesToRemove);
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import java.io.FileFilter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
|
||||
@@ -34,6 +35,7 @@ import org.owasp.dependencycheck.exception.InitializationException;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implements FileTypeAnalyzer {
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="Field definitions, getters, and setters ">
|
||||
@@ -46,15 +48,6 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
|
||||
*/
|
||||
private boolean filesMatched = false;
|
||||
|
||||
/**
|
||||
* Get the value of filesMatched. A flag indicating whether the scan
|
||||
* included any file types this analyzer supports.
|
||||
*
|
||||
* @return the value of filesMatched
|
||||
*/
|
||||
protected boolean isFilesMatched() {
|
||||
return filesMatched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of filesMatched. A flag indicating whether the scan
|
||||
|
||||
@@ -22,10 +22,11 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
@@ -47,6 +48,7 @@ import org.xml.sax.SAXException;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -56,15 +58,15 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
|
||||
/**
|
||||
* The list of suppression rules
|
||||
*/
|
||||
private List<SuppressionRule> rules;
|
||||
private SuppressionRule[] rules = null;
|
||||
|
||||
/**
|
||||
* Get the number of suppression rules.
|
||||
*
|
||||
* @return the number of suppression rules
|
||||
*/
|
||||
protected synchronized int getRuleCount() {
|
||||
return rules.size();
|
||||
protected int getRuleCount() {
|
||||
return rules.length;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,17 +85,19 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
|
||||
* @throws InitializationException thrown if there is an exception
|
||||
*/
|
||||
@Override
|
||||
public void initializeAnalyzer(Engine engine) throws InitializationException {
|
||||
try {
|
||||
loadSuppressionData();
|
||||
} catch (SuppressionParseException ex) {
|
||||
throw new InitializationException("Error initializing the suppression analyzer: " + ex.getLocalizedMessage(), ex);
|
||||
public synchronized void initializeAnalyzer(Engine engine) throws InitializationException {
|
||||
if (rules == null) {
|
||||
try {
|
||||
rules = loadSuppressionData();
|
||||
} catch (SuppressionParseException ex) {
|
||||
throw new InitializationException("Error initializing the suppression analyzer: " + ex.getLocalizedMessage(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
if (rules == null || rules.size() <= 0) {
|
||||
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
if (rules == null || rules.length <= 0) {
|
||||
return;
|
||||
}
|
||||
for (final SuppressionRule rule : rules) {
|
||||
@@ -104,40 +108,43 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
|
||||
/**
|
||||
* Loads all the suppression rules files configured in the {@link Settings}.
|
||||
*
|
||||
* @return the array of rules that were loaded
|
||||
* @throws SuppressionParseException thrown if the XML cannot be parsed.
|
||||
*/
|
||||
private synchronized void loadSuppressionData() throws SuppressionParseException {
|
||||
private SuppressionRule[] loadSuppressionData() throws SuppressionParseException {
|
||||
List<SuppressionRule> ruleList;
|
||||
final SuppressionParser parser = new SuppressionParser();
|
||||
try {
|
||||
final InputStream in = FileUtils.getResourceAsStream("dependencycheck-base-suppression.xml");
|
||||
rules = Collections.synchronizedList(parser.parseSuppressionRules(in));
|
||||
ruleList = parser.parseSuppressionRules(in);
|
||||
} catch (SAXException ex) {
|
||||
throw new SuppressionParseException("Unable to parse the base suppression data file", ex);
|
||||
}
|
||||
final String[] suppressionFilePaths = getSettings().getArray(Settings.KEYS.SUPPRESSION_FILE);
|
||||
if (suppressionFilePaths == null || suppressionFilePaths.length == 0) {
|
||||
return;
|
||||
if (suppressionFilePaths != null && suppressionFilePaths.length > 0) {
|
||||
// Load all the suppression file paths
|
||||
for (final String suppressionFilePath : suppressionFilePaths) {
|
||||
ruleList.addAll(loadSuppressionFile(parser, suppressionFilePath));
|
||||
}
|
||||
}
|
||||
|
||||
// Load all the suppression file paths
|
||||
for (final String suppressionFilePath : suppressionFilePaths) {
|
||||
loadSuppressionFile(parser, suppressionFilePath);
|
||||
}
|
||||
LOGGER.debug("{} suppression rules were loaded.", rules.size());
|
||||
LOGGER.debug("{} suppression rules were loaded.", ruleList.size());
|
||||
return ruleList.toArray(new SuppressionRule[ruleList.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a single suppression rules file from the path provided using the
|
||||
* parser provided.
|
||||
*
|
||||
* @param parser the parser to use for loading the file.
|
||||
* @param suppressionFilePath the path to load.
|
||||
* @param parser the parser to use for loading the file
|
||||
* @param suppressionFilePath the path to load
|
||||
* @return the list of loaded suppression rules
|
||||
* @throws SuppressionParseException thrown if the suppression file cannot
|
||||
* be loaded and parsed.
|
||||
*/
|
||||
private synchronized void loadSuppressionFile(final SuppressionParser parser, final String suppressionFilePath) throws SuppressionParseException {
|
||||
private List<SuppressionRule> loadSuppressionFile(final SuppressionParser parser,
|
||||
final String suppressionFilePath) throws SuppressionParseException {
|
||||
LOGGER.debug("Loading suppression rules from '{}'", suppressionFilePath);
|
||||
|
||||
final List<SuppressionRule> list = new ArrayList<>();
|
||||
File file = null;
|
||||
boolean deleteTempFile = false;
|
||||
try {
|
||||
@@ -146,7 +153,7 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
|
||||
deleteTempFile = true;
|
||||
file = getSettings().getTempFile("suppression", "xml");
|
||||
final URL url = new URL(suppressionFilePath);
|
||||
Downloader downloader = new Downloader(getSettings());
|
||||
final Downloader downloader = new Downloader(getSettings());
|
||||
try {
|
||||
downloader.fetchFile(url, file, false);
|
||||
} catch (DownloadFailedException ex) {
|
||||
@@ -177,7 +184,7 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
|
||||
throw new SuppressionParseException(msg);
|
||||
}
|
||||
try {
|
||||
rules.addAll(parser.parseSuppressionRules(file));
|
||||
list.addAll(parser.parseSuppressionRules(file));
|
||||
} catch (SuppressionParseException ex) {
|
||||
LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath());
|
||||
LOGGER.warn(ex.getMessage());
|
||||
@@ -197,6 +204,7 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
|
||||
FileUtils.delete(file);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,10 +27,10 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
* <p>
|
||||
* An interface that defines an Analyzer that is used to identify Dependencies.
|
||||
* An analyzer will collect information about the dependency in the form of
|
||||
* Evidence.<p>
|
||||
* Evidence.</p>
|
||||
* <p>
|
||||
* When the {@link org.owasp.dependencycheck.Engine} executes it will load the
|
||||
* analyzers and call the methods in the following order:
|
||||
* analyzers and call the methods in the following order:</p>
|
||||
* <ol>
|
||||
* <li>{@link #initializeSettings(org.owasp.dependencycheck.utils.Settings)}</li>
|
||||
* <li>{@link #initialize(org.owasp.dependencycheck.Engine)}</li>
|
||||
@@ -75,7 +75,7 @@ public interface Analyzer {
|
||||
*
|
||||
* @param settings the configured settings
|
||||
*/
|
||||
public void initializeSettings(Settings settings);
|
||||
void initializeSettings(Settings settings);
|
||||
|
||||
/**
|
||||
* The initialize method is called (once) prior to the analyze method being
|
||||
|
||||
@@ -24,13 +24,15 @@ import static java.util.Arrays.asList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* The Analyzer Service Loader. This class loads all services that implement
|
||||
* org.owasp.dependencycheck.analyzer.Analyzer.
|
||||
* {@link org.owasp.dependencycheck.analyzer.Analyzer}.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class AnalyzerService {
|
||||
|
||||
/**
|
||||
|
||||
@@ -111,7 +111,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
* Detects files with .zip extension.
|
||||
*/
|
||||
private static final FileFilter ZIP_FILTER = FileFilterBuilder.newInstance().addExtensions("zip").build();
|
||||
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
|
||||
/**
|
||||
* The name of the analyzer.
|
||||
@@ -121,6 +121,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
* The phase that this analyzer is intended to run in.
|
||||
*/
|
||||
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL;
|
||||
|
||||
/**
|
||||
* Initializes the analyzer with the configured settings.
|
||||
*
|
||||
@@ -289,9 +290,9 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
if (REMOVE_FROM_ANALYSIS.accept(dependency.getActualFile())) {
|
||||
addDisguisedJarsToDependencies(dependency, engine);
|
||||
engine.getDependencies().remove(dependency);
|
||||
engine.removeDependency(dependency);
|
||||
}
|
||||
Collections.sort(engine.getDependencies());
|
||||
engine.sortDependencies();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,6 +43,7 @@ import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
@@ -55,6 +56,7 @@ import org.owasp.dependencycheck.utils.XmlUtils;
|
||||
* @author colezlaw
|
||||
*
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -111,20 +113,16 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
* @throws AnalysisException if anything goes sideways
|
||||
*/
|
||||
@Override
|
||||
public void analyzeDependency(Dependency dependency, Engine engine)
|
||||
throws AnalysisException {
|
||||
|
||||
public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
final File test = new File(dependency.getActualFilePath());
|
||||
if (!test.isFile()) {
|
||||
throw new AnalysisException(String.format("%s does not exist and cannot be analyzed by dependency-check",
|
||||
dependency.getActualFilePath()));
|
||||
}
|
||||
|
||||
if (grokAssemblyExe == null) {
|
||||
LOGGER.warn("GrokAssembly didn't get deployed");
|
||||
return;
|
||||
}
|
||||
|
||||
final List<String> args = buildArgumentList();
|
||||
if (args == null) {
|
||||
LOGGER.warn("Assembly Analyzer was unable to execute");
|
||||
@@ -199,8 +197,6 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
LOGGER.error("----------------------------------------------------");
|
||||
throw new AnalysisException("Couldn't parse Assembly Analyzer results (GrokAssembly)", saxe);
|
||||
}
|
||||
// This shouldn't happen
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -176,7 +176,7 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
engine.getDependencies().remove(dependency);
|
||||
engine.removeDependency(dependency);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
final MessageDigest sha1 = getSha1MessageDigest();
|
||||
currentDep.setSha1sum(Checksum.getHex(sha1.digest(path)));
|
||||
engine.getDependencies().add(currentDep);
|
||||
engine.addDependency(currentDep);
|
||||
}
|
||||
final String source = currentDep.getDisplayFileName();
|
||||
currentDep.getProductEvidence().addEvidence(source, "Product",
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
import org.apache.lucene.analysis.util.CharArraySet;
|
||||
import org.apache.lucene.document.Document;
|
||||
@@ -63,6 +64,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class CPEAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -92,6 +94,10 @@ public class CPEAnalyzer extends AbstractAnalyzer {
|
||||
* data that will be written into the string.
|
||||
*/
|
||||
private static final int STRING_BUILDER_BUFFER = 20;
|
||||
/**
|
||||
* The URL to perform a search of the NVD CVE data at NIST.
|
||||
*/
|
||||
public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s";
|
||||
/**
|
||||
* The CPE in memory index.
|
||||
*/
|
||||
@@ -101,11 +107,6 @@ public class CPEAnalyzer extends AbstractAnalyzer {
|
||||
*/
|
||||
private CveDB cve;
|
||||
|
||||
/**
|
||||
* The URL to perform a search of the NVD CVE data at NIST.
|
||||
*/
|
||||
public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s";
|
||||
|
||||
/**
|
||||
* Returns the name of this analyzer.
|
||||
*
|
||||
@@ -126,18 +127,18 @@ public class CPEAnalyzer extends AbstractAnalyzer {
|
||||
return AnalysisPhase.IDENTIFIER_ANALYSIS;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default is to support parallel processing.
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParallelProcessing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * The default is to support parallel processing.
|
||||
// *
|
||||
// * @return false
|
||||
// */
|
||||
// @Override
|
||||
// public boolean supportsParallelProcessing() {
|
||||
// return false;
|
||||
// }
|
||||
/**
|
||||
* Creates the CPE Lucene Index.
|
||||
*
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException is thrown if there is an issue opening
|
||||
* the index.
|
||||
@@ -164,7 +165,7 @@ public class CPEAnalyzer extends AbstractAnalyzer {
|
||||
* @throws DatabaseException when the database throws an exception. This
|
||||
* usually occurs when the database is in use by another process.
|
||||
*/
|
||||
public void open(CveDB cve) throws IOException, DatabaseException {
|
||||
public synchronized void open(CveDB cve) throws IOException, DatabaseException {
|
||||
if (!isOpen()) {
|
||||
this.cve = cve;
|
||||
this.cpe = CpeMemoryIndex.getInstance();
|
||||
@@ -185,10 +186,6 @@ public class CPEAnalyzer extends AbstractAnalyzer {
|
||||
*/
|
||||
@Override
|
||||
public void closeAnalyzer() {
|
||||
if (cve != null) {
|
||||
cve.close();
|
||||
cve = null;
|
||||
}
|
||||
if (cpe != null) {
|
||||
cpe.close();
|
||||
cpe = null;
|
||||
@@ -490,7 +487,7 @@ public class CPEAnalyzer extends AbstractAnalyzer {
|
||||
final String[] words = text.split("[\\s_-]");
|
||||
final List<String> list = new ArrayList<>();
|
||||
String tempWord = null;
|
||||
CharArraySet stopWords = SearchFieldAnalyzer.getStopWords();
|
||||
final CharArraySet stopWords = SearchFieldAnalyzer.getStopWords();
|
||||
for (String word : words) {
|
||||
if (stopWords.contains(word)) {
|
||||
continue;
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
import org.owasp.dependencycheck.utils.DownloadFailedException;
|
||||
import org.owasp.dependencycheck.utils.Downloader;
|
||||
@@ -49,6 +50,7 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -232,7 +234,7 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
LOGGER.debug("Unable to delete temp file");
|
||||
}
|
||||
LOGGER.debug("Downloading {}", ma.getPomUrl());
|
||||
Downloader downloader = new Downloader(getSettings());
|
||||
final Downloader downloader = new Downloader(getSettings());
|
||||
downloader.fetchFile(new URL(ma.getPomUrl()), pomFile);
|
||||
PomUtils.analyzePOM(dependency, pomFile);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
@@ -41,6 +42,7 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
* @author Bianca Jiang (https://twitter.com/biancajiang)
|
||||
*/
|
||||
@Experimental
|
||||
@ThreadSafe
|
||||
public class CocoaPodsAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
|
||||
@@ -117,7 +117,7 @@ public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
d.getProductEvidence().addEvidence(COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST);
|
||||
d.getVersionEvidence().addEvidence(COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST);
|
||||
LOGGER.info("Adding dependency {}", d);
|
||||
engine.getDependencies().add(d);
|
||||
engine.addDependency(d);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.warn("Error opening dependency {}", dependency.getActualFilePath());
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
@@ -26,6 +27,7 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class CpeSuppressionAnalyzer extends AbstractSuppressionAnalyzer {
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,14 +18,11 @@
|
||||
package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.dependency.Identifier;
|
||||
import org.owasp.dependencycheck.utils.DependencyVersion;
|
||||
@@ -47,37 +44,19 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class DependencyBundlingAnalyzer extends AbstractAnalyzer {
|
||||
@ThreadSafe
|
||||
public class DependencyBundlingAnalyzer extends AbstractDependencyComparingAnalyzer {
|
||||
|
||||
/**
|
||||
* The Logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DependencyBundlingAnalyzer.class);
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="Constants and Member Variables">
|
||||
/**
|
||||
* A pattern for obtaining the first part of a filename.
|
||||
*/
|
||||
private static final Pattern STARTING_TEXT_PATTERN = Pattern.compile("^[a-zA-Z0-9]*");
|
||||
|
||||
/**
|
||||
* a flag indicating if this analyzer has run. This analyzer only runs once.
|
||||
*/
|
||||
private boolean analyzed = false;
|
||||
|
||||
/**
|
||||
* Returns a flag indicating if this analyzer has run. This analyzer only
|
||||
* runs once. Note this is currently only used in the unit tests.
|
||||
*
|
||||
* @return a flag indicating if this analyzer has run. This analyzer only
|
||||
* runs once
|
||||
*/
|
||||
protected synchronized boolean getAnalyzed() {
|
||||
return analyzed;
|
||||
}
|
||||
|
||||
//</editor-fold>
|
||||
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
|
||||
/**
|
||||
* The name of the analyzer.
|
||||
*/
|
||||
@@ -106,19 +85,6 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer {
|
||||
public AnalysisPhase getAnalysisPhase() {
|
||||
return ANALYSIS_PHASE;
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
/**
|
||||
* Does not support parallel processing as it only runs once and then
|
||||
* operates on <em>all</em> dependencies.
|
||||
*
|
||||
* @return whether or not parallel processing is enabled
|
||||
* @see #analyze(Dependency, Engine)
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParallelProcessing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -132,65 +98,46 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes a set of dependencies. If they have been found to have the same
|
||||
* base path and the same set of identifiers they are likely related. The
|
||||
* related dependencies are bundled into a single reportable item.
|
||||
* Evaluates the dependencies
|
||||
*
|
||||
* @param ignore this analyzer ignores the dependency being analyzed
|
||||
* @param engine the engine that is scanning the dependencies
|
||||
* @throws AnalysisException is thrown if there is an error reading the JAR
|
||||
* file.
|
||||
* @param dependency a dependency to compare
|
||||
* @param nextDependency a dependency to compare
|
||||
* @param dependenciesToRemove a set of dependencies that will be removed
|
||||
* @return true if a dependency is removed; otherwise false
|
||||
*/
|
||||
@Override
|
||||
protected synchronized void analyzeDependency(Dependency ignore, Engine engine) throws AnalysisException {
|
||||
if (!analyzed) {
|
||||
analyzed = true;
|
||||
final Set<Dependency> dependenciesToRemove = new HashSet<>();
|
||||
final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator();
|
||||
//for (Dependency nextDependency : engine.getDependencies()) {
|
||||
while (mainIterator.hasNext()) {
|
||||
final Dependency dependency = mainIterator.next();
|
||||
if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) {
|
||||
final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
|
||||
while (subIterator.hasNext()) {
|
||||
final Dependency nextDependency = subIterator.next();
|
||||
if (hashesMatch(dependency, nextDependency)) {
|
||||
if (!containedInWar(dependency.getFilePath())
|
||||
&& !containedInWar(nextDependency.getFilePath())) {
|
||||
if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
|
||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||
} else {
|
||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||
}
|
||||
}
|
||||
} else if (isShadedJar(dependency, nextDependency)) {
|
||||
if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
|
||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||
nextDependency.getRelatedDependencies().remove(dependency);
|
||||
break;
|
||||
} else {
|
||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||
dependency.getRelatedDependencies().remove(nextDependency);
|
||||
}
|
||||
} else if (cpeIdentifiersMatch(dependency, nextDependency)
|
||||
&& hasSameBasePath(dependency, nextDependency)
|
||||
&& vulnCountMatches(dependency, nextDependency)
|
||||
&& fileNameMatch(dependency, nextDependency)) {
|
||||
if (isCore(dependency, nextDependency)) {
|
||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||
} else {
|
||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||
}
|
||||
}
|
||||
}
|
||||
protected boolean evaluateDependencies(final Dependency dependency, final Dependency nextDependency, final Set<Dependency> dependenciesToRemove) {
|
||||
if (hashesMatch(dependency, nextDependency)) {
|
||||
if (!containedInWar(dependency.getFilePath())
|
||||
&& !containedInWar(nextDependency.getFilePath())) {
|
||||
if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
|
||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||
} else {
|
||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||
return true; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||
}
|
||||
}
|
||||
//removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
|
||||
// was difficult because of the inner iterator.
|
||||
engine.getDependencies().removeAll(dependenciesToRemove);
|
||||
} else if (isShadedJar(dependency, nextDependency)) {
|
||||
if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
|
||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||
nextDependency.getRelatedDependencies().remove(dependency);
|
||||
return true;
|
||||
} else {
|
||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||
dependency.getRelatedDependencies().remove(nextDependency);
|
||||
}
|
||||
} else if (cpeIdentifiersMatch(dependency, nextDependency)
|
||||
&& hasSameBasePath(dependency, nextDependency)
|
||||
&& vulnCountMatches(dependency, nextDependency)
|
||||
&& fileNameMatch(dependency, nextDependency)) {
|
||||
if (isCore(dependency, nextDependency)) {
|
||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||
} else {
|
||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||
return true; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,12 +18,8 @@
|
||||
package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.slf4j.Logger;
|
||||
@@ -36,31 +32,12 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class DependencyMergingAnalyzer extends AbstractAnalyzer {
|
||||
public class DependencyMergingAnalyzer extends AbstractDependencyComparingAnalyzer {
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="Constants and Member Variables">
|
||||
/**
|
||||
* The Logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DependencyMergingAnalyzer.class);
|
||||
/**
|
||||
* a flag indicating if this analyzer has run. This analyzer only runs once.
|
||||
*/
|
||||
private boolean analyzed = false;
|
||||
|
||||
/**
|
||||
* Returns a flag indicating if this analyzer has run. This analyzer only
|
||||
* runs once. Note this is currently only used in the unit tests.
|
||||
*
|
||||
* @return a flag indicating if this analyzer has run. This analyzer only
|
||||
* runs once
|
||||
*/
|
||||
protected synchronized boolean getAnalyzed() {
|
||||
return analyzed;
|
||||
}
|
||||
|
||||
//</editor-fold>
|
||||
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
|
||||
/**
|
||||
* The name of the analyzer.
|
||||
*/
|
||||
@@ -90,18 +67,6 @@ public class DependencyMergingAnalyzer extends AbstractAnalyzer {
|
||||
return ANALYSIS_PHASE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not support parallel processing as it only runs once and then
|
||||
* operates on <em>all</em> dependencies.
|
||||
*
|
||||
* @return whether or not parallel processing is enabled
|
||||
* @see #analyze(Dependency, Engine)
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParallelProcessing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Returns the setting key to determine if the analyzer is enabled.</p>
|
||||
@@ -112,55 +77,34 @@ public class DependencyMergingAnalyzer extends AbstractAnalyzer {
|
||||
protected String getAnalyzerEnabledSettingKey() {
|
||||
return Settings.KEYS.ANALYZER_DEPENDENCY_MERGING_ENABLED;
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
/**
|
||||
* Analyzes a set of dependencies. If they have been found to be the same
|
||||
* dependency created by more multiple FileTypeAnalyzers (i.e. a gemspec
|
||||
* dependency and a dependency from the Bundle Audit Analyzer. The
|
||||
* dependencies are then merged into a single reportable item.
|
||||
* Evaluates the dependencies
|
||||
*
|
||||
* @param ignore this analyzer ignores the dependency being analyzed
|
||||
* @param engine the engine that is scanning the dependencies
|
||||
* @throws AnalysisException is thrown if there is an error reading the JAR
|
||||
* file.
|
||||
* @param dependency a dependency to compare
|
||||
* @param nextDependency a dependency to compare
|
||||
* @param dependenciesToRemove a set of dependencies that will be removed
|
||||
* @return true if a dependency is removed; otherwise false
|
||||
*/
|
||||
@Override
|
||||
protected synchronized void analyzeDependency(Dependency ignore, Engine engine) throws AnalysisException {
|
||||
if (!analyzed) {
|
||||
analyzed = true;
|
||||
final Set<Dependency> dependenciesToRemove = new HashSet<>();
|
||||
final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator();
|
||||
//for (Dependency nextDependency : engine.getDependencies()) {
|
||||
while (mainIterator.hasNext()) {
|
||||
final Dependency dependency = mainIterator.next();
|
||||
if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) {
|
||||
final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
|
||||
while (subIterator.hasNext()) {
|
||||
final Dependency nextDependency = subIterator.next();
|
||||
Dependency main;
|
||||
if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) {
|
||||
if (main == dependency) {
|
||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||
} else {
|
||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||
}
|
||||
} else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) {
|
||||
if (main == dependency) {
|
||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||
} else {
|
||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected boolean evaluateDependencies(final Dependency dependency, final Dependency nextDependency, final Set<Dependency> dependenciesToRemove) {
|
||||
Dependency main;
|
||||
if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) {
|
||||
if (main == dependency) {
|
||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||
} else {
|
||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||
return true; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||
}
|
||||
} else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) {
|
||||
if (main == dependency) {
|
||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||
} else {
|
||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||
return true; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||
}
|
||||
//removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
|
||||
// was difficult because of the inner iterator.
|
||||
engine.getDependencies().removeAll(dependenciesToRemove);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
@@ -44,6 +45,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class FalsePositiveAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -155,8 +157,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mustContain
|
||||
!= null) {
|
||||
if (mustContain != null) {
|
||||
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
|
||||
while (itr.hasNext()) {
|
||||
final Identifier i = itr.next();
|
||||
@@ -444,7 +445,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
|
||||
String parentPath = dependency.getFilePath().toLowerCase();
|
||||
if (parentPath.contains(".jar")) {
|
||||
parentPath = parentPath.substring(0, parentPath.indexOf(".jar") + 4);
|
||||
final List<Dependency> dependencies = engine.getDependencies();
|
||||
final Dependency[] dependencies = engine.getDependencies();
|
||||
final Dependency parent = findDependency(parentPath, dependencies);
|
||||
if (parent != null) {
|
||||
boolean remove = false;
|
||||
@@ -462,7 +463,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
|
||||
}
|
||||
}
|
||||
if (remove) {
|
||||
dependencies.remove(dependency);
|
||||
engine.removeDependency(dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -474,10 +475,10 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
|
||||
* dependencies.
|
||||
*
|
||||
* @param dependencyPath the path of the dependency to return
|
||||
* @param dependencies the collection of dependencies to search
|
||||
* @param dependencies the array of dependencies to search
|
||||
* @return the dependency object for the given path, otherwise null
|
||||
*/
|
||||
private Dependency findDependency(String dependencyPath, List<Dependency> dependencies) {
|
||||
private Dependency findDependency(String dependencyPath, Dependency[] dependencies) {
|
||||
for (Dependency d : dependencies) {
|
||||
if (d.getFilePath().equalsIgnoreCase(dependencyPath)) {
|
||||
return d;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import java.io.File;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.io.filefilter.NameFileFilter;
|
||||
@@ -30,11 +31,11 @@ import org.owasp.dependencycheck.utils.DependencyVersionUtil;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
*
|
||||
* Takes a dependency and analyzes the filename and determines the hashes.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class FileNameAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -76,6 +77,7 @@ public class FileNameAnalyzer extends AbstractAnalyzer {
|
||||
public AnalysisPhase getAnalysisPhase() {
|
||||
return ANALYSIS_PHASE;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Returns the setting key to determine if the analyzer is enabled.</p>
|
||||
|
||||
@@ -26,6 +26,8 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
@@ -40,7 +42,6 @@ import org.owasp.dependencycheck.xml.hints.VendorDuplicatingHintRule;
|
||||
import org.owasp.dependencycheck.xml.hints.HintParseException;
|
||||
import org.owasp.dependencycheck.xml.hints.HintParser;
|
||||
import org.owasp.dependencycheck.xml.hints.HintRule;
|
||||
import org.owasp.dependencycheck.xml.hints.Hints;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xml.sax.SAXException;
|
||||
@@ -51,6 +52,7 @@ import org.xml.sax.SAXException;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class HintAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -62,11 +64,14 @@ public class HintAnalyzer extends AbstractAnalyzer {
|
||||
*/
|
||||
private static final String HINT_RULE_FILE_NAME = "dependencycheck-base-hint.xml";
|
||||
/**
|
||||
* The collection of hints.
|
||||
* The array of hint rules.
|
||||
*/
|
||||
private Hints hints;
|
||||
private HintRule[] hints = null;
|
||||
/**
|
||||
* The array of vendor duplicating hint rules.
|
||||
*/
|
||||
private VendorDuplicatingHintRule[] vendorHints;
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
|
||||
/**
|
||||
* The name of the analyzer.
|
||||
*/
|
||||
@@ -122,7 +127,6 @@ public class HintAnalyzer extends AbstractAnalyzer {
|
||||
throw new InitializationException("Unable to parse the hint file", ex);
|
||||
}
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
/**
|
||||
* The HintAnalyzer uses knowledge about a dependency to add additional
|
||||
@@ -135,7 +139,7 @@ public class HintAnalyzer extends AbstractAnalyzer {
|
||||
*/
|
||||
@Override
|
||||
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
for (HintRule hint : hints.getHintRules()) {
|
||||
for (HintRule hint : hints) {
|
||||
boolean matchFound = false;
|
||||
for (Evidence given : hint.getGivenVendor()) {
|
||||
if (dependency.getVendorEvidence().getEvidence().contains(given)) {
|
||||
@@ -199,7 +203,7 @@ public class HintAnalyzer extends AbstractAnalyzer {
|
||||
final List<Evidence> newEntries = new ArrayList<>();
|
||||
while (itr.hasNext()) {
|
||||
final Evidence e = itr.next();
|
||||
for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) {
|
||||
for (VendorDuplicatingHintRule dhr : vendorHints) {
|
||||
if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) {
|
||||
newEntries.add(new Evidence(e.getSource() + " (hint)",
|
||||
e.getName(), dhr.getDuplicate(), e.getConfidence()));
|
||||
@@ -217,71 +221,79 @@ public class HintAnalyzer extends AbstractAnalyzer {
|
||||
* @throws HintParseException thrown if the XML cannot be parsed.
|
||||
*/
|
||||
private void loadHintRules() throws HintParseException {
|
||||
final HintParser parser = new HintParser();
|
||||
File file = null;
|
||||
try {
|
||||
hints = parser.parseHints(FileUtils.getResourceAsStream(HINT_RULE_FILE_NAME));
|
||||
} catch (HintParseException | SAXException ex) {
|
||||
LOGGER.error("Unable to parse the base hint data file");
|
||||
LOGGER.debug("Unable to parse the base hint data file", ex);
|
||||
}
|
||||
final String filePath = getSettings().getString(Settings.KEYS.HINTS_FILE);
|
||||
if (filePath == null) {
|
||||
return;
|
||||
}
|
||||
boolean deleteTempFile = false;
|
||||
try {
|
||||
final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
|
||||
if (uriRx.matcher(filePath).matches()) {
|
||||
deleteTempFile = true;
|
||||
file = getSettings().getTempFile("hint", "xml");
|
||||
final URL url = new URL(filePath);
|
||||
Downloader downloader = new Downloader(getSettings());
|
||||
try {
|
||||
downloader.fetchFile(url, file, false);
|
||||
} catch (DownloadFailedException ex) {
|
||||
downloader.fetchFile(url, file, true);
|
||||
}
|
||||
} else {
|
||||
file = new File(filePath);
|
||||
if (!file.exists()) {
|
||||
try (InputStream fromClasspath = FileUtils.getResourceAsStream(filePath)) {
|
||||
if (fromClasspath != null) {
|
||||
deleteTempFile = true;
|
||||
file = getSettings().getTempFile("hint", "xml");
|
||||
try {
|
||||
org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file);
|
||||
} catch (IOException ex) {
|
||||
throw new HintParseException("Unable to locate hints file in classpath", ex);
|
||||
if (hints == null) {
|
||||
final HintParser parser = new HintParser();
|
||||
File file = null;
|
||||
try {
|
||||
parser.parseHints(FileUtils.getResourceAsStream(HINT_RULE_FILE_NAME));
|
||||
hints = parser.getHintRules();
|
||||
vendorHints = parser.getVendorDuplicatingHintRules();
|
||||
} catch (HintParseException | SAXException ex) {
|
||||
LOGGER.error("Unable to parse the base hint data file");
|
||||
LOGGER.debug("Unable to parse the base hint data file", ex);
|
||||
}
|
||||
final String filePath = getSettings().getString(Settings.KEYS.HINTS_FILE);
|
||||
if (filePath == null) {
|
||||
return;
|
||||
}
|
||||
boolean deleteTempFile = false;
|
||||
try {
|
||||
final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
|
||||
if (uriRx.matcher(filePath).matches()) {
|
||||
deleteTempFile = true;
|
||||
file = getSettings().getTempFile("hint", "xml");
|
||||
final URL url = new URL(filePath);
|
||||
final Downloader downloader = new Downloader(getSettings());
|
||||
try {
|
||||
downloader.fetchFile(url, file, false);
|
||||
} catch (DownloadFailedException ex) {
|
||||
downloader.fetchFile(url, file, true);
|
||||
}
|
||||
} else {
|
||||
file = new File(filePath);
|
||||
if (!file.exists()) {
|
||||
try (InputStream fromClasspath = FileUtils.getResourceAsStream(filePath)) {
|
||||
if (fromClasspath != null) {
|
||||
deleteTempFile = true;
|
||||
file = getSettings().getTempFile("hint", "xml");
|
||||
try {
|
||||
org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file);
|
||||
} catch (IOException ex) {
|
||||
throw new HintParseException("Unable to locate hints file in classpath", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (file != null) {
|
||||
try {
|
||||
final Hints newHints = parser.parseHints(file);
|
||||
hints.getHintRules().addAll(newHints.getHintRules());
|
||||
hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules());
|
||||
LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size());
|
||||
LOGGER.debug("{} duplicating hint rules were loaded.", hints.getVendorDuplicatingHintRules().size());
|
||||
} catch (HintParseException ex) {
|
||||
LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath());
|
||||
LOGGER.warn(ex.getMessage());
|
||||
LOGGER.debug("", ex);
|
||||
throw ex;
|
||||
if (file != null) {
|
||||
try {
|
||||
parser.parseHints(file);
|
||||
if (parser.getHintRules() != null && parser.getHintRules().length > 0) {
|
||||
hints = (HintRule[]) ArrayUtils.addAll(hints, parser.getHintRules());
|
||||
}
|
||||
if (parser.getVendorDuplicatingHintRules() != null && parser.getVendorDuplicatingHintRules().length > 0) {
|
||||
vendorHints = (VendorDuplicatingHintRule[]) ArrayUtils.addAll(vendorHints, parser.getVendorDuplicatingHintRules());
|
||||
}
|
||||
LOGGER.debug("{} hint rules were loaded.", hints.length);
|
||||
LOGGER.debug("{} duplicating hint rules were loaded.", vendorHints.length);
|
||||
} catch (HintParseException ex) {
|
||||
LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath());
|
||||
LOGGER.warn(ex.getMessage());
|
||||
LOGGER.debug("", ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
} catch (DownloadFailedException ex) {
|
||||
throw new HintParseException("Unable to fetch the configured hint file", ex);
|
||||
} catch (MalformedURLException ex) {
|
||||
throw new HintParseException("Configured hint file has an invalid URL", ex);
|
||||
} catch (IOException ex) {
|
||||
throw new HintParseException("Unable to create temp file for hints", ex);
|
||||
} finally {
|
||||
if (deleteTempFile && file != null) {
|
||||
FileUtils.delete(file);
|
||||
}
|
||||
}
|
||||
} catch (DownloadFailedException ex) {
|
||||
throw new HintParseException("Unable to fetch the configured hint file", ex);
|
||||
} catch (MalformedURLException ex) {
|
||||
throw new HintParseException("Configured hint file has an invalid URL", ex);
|
||||
} catch (IOException ex) {
|
||||
throw new HintParseException("Unable to create temp file for hints", ex);
|
||||
} finally {
|
||||
if (deleteTempFile && file != null) {
|
||||
FileUtils.delete(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|| fileName.endsWith("-doc.jar")
|
||||
|| isMacOSMetaDataFile(dependency, engine))
|
||||
|| !isZipFile(dependency)) {
|
||||
engine.getDependencies().remove(dependency);
|
||||
engine.removeDependency(dependency);
|
||||
return;
|
||||
}
|
||||
final boolean hasManifest = parseManifest(dependency, classNames);
|
||||
@@ -289,7 +289,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
* @return whether or not the given dependencies contain a dependency with
|
||||
* the given filename
|
||||
*/
|
||||
private boolean hasDependencyWithFilename(final List<Dependency> dependencies, final String fileName) {
|
||||
private boolean hasDependencyWithFilename(final Dependency[] dependencies, final String fileName) {
|
||||
for (final Dependency dependency : dependencies) {
|
||||
if (Paths.get(dependency.getActualFilePath()).getFileName().toString().toLowerCase()
|
||||
.equals(fileName.toLowerCase())) {
|
||||
@@ -386,7 +386,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
newDependency.setFileName(displayName);
|
||||
newDependency.setFilePath(displayPath);
|
||||
setPomEvidence(newDependency, pom, null);
|
||||
engine.getDependencies().add(newDependency);
|
||||
engine.addDependency(newDependency);
|
||||
} catch (AnalysisException ex) {
|
||||
LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath());
|
||||
LOGGER.trace("", ex);
|
||||
@@ -700,6 +700,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
value = Jsoup.parse(value).text();
|
||||
}
|
||||
if (IGNORE_VALUES.contains(value)) {
|
||||
//noinspection UnnecessaryContinue
|
||||
continue;
|
||||
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
|
||||
foundSomething = true;
|
||||
@@ -733,6 +734,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
foundSomething = true;
|
||||
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
||||
} else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) {
|
||||
//noinspection UnnecessaryContinue
|
||||
continue;
|
||||
//skipping main class as if this has important information to add it will be added during class name analysis...
|
||||
} else {
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
import org.owasp.dependencycheck.utils.DownloadFailedException;
|
||||
import org.owasp.dependencycheck.utils.Downloader;
|
||||
@@ -59,6 +60,7 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -251,7 +253,7 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
LOGGER.debug("Unable to delete temp file");
|
||||
}
|
||||
LOGGER.debug("Downloading {}", ma.getPomUrl());
|
||||
Downloader downloader = new Downloader(getSettings());
|
||||
final Downloader downloader = new Downloader(getSettings());
|
||||
downloader.fetchFile(new URL(ma.getPomUrl()), pomFile);
|
||||
PomUtils.analyzePOM(dependency, pomFile);
|
||||
} catch (DownloadFailedException ex) {
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.json.Json;
|
||||
import javax.json.JsonException;
|
||||
import javax.json.JsonObject;
|
||||
@@ -47,6 +48,7 @@ import org.owasp.dependencycheck.exception.InitializationException;
|
||||
* @author Dale Visser
|
||||
*/
|
||||
@Experimental
|
||||
@ThreadSafe
|
||||
public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,11 +37,11 @@ import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.json.Json;
|
||||
import javax.json.JsonArray;
|
||||
import javax.json.JsonException;
|
||||
@@ -59,6 +59,7 @@ import org.owasp.dependencycheck.utils.URLConnectionFailureException;
|
||||
*
|
||||
* @author Steve Springett
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class NspAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -284,11 +285,11 @@ public class NspAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
* @param depType the dependency type
|
||||
*/
|
||||
private void processPackage(Dependency dependency, JsonArray jsonArray, String depType) {
|
||||
JsonObjectBuilder builder = Json.createObjectBuilder();
|
||||
final JsonObjectBuilder builder = Json.createObjectBuilder();
|
||||
for (JsonString str : jsonArray.getValuesAs(JsonString.class)) {
|
||||
builder.add(str.toString(), "");
|
||||
}
|
||||
JsonObject jsonObject = builder.build();
|
||||
final JsonObject jsonObject = builder.build();
|
||||
processPackage(dependency, jsonObject, depType);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,7 @@ import org.owasp.dependencycheck.exception.InitializationException;
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class NuspecAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,9 +17,8 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||
@@ -27,9 +26,7 @@ import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.dependency.Identifier;
|
||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* NvdCveAnalyzer is a utility class that takes a project dependency and
|
||||
@@ -38,36 +35,13 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class NvdCveAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
/**
|
||||
* The Logger for use throughout the class
|
||||
*/
|
||||
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(NvdCveAnalyzer.class);
|
||||
|
||||
/**
|
||||
* The CVE Index.
|
||||
*/
|
||||
private CveDB cveDB;
|
||||
|
||||
/**
|
||||
* Closes the data source.
|
||||
*/
|
||||
@Override
|
||||
public void closeAnalyzer() {
|
||||
cveDB.close();
|
||||
cveDB = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status of the data source - is the database open.
|
||||
*
|
||||
* @return true or false.
|
||||
*/
|
||||
public boolean isOpen() {
|
||||
return cveDB != null;
|
||||
}
|
||||
|
||||
//private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(NvdCveAnalyzer.class);
|
||||
/**
|
||||
* Analyzes a dependency and attempts to determine if there are any CPE
|
||||
* identifiers for this dependency.
|
||||
@@ -79,6 +53,7 @@ public class NvdCveAnalyzer extends AbstractAnalyzer {
|
||||
*/
|
||||
@Override
|
||||
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
final CveDB cveDB = engine.getDatabase();
|
||||
for (Identifier id : dependency.getIdentifiers()) {
|
||||
if ("cpe".equals(id.getType())) {
|
||||
try {
|
||||
@@ -133,16 +108,4 @@ public class NvdCveAnalyzer extends AbstractAnalyzer {
|
||||
protected String getAnalyzerEnabledSettingKey() {
|
||||
return Settings.KEYS.ANALYZER_NVD_CVE_ENABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the database used to gather NVD CVE data.
|
||||
*
|
||||
* @param engine a reference the dependency-check engine
|
||||
* @throws InitializationException is thrown if there is an issue opening
|
||||
* the index.
|
||||
*/
|
||||
@Override
|
||||
public void initializeAnalyzer(Engine engine) throws InitializationException {
|
||||
this.cveDB = engine.getDatabase();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
|
||||
/**
|
||||
@@ -38,6 +39,7 @@ import org.owasp.dependencycheck.exception.InitializationException;
|
||||
*
|
||||
* @author Dale Visser
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -143,6 +145,16 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
return OPENSSLV_FILTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setting for the analyzer enabled setting key.
|
||||
*
|
||||
* @return the setting for the analyzer enabled setting key
|
||||
*/
|
||||
@Override
|
||||
protected String getAnalyzerEnabledSettingKey() {
|
||||
return Settings.KEYS.ANALYZER_OPENSSL_ENABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* No-op initializer implementation.
|
||||
*
|
||||
@@ -182,7 +194,7 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
dependency.getVendorEvidence().addEvidence(OPENSSLV_H, "Vendor", "OpenSSL", Confidence.HIGHEST);
|
||||
dependency.getProductEvidence().addEvidence(OPENSSLV_H, "Product", "OpenSSL", Confidence.HIGHEST);
|
||||
} else {
|
||||
engine.getDependencies().remove(dependency);
|
||||
engine.removeDependency(dependency);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,14 +214,4 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
"Problem occurred while reading dependency file.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setting for the analyzer enabled setting key.
|
||||
*
|
||||
* @return the setting for the analyzer enabled setting key
|
||||
*/
|
||||
@Override
|
||||
protected String getAnalyzerEnabledSettingKey() {
|
||||
return Settings.KEYS.ANALYZER_OPENSSL_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.owasp.dependencycheck.utils.FileUtils;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.owasp.dependencycheck.utils.UrlStringUtils;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Used to analyze a Wheel or egg distribution files, or their contents in
|
||||
@@ -55,30 +56,26 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* @author Dale Visser
|
||||
*/
|
||||
@Experimental
|
||||
@ThreadSafe
|
||||
public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
* Name of egg metadata files to analyze.
|
||||
*/
|
||||
private static final String PKG_INFO = "PKG-INFO";
|
||||
|
||||
/**
|
||||
* Name of wheel metadata files to analyze.
|
||||
*/
|
||||
private static final String METADATA = "METADATA";
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory
|
||||
.getLogger(PythonDistributionAnalyzer.class);
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(PythonDistributionAnalyzer.class);
|
||||
/**
|
||||
* The count of directories created during analysis. This is used for
|
||||
* creating temporary directories.
|
||||
*/
|
||||
private static final AtomicInteger DIR_COUNT = new AtomicInteger(0);
|
||||
|
||||
/**
|
||||
* The name of the analyzer.
|
||||
*/
|
||||
@@ -87,52 +84,39 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
* The phase that this analyzer is intended to run in.
|
||||
*/
|
||||
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
|
||||
|
||||
/**
|
||||
* The set of file extensions supported by this analyzer.
|
||||
*/
|
||||
private static final String[] EXTENSIONS = {"whl", "egg", "zip"};
|
||||
|
||||
/**
|
||||
* Used to match on egg archive candidate extensions.
|
||||
*/
|
||||
private static final FileFilter EGG_OR_ZIP = FileFilterBuilder.newInstance().addExtensions("egg", "zip").build();
|
||||
|
||||
/**
|
||||
* Used to detect files with a .whl extension.
|
||||
*/
|
||||
private static final FileFilter WHL_FILTER = FileFilterBuilder.newInstance().addExtensions("whl").build();
|
||||
|
||||
/**
|
||||
* The parent directory for the individual directories per archive.
|
||||
*/
|
||||
private File tempFileLocation;
|
||||
|
||||
/**
|
||||
* Filter that detects *.dist-info files (but doesn't verify they are
|
||||
* directories.
|
||||
*/
|
||||
private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter(
|
||||
".dist-info");
|
||||
|
||||
private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter(".dist-info");
|
||||
/**
|
||||
* Filter that detects files named "METADATA".
|
||||
*/
|
||||
private static final FilenameFilter EGG_INFO_FILTER = new NameFileFilter(
|
||||
"EGG-INFO");
|
||||
|
||||
private static final FilenameFilter EGG_INFO_FILTER = new NameFileFilter("EGG-INFO");
|
||||
/**
|
||||
* Filter that detects files named "METADATA".
|
||||
*/
|
||||
private static final NameFileFilter METADATA_FILTER = new NameFileFilter(
|
||||
METADATA);
|
||||
|
||||
private static final NameFileFilter METADATA_FILTER = new NameFileFilter(METADATA);
|
||||
/**
|
||||
* Filter that detects files named "PKG-INFO".
|
||||
*/
|
||||
private static final NameFileFilter PKG_INFO_FILTER = new NameFileFilter(
|
||||
PKG_INFO);
|
||||
|
||||
private static final NameFileFilter PKG_INFO_FILTER = new NameFileFilter(PKG_INFO);
|
||||
/**
|
||||
* The file filter used to determine which files this analyzer supports.
|
||||
*/
|
||||
@@ -311,8 +295,7 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
addPropertyToEvidence(headers, vendorEvidence, "Author", Confidence.LOW);
|
||||
final String summary = headers.getHeader("Summary", null);
|
||||
if (StringUtils.isNotBlank(summary)) {
|
||||
JarAnalyzer
|
||||
.addDescription(dependency, summary, METADATA, "summary");
|
||||
JarAnalyzer.addDescription(dependency, summary, METADATA, "summary");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
|
||||
/**
|
||||
@@ -44,13 +45,13 @@ import org.owasp.dependencycheck.exception.InitializationException;
|
||||
* @author Dale Visser
|
||||
*/
|
||||
@Experimental
|
||||
@ThreadSafe
|
||||
public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
* Used when compiling file scanning regex patterns.
|
||||
*/
|
||||
private static final int REGEX_OPTIONS = Pattern.DOTALL
|
||||
| Pattern.CASE_INSENSITIVE;
|
||||
private static final int REGEX_OPTIONS = Pattern.DOTALL | Pattern.CASE_INSENSITIVE;
|
||||
|
||||
/**
|
||||
* Filename extensions for files to be analyzed.
|
||||
@@ -58,16 +59,14 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
private static final String EXTENSIONS = "py";
|
||||
|
||||
/**
|
||||
* Pattern for matching the module docstring in a source file.
|
||||
* Pattern for matching the module doc string in a source file.
|
||||
*/
|
||||
private static final Pattern MODULE_DOCSTRING = Pattern.compile(
|
||||
"^(['\\\"]{3})(.*?)\\1", REGEX_OPTIONS);
|
||||
private static final Pattern MODULE_DOCSTRING = Pattern.compile("^(['\\\"]{3})(.*?)\\1", REGEX_OPTIONS);
|
||||
|
||||
/**
|
||||
* Matches assignments to version variables in Python source code.
|
||||
*/
|
||||
private static final Pattern VERSION_PATTERN = Pattern.compile(
|
||||
"\\b(__)?version(__)? *= *(['\"]+)(\\d+\\.\\d+.*?)\\3",
|
||||
private static final Pattern VERSION_PATTERN = Pattern.compile("\\b(__)?version(__)? *= *(['\"]+)(\\d+\\.\\d+.*?)\\3",
|
||||
REGEX_OPTIONS);
|
||||
|
||||
/**
|
||||
@@ -130,6 +129,16 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
return AnalysisPhase.INFORMATION_COLLECTION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key name for the analyzers enabled setting.
|
||||
*
|
||||
* @return the key name for the analyzers enabled setting
|
||||
*/
|
||||
@Override
|
||||
protected String getAnalyzerEnabledSettingKey() {
|
||||
return Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FileFilter
|
||||
*
|
||||
@@ -192,7 +201,7 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
engine.getDependencies().remove(dependency);
|
||||
engine.removeDependency(dependency);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,8 +221,7 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
try {
|
||||
contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim();
|
||||
} catch (IOException e) {
|
||||
throw new AnalysisException(
|
||||
"Problem occurred while reading dependency file.", e);
|
||||
throw new AnalysisException("Problem occurred while reading dependency file.", e);
|
||||
}
|
||||
boolean found = false;
|
||||
if (!contents.isEmpty()) {
|
||||
@@ -311,9 +319,4 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAnalyzerEnabledSettingKey() {
|
||||
return Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
@@ -50,6 +51,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Dale Visser
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -482,7 +484,7 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
dependency.setDisplayFileName(displayFileName);
|
||||
dependency.setFileName(fileName);
|
||||
dependency.setFilePath(filePath);
|
||||
engine.getDependencies().add(dependency);
|
||||
engine.addDependency(dependency);
|
||||
return dependency;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
@@ -47,6 +48,7 @@ import org.owasp.dependencycheck.dependency.Dependency;
|
||||
* @author Bianca Jiang (https://twitter.com/biancajiang)
|
||||
*/
|
||||
@Experimental
|
||||
@ThreadSafe
|
||||
public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
@@ -46,6 +47,7 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Dale Visser
|
||||
*/
|
||||
@Experimental
|
||||
@ThreadSafe
|
||||
public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -130,8 +132,7 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
private static final Pattern GEMSPEC_BLOCK_INIT = Pattern.compile("Gem::Specification\\.new\\s+?do\\s+?\\|(.+?)\\|");
|
||||
|
||||
@Override
|
||||
protected void analyzeDependency(Dependency dependency, Engine engine)
|
||||
throws AnalysisException {
|
||||
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
String contents;
|
||||
try {
|
||||
contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
@@ -41,6 +42,7 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
* @author Bianca Jiang (https://twitter.com/biancajiang)
|
||||
*/
|
||||
@Experimental
|
||||
@ThreadSafe
|
||||
public class SwiftPackageManagerAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
@@ -37,8 +38,14 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class VersionFilterAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
/**
|
||||
* The Logger for use throughout the class
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(VersionFilterAnalyzer.class);
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="Constants">
|
||||
/**
|
||||
* Evidence source.
|
||||
@@ -111,11 +118,6 @@ public class VersionFilterAnalyzer extends AbstractAnalyzer {
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
/**
|
||||
* The Logger for use throughout the class
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(VersionFilterAnalyzer.class);
|
||||
|
||||
/**
|
||||
* The HintAnalyzer uses knowledge about a dependency to add additional
|
||||
* information to help in identification of identifiers or vulnerabilities.
|
||||
@@ -126,7 +128,7 @@ public class VersionFilterAnalyzer extends AbstractAnalyzer {
|
||||
* the dependency.
|
||||
*/
|
||||
@Override
|
||||
protected synchronized void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
String fileVersion = null;
|
||||
String pomVersion = null;
|
||||
String manifestVersion = null;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
@@ -26,6 +27,7 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class VulnerabilitySuppressionAnalyzer extends AbstractSuppressionAnalyzer {
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.analyzer.exception;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* An exception thrown when the analysis of a dependency fails.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class AnalysisException extends Exception {
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.analyzer.exception;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* An exception thrown when files in an archive cannot be extracted.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class ArchiveExtractionException extends Exception {
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,9 +21,11 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.xpath.XPath;
|
||||
@@ -45,12 +47,13 @@ import org.xml.sax.SAXException;
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class CentralSearch {
|
||||
|
||||
/**
|
||||
* The URL for the Central service
|
||||
*/
|
||||
private final URL rootURL;
|
||||
private final String rootURL;
|
||||
|
||||
/**
|
||||
* Whether to use the Proxy when making requests
|
||||
@@ -70,7 +73,7 @@ public class CentralSearch {
|
||||
* Creates a NexusSearch for the given repository URL.
|
||||
*
|
||||
* @param settings the configured settings
|
||||
* @throws java.net.MalformedURLException thrown if the configured URL is
|
||||
* @throws MalformedURLException thrown if the configured URL is
|
||||
* invalid
|
||||
*/
|
||||
public CentralSearch(Settings settings) throws MalformedURLException {
|
||||
@@ -78,7 +81,10 @@ public class CentralSearch {
|
||||
|
||||
final String searchUrl = settings.getString(Settings.KEYS.ANALYZER_CENTRAL_URL);
|
||||
LOGGER.debug("Central Search URL: {}", searchUrl);
|
||||
this.rootURL = new URL(searchUrl);
|
||||
if (isInvalidURL(searchUrl)) {
|
||||
throw new MalformedURLException(String.format("The configured central analyzer URL is invalid: %s", searchUrl));
|
||||
}
|
||||
this.rootURL = searchUrl;
|
||||
if (null != settings.getString(Settings.KEYS.PROXY_SERVER)) {
|
||||
useProxy = true;
|
||||
LOGGER.debug("Using proxy");
|
||||
@@ -103,7 +109,7 @@ public class CentralSearch {
|
||||
throw new IllegalArgumentException("Invalid SHA1 format");
|
||||
}
|
||||
List<MavenArtifact> result = null;
|
||||
final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1));
|
||||
final URL url = new URL(String.format("%s?q=1:\"%s\"&wt=xml", rootURL, sha1));
|
||||
|
||||
LOGGER.debug("Searching Central url {}", url);
|
||||
|
||||
@@ -178,4 +184,21 @@ public class CentralSearch {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to determine if the gien URL is <b>invalid</b>.
|
||||
*
|
||||
* @param url the url to evaluate
|
||||
* @return true if the url is malformed; otherwise false
|
||||
*/
|
||||
private boolean isInvalidURL(String url) {
|
||||
try {
|
||||
final URL u = new URL(url);
|
||||
u.toURI();
|
||||
} catch (MalformedURLException | URISyntaxException e) {
|
||||
LOGGER.trace("URL is invalid: {}", url);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.composer;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Represents a dependency (GAV, right now) from a Composer dependency.
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@ThreadSafe
|
||||
public final class ComposerDependency {
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.composer;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Represents an exception when handling a composer.json or composer.lock file. Generally used to wrap a downstream exception.
|
||||
* Represents an exception when handling a composer.json or composer.lock file.
|
||||
* Generally used to wrap a downstream exception.
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class ComposerException extends RuntimeException {
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,12 +29,14 @@ import javax.json.stream.JsonParsingException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
/**
|
||||
* Parses a Composer.lock file from an input stream. In a separate class so it can hopefully be injected.
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class ComposerLockParser {
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,8 @@ import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.core.KeywordAnalyzer;
|
||||
import org.apache.lucene.analysis.miscellaneous.PerFieldAnalyzerWrapper;
|
||||
@@ -47,21 +49,29 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An in memory Lucene index that contains the vendor/product combinations from
|
||||
* the CPE (application) identifiers within the NVD CVE data.
|
||||
* the CPE (application) identifiers within the NVD CVE data.</p>
|
||||
*
|
||||
* This is the last remaining singleton in dependency-check-core; The use of
|
||||
* this singleton - while it may not technically be thread-safe (one database
|
||||
* used to build this index may not have the same entries as another) the risk
|
||||
* of this is currently believed to be small. As this memory index consumes a
|
||||
* large amount of memory we will remain using the singleton pattern for now.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public final class CpeMemoryIndex implements AutoCloseable {
|
||||
|
||||
/**
|
||||
* Singleton instance.
|
||||
*/
|
||||
private static final CpeMemoryIndex INSTANCE = new CpeMemoryIndex();
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CpeMemoryIndex.class);
|
||||
/**
|
||||
* singleton instance.
|
||||
*/
|
||||
private static final CpeMemoryIndex INSTANCE = new CpeMemoryIndex();
|
||||
/**
|
||||
* The in memory Lucene index.
|
||||
*/
|
||||
@@ -82,19 +92,11 @@ public final class CpeMemoryIndex implements AutoCloseable {
|
||||
* The Lucene QueryParser used for Searching.
|
||||
*/
|
||||
private QueryParser queryParser;
|
||||
/**
|
||||
* The search field analyzer for the product field.
|
||||
*/
|
||||
private SearchFieldAnalyzer productFieldAnalyzer;
|
||||
/**
|
||||
* The search field analyzer for the vendor field.
|
||||
*/
|
||||
private SearchFieldAnalyzer vendorFieldAnalyzer;
|
||||
/**
|
||||
* Track the number of current users of the Lucene index; used to track it
|
||||
* it is okay to actually close the index.
|
||||
*/
|
||||
private int usageCount = 0;
|
||||
private final AtomicInteger usageCount = new AtomicInteger(0);
|
||||
|
||||
/**
|
||||
* private constructor for singleton.
|
||||
@@ -118,8 +120,7 @@ public final class CpeMemoryIndex implements AutoCloseable {
|
||||
* @throws IndexException thrown if there is an error creating the index
|
||||
*/
|
||||
public synchronized void open(CveDB cve) throws IndexException {
|
||||
if (INSTANCE.usageCount <= 0) {
|
||||
INSTANCE.usageCount = 0;
|
||||
if (INSTANCE.usageCount.addAndGet(1) == 1) {
|
||||
index = new RAMDirectory();
|
||||
buildIndex(cve);
|
||||
try {
|
||||
@@ -131,7 +132,6 @@ public final class CpeMemoryIndex implements AutoCloseable {
|
||||
searchingAnalyzer = createSearchingAnalyzer();
|
||||
queryParser = new QueryParser(LuceneUtils.CURRENT_VERSION, Fields.DOCUMENT_KEY, searchingAnalyzer);
|
||||
}
|
||||
INSTANCE.usageCount += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,7 +140,7 @@ public final class CpeMemoryIndex implements AutoCloseable {
|
||||
* @return whether or not the index is open
|
||||
*/
|
||||
public synchronized boolean isOpen() {
|
||||
return INSTANCE.usageCount > 0;
|
||||
return INSTANCE.usageCount.get() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,8 +151,8 @@ public final class CpeMemoryIndex implements AutoCloseable {
|
||||
private Analyzer createSearchingAnalyzer() {
|
||||
final Map<String, Analyzer> fieldAnalyzers = new HashMap<>();
|
||||
fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer());
|
||||
productFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
|
||||
vendorFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
|
||||
SearchFieldAnalyzer productFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
|
||||
SearchFieldAnalyzer vendorFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
|
||||
fieldAnalyzers.put(Fields.PRODUCT, productFieldAnalyzer);
|
||||
fieldAnalyzers.put(Fields.VENDOR, vendorFieldAnalyzer);
|
||||
|
||||
@@ -164,8 +164,9 @@ public final class CpeMemoryIndex implements AutoCloseable {
|
||||
*/
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
INSTANCE.usageCount -= 1;
|
||||
if (INSTANCE.usageCount <= 0) {
|
||||
final int count = INSTANCE.usageCount.get() - 1;
|
||||
if (count <= 0) {
|
||||
INSTANCE.usageCount.set(0);
|
||||
if (searchingAnalyzer != null) {
|
||||
searchingAnalyzer.close();
|
||||
searchingAnalyzer = null;
|
||||
@@ -218,8 +219,6 @@ public final class CpeMemoryIndex implements AutoCloseable {
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.debug("", ex);
|
||||
throw new IndexException("Error reading CPE data", ex);
|
||||
} catch (CorruptIndexException ex) {
|
||||
throw new IndexException("Unable to close an in-memory index", ex);
|
||||
} catch (IOException ex) {
|
||||
throw new IndexException("Unable to close an in-memory index", ex);
|
||||
}
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.cpe;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Fields is a collection of field names used within the Lucene index for CPE entries.
|
||||
* Fields is a collection of field names used within the Lucene index for CPE
|
||||
* entries.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public final class Fields {
|
||||
|
||||
/**
|
||||
@@ -38,7 +42,8 @@ public final class Fields {
|
||||
public static final String PRODUCT = "product";
|
||||
|
||||
/**
|
||||
* Private constructor as this is more of an enumeration rather then a full class.
|
||||
* Private constructor as this is more of an enumeration rather then a full
|
||||
* class.
|
||||
*/
|
||||
private Fields() {
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package org.owasp.dependencycheck.data.cpe;
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -27,6 +28,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class IndexEntry implements Serializable {
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.cpe;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* An exception thrown when the there is an issue using the in-memory CPE Index.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class IndexException extends Exception {
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,11 +26,13 @@ import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public final class CweDB {
|
||||
|
||||
/**
|
||||
@@ -59,9 +61,7 @@ public final class CweDB {
|
||||
final String filePath = "data/cwe.hashmap.serialized";
|
||||
try (InputStream input = FileUtils.getResourceAsStream(filePath);
|
||||
ObjectInputStream oin = new ObjectInputStream(input)) {
|
||||
|
||||
final Map<String, String> ret = (HashMap<String, String>) oin.readObject();
|
||||
return ret;
|
||||
return (HashMap<String, String>) oin.readObject();
|
||||
} catch (ClassNotFoundException ex) {
|
||||
LOGGER.warn("Unable to load CWE data. This should not be an issue.");
|
||||
LOGGER.debug("", ex);
|
||||
@@ -79,7 +79,7 @@ public final class CweDB {
|
||||
* @param cweId the CWE ID
|
||||
* @return the full name of the CWE
|
||||
*/
|
||||
public static String getCweName(String cweId) {
|
||||
public static synchronized String getCweName(String cweId) {
|
||||
if (cweId != null) {
|
||||
return CWE.get(cweId);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package org.owasp.dependencycheck.data.cwe;
|
||||
|
||||
import java.util.HashMap;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
@@ -27,6 +28,7 @@ import org.xml.sax.helpers.DefaultHandler;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class CweHandler extends DefaultHandler {
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,15 +18,18 @@
|
||||
package org.owasp.dependencycheck.data.lucene;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.apache.lucene.analysis.TokenFilter;
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
|
||||
|
||||
/**
|
||||
* An abstract tokenizing filter that can be used as the base for a tokenizing filter.
|
||||
* An abstract tokenizing filter that can be used as the base for a tokenizing
|
||||
* filter.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public abstract class AbstractTokenizingFilter extends TokenFilter {
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,14 +18,17 @@
|
||||
package org.owasp.dependencycheck.data.lucene;
|
||||
|
||||
import java.io.Reader;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.apache.lucene.analysis.util.CharTokenizer;
|
||||
import org.apache.lucene.util.Version;
|
||||
|
||||
/**
|
||||
* Tokenizes the input breaking it into tokens when non-alpha/numeric characters are found.
|
||||
* Tokenizes the input breaking it into tokens when non-alpha/numeric characters
|
||||
* are found.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class AlphaNumericTokenizer extends CharTokenizer {
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.lucene;
|
||||
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.apache.lucene.search.similarities.DefaultSimilarity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class DependencySimilarity extends DefaultSimilarity {
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,19 +18,22 @@
|
||||
package org.owasp.dependencycheck.data.lucene;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.apache.lucene.util.Version;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Lucene utils is a set of utilize written to make constructing Lucene queries simpler.</p>
|
||||
* Lucene utils is a set of utilize written to make constructing Lucene queries
|
||||
* simpler.</p>
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public final class LuceneUtils {
|
||||
|
||||
/**
|
||||
* The current version of Lucene being used. Declaring this one place so an upgrade doesn't require hunting through the code
|
||||
* base.
|
||||
* The current version of Lucene being used. Declaring this one place so an
|
||||
* upgrade doesn't require hunting through the code base.
|
||||
*/
|
||||
public static final Version CURRENT_VERSION = Version.LUCENE_47;
|
||||
|
||||
@@ -41,7 +44,8 @@ public final class LuceneUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the text to the supplied StringBuilder escaping Lucene control characters in the process.
|
||||
* Appends the text to the supplied StringBuilder escaping Lucene control
|
||||
* characters in the process.
|
||||
*
|
||||
* @param buf a StringBuilder to append the escaped text to
|
||||
* @param text the data to be escaped
|
||||
@@ -88,7 +92,8 @@ public final class LuceneUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes the text passed in so that it is treated as data instead of control characters.
|
||||
* Escapes the text passed in so that it is treated as data instead of
|
||||
* control characters.
|
||||
*
|
||||
* @param text data to be escaped
|
||||
* @return the escaped text.
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
package org.owasp.dependencycheck.data.lucene;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.analysis.Tokenizer;
|
||||
@@ -44,8 +42,8 @@ public class SearchFieldAnalyzer extends Analyzer {
|
||||
/**
|
||||
* The list of additional stop words to use.
|
||||
*/
|
||||
private static final List<String> ADDITIONAL_STOP_WORDS = Arrays.asList("software", "framework", "inc",
|
||||
"com", "org", "net", "www", "consulting", "ltd", "foundation", "project");
|
||||
private static final String[] ADDITIONAL_STOP_WORDS = {"software", "framework", "inc",
|
||||
"com", "org", "net", "www", "consulting", "ltd", "foundation", "project"};
|
||||
/**
|
||||
* The set of stop words to use in the analyzer.
|
||||
*/
|
||||
@@ -57,8 +55,8 @@ public class SearchFieldAnalyzer extends Analyzer {
|
||||
* @return the set of stop words being used
|
||||
*/
|
||||
public static CharArraySet getStopWords() {
|
||||
CharArraySet words = new CharArraySet(LuceneUtils.CURRENT_VERSION, StopAnalyzer.ENGLISH_STOP_WORDS_SET, true);
|
||||
words.addAll(ADDITIONAL_STOP_WORDS);
|
||||
final CharArraySet words = StopFilter.makeStopSet(LuceneUtils.CURRENT_VERSION, ADDITIONAL_STOP_WORDS, true);
|
||||
words.addAll(StopAnalyzer.ENGLISH_STOP_WORDS_SET);
|
||||
return words;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.owasp.dependencycheck.data.lucene;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.apache.lucene.analysis.TokenFilter;
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
|
||||
@@ -33,6 +34,7 @@ import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public final class TokenPairConcatenatingFilter extends TokenFilter {
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
|
||||
import org.owasp.dependencycheck.utils.UrlStringUtils;
|
||||
@@ -28,13 +29,12 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Takes a TokenStream and splits or adds tokens to correctly index version numbers.</p>
|
||||
* <p>
|
||||
* <b>Example:</b> "3.0.0.RELEASE" -> "3 3.0 3.0.0 RELEASE 3.0.0.RELEASE".</p>
|
||||
*
|
||||
* Takes a TokenStream, looks for URLs, and breaks them into separate tokens.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public final class UrlTokenizingFilter extends AbstractTokenizingFilter {
|
||||
|
||||
/**
|
||||
@@ -52,8 +52,9 @@ public final class UrlTokenizingFilter extends AbstractTokenizingFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the underlying TokenStream and sets CharTermAttributes to construct an expanded set of tokens by concatenating
|
||||
* tokens with the previous token.
|
||||
* Increments the underlying TokenStream and sets CharTermAttributes to
|
||||
* construct an expanded set of tokens by concatenating tokens with the
|
||||
* previous token.
|
||||
*
|
||||
* @return whether or not we have hit the end of the TokenStream
|
||||
* @throws IOException is thrown when an IOException occurs
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.nexus;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Simple bean representing a Maven Artifact.
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class MavenArtifact {
|
||||
|
||||
/**
|
||||
@@ -45,7 +48,8 @@ public class MavenArtifact {
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* The artifact url. This may change depending on which Nexus server the search took place.
|
||||
* The artifact url. This may change depending on which Nexus server the
|
||||
* search took place.
|
||||
*/
|
||||
private String artifactUrl;
|
||||
/**
|
||||
@@ -80,7 +84,8 @@ public class MavenArtifact {
|
||||
* @param version the version
|
||||
* @param jarAvailable if the jar file is available from central
|
||||
* @param pomAvailable if the pom file is available from central
|
||||
* @param secureDownload if the jar and pom files should be downloaded using HTTPS.
|
||||
* @param secureDownload if the jar and pom files should be downloaded using
|
||||
* HTTPS.
|
||||
*/
|
||||
public MavenArtifact(String groupId, String artifactId, String version, boolean jarAvailable, boolean pomAvailable, boolean secureDownload) {
|
||||
this.groupId = groupId;
|
||||
@@ -220,5 +225,3 @@ public class MavenArtifact {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: cc=120:sw=4:ts=4:sts=4
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.xpath.XPath;
|
||||
@@ -41,6 +42,7 @@ import org.xml.sax.SAXException;
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class NexusSearch {
|
||||
|
||||
/**
|
||||
@@ -66,16 +68,17 @@ public class NexusSearch {
|
||||
*
|
||||
* @param settings the configured settings
|
||||
* @param useProxy flag indicating if the proxy settings should be used
|
||||
* @throws java.net.MalformedURLException thrown if the configured URL is invalid
|
||||
* @throws java.net.MalformedURLException thrown if the configured URL is
|
||||
* invalid
|
||||
*/
|
||||
public NexusSearch(Settings settings, boolean useProxy) throws MalformedURLException {
|
||||
this.settings = settings;
|
||||
this.useProxy = useProxy;
|
||||
|
||||
|
||||
final String searchUrl = settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
|
||||
LOGGER.debug("Nexus Search URL: {}", searchUrl);
|
||||
this.rootURL = new URL(searchUrl);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,7 +106,7 @@ public class NexusSearch {
|
||||
// 2) Otherwise, don't use the proxy (either the proxy isn't configured,
|
||||
// or proxy is specifically set to false
|
||||
HttpURLConnection conn;
|
||||
URLConnectionFactory factory = new URLConnectionFactory(settings);
|
||||
final URLConnectionFactory factory = new URLConnectionFactory(settings);
|
||||
conn = factory.createHttpURLConnection(url, useProxy);
|
||||
conn.setDoOutput(true);
|
||||
|
||||
@@ -169,7 +172,7 @@ public class NexusSearch {
|
||||
HttpURLConnection conn;
|
||||
try {
|
||||
final URL url = new URL(rootURL, "status");
|
||||
URLConnectionFactory factory = new URLConnectionFactory(settings);
|
||||
final URLConnectionFactory factory = new URLConnectionFactory(settings);
|
||||
conn = factory.createHttpURLConnection(url, useProxy);
|
||||
conn.addRequestProperty("Accept", "application/xml");
|
||||
conn.connect();
|
||||
@@ -187,9 +190,6 @@ public class NexusSearch {
|
||||
} catch (IOException | ParserConfigurationException | SAXException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: cc=120:sw=4:ts=4:sts=4
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package org.owasp.dependencycheck.data.nsp;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* The response from NSP check API will respond with 0 or more advisories. This
|
||||
@@ -25,6 +26,7 @@ import java.util.Arrays;
|
||||
*
|
||||
* @author Steve Springett
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class Advisory {
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.owasp.dependencycheck.utils.URLConnectionFactory;
|
||||
@@ -45,6 +46,7 @@ import org.owasp.dependencycheck.utils.URLConnectionFailureException;
|
||||
*
|
||||
* @author Steve Springett
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class NspSearch {
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Class used to create a Sanitized version of package.json suitable for
|
||||
@@ -32,6 +33,7 @@ import java.util.Map;
|
||||
*
|
||||
* @author Steve Springett
|
||||
*/
|
||||
@ThreadSafe
|
||||
public final class SanitizePackage {
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,12 +17,16 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.nuget;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Represents the contents of a Nuspec manifest.
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class NugetPackage {
|
||||
|
||||
/**
|
||||
* The id.
|
||||
*/
|
||||
@@ -55,6 +59,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Sets the id.
|
||||
*
|
||||
* @param id the id
|
||||
*/
|
||||
public void setId(String id) {
|
||||
@@ -63,6 +68,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Gets the id.
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
public String getId() {
|
||||
@@ -71,6 +77,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Sets the version.
|
||||
*
|
||||
* @param version the version
|
||||
*/
|
||||
public void setVersion(String version) {
|
||||
@@ -79,6 +86,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Gets the version.
|
||||
*
|
||||
* @return the version
|
||||
*/
|
||||
public String getVersion() {
|
||||
@@ -87,6 +95,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Sets the title.
|
||||
*
|
||||
* @param title the title
|
||||
*/
|
||||
public void setTitle(String title) {
|
||||
@@ -95,6 +104,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Gets the title.
|
||||
*
|
||||
* @return the title
|
||||
*/
|
||||
public String getTitle() {
|
||||
@@ -103,6 +113,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Sets the authors.
|
||||
*
|
||||
* @param authors the authors
|
||||
*/
|
||||
public void setAuthors(String authors) {
|
||||
@@ -111,6 +122,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Gets the authors.
|
||||
*
|
||||
* @return the authors
|
||||
*/
|
||||
public String getAuthors() {
|
||||
@@ -119,6 +131,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Sets the owners.
|
||||
*
|
||||
* @param owners the owners
|
||||
*/
|
||||
public void setOwners(String owners) {
|
||||
@@ -127,6 +140,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Gets the owners.
|
||||
*
|
||||
* @return the owners
|
||||
*/
|
||||
public String getOwners() {
|
||||
@@ -135,6 +149,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Sets the licenseUrl.
|
||||
*
|
||||
* @param licenseUrl the licenseUrl
|
||||
*/
|
||||
public void setLicenseUrl(String licenseUrl) {
|
||||
@@ -143,6 +158,7 @@ public class NugetPackage {
|
||||
|
||||
/**
|
||||
* Gets the licenseUrl.
|
||||
*
|
||||
* @return the licenseUrl
|
||||
*/
|
||||
public String getLicenseUrl() {
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.nuget;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Exception during the parsing of a Nuspec file.
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class NuspecParseException extends Exception {
|
||||
|
||||
/**
|
||||
@@ -32,19 +35,20 @@ public class NuspecParseException extends Exception {
|
||||
/**
|
||||
* Constructs a new exception with <code>null</code> as its detail message.
|
||||
*
|
||||
* The cause is not initialized, and may subsequently be initialized by a call to
|
||||
* {@link java.lang.Throwable#initCause(java.lang.Throwable)}.
|
||||
* The cause is not initialized, and may subsequently be initialized by a
|
||||
* call to {@link java.lang.Throwable#initCause(java.lang.Throwable)}.
|
||||
*/
|
||||
public NuspecParseException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently
|
||||
* be initialized by a call to {@link java.lang.Throwable#initCause(java.lang.Throwable)}.
|
||||
* Constructs a new exception with the specified detail message. The cause
|
||||
* is not initialized, and may subsequently be initialized by a call to
|
||||
* {@link java.lang.Throwable#initCause(java.lang.Throwable)}.
|
||||
*
|
||||
* @param message the detail message. The detail message is saved for later retrieval by the
|
||||
* {@link java.lang.Throwable#getMessage()} method.
|
||||
* @param message the detail message. The detail message is saved for later
|
||||
* retrieval by the {@link java.lang.Throwable#getMessage()} method.
|
||||
*/
|
||||
public NuspecParseException(String message) {
|
||||
super(message);
|
||||
@@ -53,13 +57,16 @@ public class NuspecParseException extends Exception {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message and cause.
|
||||
*
|
||||
* Note that the detail message associated with <code>cause</code> is <em>not</em>
|
||||
* Note that the detail message associated with <code>cause</code> is
|
||||
* <em>not</em>
|
||||
* automatically incorporated in this exception's detail message.
|
||||
*
|
||||
* @param message the detail message (which is saved for later retrieval by the
|
||||
* {@link java.lang.Throwable#getMessage()} method.
|
||||
* @param cause the cause (which is saved for later retrieval by the {@link java.lang.Throwable#getCause()} method).
|
||||
* (A <code>null</code> value is permitted, and indicates that the cause is nonexistent or unknown).
|
||||
* @param message the detail message (which is saved for later retrieval by
|
||||
* the {@link java.lang.Throwable#getMessage()} method.
|
||||
* @param cause the cause (which is saved for later retrieval by the
|
||||
* {@link java.lang.Throwable#getCause()} method). (A <code>null</code>
|
||||
* value is permitted, and indicates that the cause is nonexistent or
|
||||
* unknown).
|
||||
*/
|
||||
public NuspecParseException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.io.InputStream;
|
||||
*
|
||||
*/
|
||||
public interface NuspecParser {
|
||||
|
||||
/**
|
||||
* Parse an input stream and return the resulting {@link NugetPackage}.
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.owasp.dependencycheck.data.nuget;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.xpath.XPath;
|
||||
@@ -35,6 +36,7 @@ import org.xml.sax.SAXException;
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class XPathNuspecParser implements NuspecParser {
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.owasp.dependencycheck.utils.DBUtils;
|
||||
import org.owasp.dependencycheck.utils.DependencyVersion;
|
||||
@@ -44,6 +45,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public final class ConnectionFactory {
|
||||
|
||||
/**
|
||||
@@ -245,6 +247,7 @@ public final class ConnectionFactory {
|
||||
public boolean h2DataFileExists() throws IOException {
|
||||
return h2DataFileExists(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the H2 database file exists. If it does not exist then the
|
||||
* data structure will need to be created.
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.nvdcve;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* An exception used to indicate the db4o database is corrupt. This could be due to invalid data or a complete failure of the db.
|
||||
* An exception used to indicate the db4o database is corrupt. This could be due
|
||||
* to invalid data or a complete failure of the db.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class CorruptDatabaseException extends DatabaseException {
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.nvdcve;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.sql.Connection;
|
||||
@@ -354,6 +353,7 @@ public final class CveDB implements AutoCloseable {
|
||||
*
|
||||
* @throws SQLException thrown if a SQL Exception occurs
|
||||
*/
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
public synchronized void commit() throws SQLException {
|
||||
//temporary remove this as autocommit is on.
|
||||
//if (isOpen()) {
|
||||
@@ -514,7 +514,7 @@ public final class CveDB implements AutoCloseable {
|
||||
*
|
||||
* It should be also called when DB is closed.
|
||||
*/
|
||||
private void clearCache() {
|
||||
private synchronized void clearCache() {
|
||||
vulnerabilitiesForCpeCache.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.nvdcve;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* An exception thrown if an operation against the database fails.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class DatabaseException extends RuntimeException {
|
||||
|
||||
/**
|
||||
|
||||
@@ -97,7 +97,7 @@ public class DatabaseProperties {
|
||||
*
|
||||
* @return whether or not any properties are set
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
public synchronized boolean isEmpty() {
|
||||
return properties == null || properties.isEmpty();
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ public class DatabaseProperties {
|
||||
* @param updatedValue the updated NVD CVE entry
|
||||
* @throws UpdateException is thrown if there is an update exception
|
||||
*/
|
||||
public void save(NvdCveInfo updatedValue) throws UpdateException {
|
||||
public synchronized void save(NvdCveInfo updatedValue) throws UpdateException {
|
||||
if (updatedValue == null) {
|
||||
return;
|
||||
}
|
||||
@@ -121,7 +121,7 @@ public class DatabaseProperties {
|
||||
* @param value the property value
|
||||
* @throws UpdateException is thrown if there is an update exception
|
||||
*/
|
||||
public void save(String key, String value) throws UpdateException {
|
||||
public synchronized void save(String key, String value) throws UpdateException {
|
||||
properties.put(key, value);
|
||||
cveDB.saveProperty(key, value);
|
||||
}
|
||||
@@ -133,7 +133,7 @@ public class DatabaseProperties {
|
||||
* @param key the property key
|
||||
* @return the value of the property
|
||||
*/
|
||||
public String getProperty(String key) {
|
||||
public synchronized String getProperty(String key) {
|
||||
return properties.getProperty(key);
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ public class DatabaseProperties {
|
||||
* @param defaultValue the default value
|
||||
* @return the value of the property
|
||||
*/
|
||||
public String getProperty(String key, String defaultValue) {
|
||||
public synchronized String getProperty(String key, String defaultValue) {
|
||||
return properties.getProperty(key, defaultValue);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public class DatabaseProperties {
|
||||
*
|
||||
* @return the collection of Database Properties
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
public synchronized Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ public class DatabaseProperties {
|
||||
*
|
||||
* @return a map of the database meta data
|
||||
*/
|
||||
public Map<String, String> getMetaData() {
|
||||
public synchronized Map<String, String> getMetaData() {
|
||||
final Map<String, String> map = new TreeMap<>();
|
||||
for (Entry<Object, Object> entry : properties.entrySet()) {
|
||||
final String key = (String) entry.getKey();
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.nvdcve;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* An exception thrown the database driver is unable to be loaded.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class DriverLoadException extends Exception {
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,12 +31,14 @@ import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* DriverLoader is a utility class that is used to load database drivers.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public final class DriverLoader {
|
||||
|
||||
/**
|
||||
@@ -148,8 +150,6 @@ public final class DriverLoader {
|
||||
final Driver driver = (Driver) c.newInstance();
|
||||
|
||||
//TODO add usage count so we don't de-register a driver that is in use.
|
||||
|
||||
|
||||
final Driver shim = new DriverShim(driver);
|
||||
//using the DriverShim to get around the fact that the DriverManager won't register a driver not in the base class path
|
||||
DriverManager.registerDriver(shim);
|
||||
|
||||
@@ -28,16 +28,19 @@ import java.sql.DriverPropertyInfo;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLFeatureNotSupportedException;
|
||||
import java.util.Properties;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Driver shim to get around the class loader issue with the DriverManager. The following code is a nearly identical
|
||||
* copy (with more comments and a few more methods implemented) of the DriverShim from:</p>
|
||||
* Driver shim to get around the class loader issue with the DriverManager. The
|
||||
* following code is a nearly identical copy (with more comments and a few more
|
||||
* methods implemented) of the DriverShim from:</p>
|
||||
* <blockquote>http://www.kfu.com/~nsayer/Java/dyn-jdbc.html</blockquote>
|
||||
*
|
||||
* @author Jeremy Long
|
||||
* @see java.sql.Driver
|
||||
*/
|
||||
@ThreadSafe
|
||||
class DriverShim implements Driver {
|
||||
|
||||
/**
|
||||
@@ -59,12 +62,13 @@ class DriverShim implements Driver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the underlying driver's call to acceptsURL. Returns whether or not the driver can open a connection to the
|
||||
* given URL.
|
||||
* Wraps the underlying driver's call to acceptsURL. Returns whether or not
|
||||
* the driver can open a connection to the given URL.
|
||||
*
|
||||
* @param url the URL of the database
|
||||
* @return true if the wrapped driver can connect to the specified URL
|
||||
* @throws SQLException thrown if there is an error connecting to the database
|
||||
* @throws SQLException thrown if there is an error connecting to the
|
||||
* database
|
||||
* @see java.sql.Driver#acceptsURL(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
@@ -78,7 +82,8 @@ class DriverShim implements Driver {
|
||||
* @param url the URL of the database
|
||||
* @param info a collection of string/value pairs
|
||||
* @return a Connection object
|
||||
* @throws SQLException thrown if there is an error connecting to the database
|
||||
* @throws SQLException thrown if there is an error connecting to the
|
||||
* database
|
||||
* @see java.sql.Driver#connect(java.lang.String, java.util.Properties)
|
||||
*/
|
||||
@Override
|
||||
@@ -112,7 +117,8 @@ class DriverShim implements Driver {
|
||||
* Wraps the call to the underlying driver's getParentLogger method.
|
||||
*
|
||||
* @return the parent's Logger
|
||||
* @throws SQLFeatureNotSupportedException thrown if the feature is not supported
|
||||
* @throws SQLFeatureNotSupportedException thrown if the feature is not
|
||||
* supported
|
||||
* @see java.sql.Driver#getParentLogger()
|
||||
*/
|
||||
public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||
@@ -140,7 +146,8 @@ class DriverShim implements Driver {
|
||||
* @param info a collection of string/value pairs
|
||||
* @return an array of DriverPropertyInfo objects
|
||||
* @throws SQLException thrown if there is an error accessing the database
|
||||
* @see java.sql.Driver#getPropertyInfo(java.lang.String, java.util.Properties)
|
||||
* @see java.sql.Driver#getPropertyInfo(java.lang.String,
|
||||
* java.util.Properties)
|
||||
*/
|
||||
@Override
|
||||
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||
@@ -44,6 +45,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class EngineVersionCheck implements CachedWebDataSource {
|
||||
|
||||
/**
|
||||
@@ -115,7 +117,7 @@ public class EngineVersionCheck implements CachedWebDataSource {
|
||||
public void update(Engine engine) throws UpdateException {
|
||||
this.settings = engine.getSettings();
|
||||
try {
|
||||
CveDB db = engine.getDatabase();
|
||||
final CveDB db = engine.getDatabase();
|
||||
final boolean autoupdate = settings.getBoolean(Settings.KEYS.AUTO_UPDATE, true);
|
||||
final boolean enabled = settings.getBoolean(Settings.KEYS.UPDATE_VERSION_CHECK_ENABLED, true);
|
||||
final String original = settings.getString(Settings.KEYS.CVE_ORIGINAL_MODIFIED_20_URL);
|
||||
@@ -208,7 +210,7 @@ public class EngineVersionCheck implements CachedWebDataSource {
|
||||
try {
|
||||
final String str = settings.getString(Settings.KEYS.ENGINE_VERSION_CHECK_URL, "http://jeremylong.github.io/DependencyCheck/current.txt");
|
||||
final URL url = new URL(str);
|
||||
URLConnectionFactory factory = new URLConnectionFactory(settings);
|
||||
final URLConnectionFactory factory = new URLConnectionFactory(settings);
|
||||
conn = factory.createHttpURLConnection(url);
|
||||
conn.connect();
|
||||
if (conn.getResponseCode() != 200) {
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.update;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
@@ -27,8 +24,6 @@ import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -36,6 +31,7 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory;
|
||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||
@@ -63,6 +59,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class NvdCveUpdater implements CachedWebDataSource {
|
||||
|
||||
/**
|
||||
@@ -116,9 +113,12 @@ public class NvdCveUpdater implements CachedWebDataSource {
|
||||
if (isUpdateConfiguredFalse()) {
|
||||
return;
|
||||
}
|
||||
H2DBLock dbupdate = new H2DBLock(settings, ConnectionFactory.isH2Connection(settings));
|
||||
H2DBLock dbupdate = null;
|
||||
try {
|
||||
dbupdate.lock();
|
||||
if (ConnectionFactory.isH2Connection(settings)) {
|
||||
dbupdate = new H2DBLock(settings);
|
||||
dbupdate.lock();
|
||||
}
|
||||
initializeExecutorServices();
|
||||
dbProperties = cveDb.getDatabaseProperties();
|
||||
|
||||
@@ -142,7 +142,9 @@ public class NvdCveUpdater implements CachedWebDataSource {
|
||||
} catch (H2DBLockException ex) {
|
||||
throw new UpdateException("Unable to obtain an exclusive lock on the H2 database to perform updates", ex);
|
||||
} finally {
|
||||
dbupdate.release();
|
||||
if (dbupdate != null) {
|
||||
dbupdate.release();
|
||||
}
|
||||
shutdownExecutorServices();
|
||||
}
|
||||
}
|
||||
@@ -480,7 +482,7 @@ public class NvdCveUpdater implements CachedWebDataSource {
|
||||
*
|
||||
* @param settings the configured settings
|
||||
*/
|
||||
protected void setSettings(Settings settings) {
|
||||
protected synchronized void setSettings(Settings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@@ -513,7 +515,7 @@ public class NvdCveUpdater implements CachedWebDataSource {
|
||||
public Long call() throws Exception {
|
||||
LOGGER.debug("Checking for updates from: {}", url);
|
||||
try {
|
||||
Downloader downloader = new Downloader(settings);
|
||||
final Downloader downloader = new Downloader(settings);
|
||||
return downloader.getLastModified(new URL(url));
|
||||
} finally {
|
||||
settings.cleanup(false);
|
||||
|
||||
@@ -19,13 +19,15 @@ package org.owasp.dependencycheck.data.update;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
/**
|
||||
* The CachedWebDataSource Service Loader. This class loads all services that implement
|
||||
* org.owasp.dependencycheck.data.update.CachedWebDataSource.
|
||||
* The CachedWebDataSource Service Loader. This class loads all services that
|
||||
* implement {@link org.owasp.dependencycheck.data.update.CachedWebDataSource}.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class UpdateService {
|
||||
|
||||
/**
|
||||
@@ -36,14 +38,16 @@ public class UpdateService {
|
||||
/**
|
||||
* Creates a new instance of UpdateService.
|
||||
*
|
||||
* @param classLoader the ClassLoader to use when dynamically loading Analyzer and Update services
|
||||
* @param classLoader the ClassLoader to use when dynamically loading
|
||||
* Analyzer and Update services
|
||||
*/
|
||||
public UpdateService(ClassLoader classLoader) {
|
||||
loader = ServiceLoader.load(CachedWebDataSource.class, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Iterator for all instances of the CachedWebDataSource interface.
|
||||
* Returns an Iterator for all instances of the CachedWebDataSource
|
||||
* interface.
|
||||
*
|
||||
* @return an iterator of CachedWebDataSource.
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,7 @@ package org.owasp.dependencycheck.data.update.cpe;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.owasp.dependencycheck.data.update.NvdCveUpdater;
|
||||
import org.owasp.dependencycheck.data.update.exception.InvalidDataException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
@@ -34,6 +35,7 @@ import org.xml.sax.helpers.DefaultHandler;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class CPEHandler extends DefaultHandler {
|
||||
|
||||
/**
|
||||
@@ -62,6 +64,11 @@ public class CPEHandler extends DefaultHandler {
|
||||
*/
|
||||
private final List<Cpe> data = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs a new CPE Handler object with the configured settings.
|
||||
*
|
||||
* @param settings the configured settings
|
||||
*/
|
||||
public CPEHandler(Settings settings) {
|
||||
cpeStartsWith = settings.getString(Settings.KEYS.CVE_CPE_STARTS_WITH_FILTER, "cpe:/a:");
|
||||
}
|
||||
|
||||
@@ -20,14 +20,30 @@ package org.owasp.dependencycheck.data.update.cpe;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.data.update.exception.InvalidDataException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class Cpe {
|
||||
|
||||
/**
|
||||
* The CPE identifier string (cpe:/a:vendor:product:version).
|
||||
*/
|
||||
private String value;
|
||||
/**
|
||||
* The vendor portion of the identifier.
|
||||
*/
|
||||
private String vendor;
|
||||
|
||||
/**
|
||||
* The product portion of the identifier.
|
||||
*/
|
||||
private String product;
|
||||
|
||||
/**
|
||||
* Constructs a new Cpe Object by parsing the vendor and product from the CPE identifier value.
|
||||
*
|
||||
@@ -47,11 +63,6 @@ public class Cpe {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The CPE identifier string (cpe:/a:vendor:product:version).
|
||||
*/
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* Get the value of value.
|
||||
*
|
||||
@@ -69,10 +80,6 @@ public class Cpe {
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
/**
|
||||
* The vendor portion of the identifier.
|
||||
*/
|
||||
private String vendor;
|
||||
|
||||
/**
|
||||
* Get the value of vendor.
|
||||
@@ -92,11 +99,6 @@ public class Cpe {
|
||||
this.vendor = vendor;
|
||||
}
|
||||
|
||||
/**
|
||||
* The product portion of the identifier.
|
||||
*/
|
||||
private String product;
|
||||
|
||||
/**
|
||||
* Get the value of product.
|
||||
*
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.update.exception;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* An InvalidDataDataException is a generic exception used when trying to load the NVD CVE meta data.
|
||||
* An InvalidDataDataException is a generic exception used when trying to load
|
||||
* the NVD CVE meta data.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class InvalidDataException extends Exception {
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.update.exception;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* An exception used when an error occurs reading a setting.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class UpdateException extends Exception {
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.net.URL;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||
import org.owasp.dependencycheck.utils.DownloadFailedException;
|
||||
@@ -39,6 +40,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class DownloadTask implements Callable<Future<ProcessTask>> {
|
||||
|
||||
/**
|
||||
@@ -128,15 +130,6 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
||||
return first;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of first.
|
||||
*
|
||||
* @param first new value of first
|
||||
*/
|
||||
public void setFirst(File first) {
|
||||
this.first = first;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of second.
|
||||
*
|
||||
@@ -146,15 +139,6 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
||||
return second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of second.
|
||||
*
|
||||
* @param second new value of second
|
||||
*/
|
||||
public void setSecond(File second) {
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<ProcessTask> call() throws Exception {
|
||||
try {
|
||||
@@ -163,7 +147,7 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
||||
LOGGER.info("Download Started for NVD CVE - {}", nvdCveInfo.getId());
|
||||
final long startDownload = System.currentTimeMillis();
|
||||
try {
|
||||
Downloader downloader = new Downloader(settings);
|
||||
final Downloader downloader = new Downloader(settings);
|
||||
downloader.fetchFile(url1, first);
|
||||
downloader.fetchFile(url2, second);
|
||||
} catch (DownloadFailedException ex) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
@@ -34,6 +35,7 @@ import org.xml.sax.helpers.DefaultHandler;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class NvdCve12Handler extends DefaultHandler {
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,7 @@ package org.owasp.dependencycheck.data.update.nvd;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.apache.lucene.index.CorruptIndexException;
|
||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
@@ -40,6 +41,7 @@ import static org.owasp.dependencycheck.data.update.nvd.NvdCve20Handler.Attribut
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class NvdCve20Handler extends DefaultHandler {
|
||||
|
||||
/**
|
||||
@@ -184,9 +186,7 @@ public class NvdCve20Handler extends DefaultHandler {
|
||||
totalNumberOfApplicationEntries += 1;
|
||||
try {
|
||||
saveEntry(vulnerability);
|
||||
} catch (DatabaseException | CorruptIndexException ex) {
|
||||
throw new SAXException(ex);
|
||||
} catch (IOException ex) {
|
||||
} catch (DatabaseException | IOException ex) {
|
||||
throw new SAXException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,17 +17,36 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.data.update.nvd;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* A pojo that contains the Url and timestamp of the current NvdCve XML files.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class NvdCveInfo {
|
||||
|
||||
/**
|
||||
* an id.
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* a url.
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* The 1.2 schema URL.
|
||||
*/
|
||||
private String oldSchemaVersionUrl;
|
||||
/**
|
||||
* a timestamp - epoch time.
|
||||
*/
|
||||
private long timestamp;
|
||||
/**
|
||||
* indicates whether or not this item should be updated.
|
||||
*/
|
||||
private boolean needsUpdate = true;
|
||||
|
||||
/**
|
||||
* Get the value of id.
|
||||
@@ -46,10 +65,6 @@ public class NvdCveInfo {
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
/**
|
||||
* a url.
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* Get the value of url.
|
||||
@@ -68,10 +83,6 @@ public class NvdCveInfo {
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
/**
|
||||
* The 1.2 schema URL.
|
||||
*/
|
||||
private String oldSchemaVersionUrl;
|
||||
|
||||
/**
|
||||
* Get the value of oldSchemaVersionUrl.
|
||||
@@ -90,10 +101,6 @@ public class NvdCveInfo {
|
||||
public void setOldSchemaVersionUrl(String oldSchemaVersionUrl) {
|
||||
this.oldSchemaVersionUrl = oldSchemaVersionUrl;
|
||||
}
|
||||
/**
|
||||
* a timestamp - epoch time.
|
||||
*/
|
||||
private long timestamp;
|
||||
|
||||
/**
|
||||
* Get the value of timestamp - epoch time.
|
||||
@@ -112,10 +119,6 @@ public class NvdCveInfo {
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
/**
|
||||
* indicates whether or not this item should be updated.
|
||||
*/
|
||||
private boolean needsUpdate = true;
|
||||
|
||||
/**
|
||||
* Get the value of needsUpdate.
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||
@@ -42,6 +43,7 @@ import org.xml.sax.SAXException;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class ProcessTask implements Callable<ProcessTask> {
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,13 +21,15 @@ import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
/**
|
||||
* Contains a collection of updateable NvdCveInfo objects. This is used to determine which files need to be downloaded and
|
||||
* processed.
|
||||
* Contains a collection of updateable NvdCveInfo objects. This is used to
|
||||
* determine which files need to be downloaded and processed.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class UpdateableNvdCve implements Iterable<NvdCveInfo>, Iterator<NvdCveInfo> {
|
||||
|
||||
/**
|
||||
@@ -36,7 +38,13 @@ public class UpdateableNvdCve implements Iterable<NvdCveInfo>, Iterator<NvdCveIn
|
||||
private final Map<String, NvdCveInfo> collection = new TreeMap<>();
|
||||
|
||||
/**
|
||||
* Returns the collection of NvdCveInfo objects. This method is mainly used for testing.
|
||||
* An internal iterator used to implement iterable.
|
||||
*/
|
||||
private Iterator<Entry<String, NvdCveInfo>> iterableContent = null;
|
||||
|
||||
/**
|
||||
* Returns the collection of NvdCveInfo objects. This method is mainly used
|
||||
* for testing.
|
||||
*
|
||||
* @return the collection of NvdCveInfo objects
|
||||
*/
|
||||
@@ -63,7 +71,8 @@ public class UpdateableNvdCve implements Iterable<NvdCveInfo>, Iterator<NvdCveIn
|
||||
*
|
||||
* @param id the key for the item to be added
|
||||
* @param url the URL to download the item
|
||||
* @param oldUrl the URL for the old version of the item (the NVD CVE old schema still contains useful data we need).
|
||||
* @param oldUrl the URL for the old version of the item (the NVD CVE old
|
||||
* schema still contains useful data we need).
|
||||
* @param timestamp the last modified date of the downloaded item
|
||||
* @param needsUpdate whether or not the data needs to be updated
|
||||
*/
|
||||
@@ -93,10 +102,6 @@ public class UpdateableNvdCve implements Iterable<NvdCveInfo>, Iterator<NvdCveIn
|
||||
public long getTimeStamp(String key) {
|
||||
return collection.get(key).getTimestamp();
|
||||
}
|
||||
/**
|
||||
* An internal iterator used to implement iterable.
|
||||
*/
|
||||
private Iterator<Entry<String, NvdCveInfo>> iterableContent = null;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -118,7 +123,8 @@ public class UpdateableNvdCve implements Iterable<NvdCveInfo>, Iterator<NvdCveIn
|
||||
* <p>
|
||||
* <b>This method is not thread safe.</b></p>
|
||||
*
|
||||
* @return true or false depending on whether or not another item exists in the collection
|
||||
* @return true or false depending on whether or not another item exists in
|
||||
* the collection
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
@@ -43,6 +44,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class Dependency implements Serializable, Comparable<Dependency> {
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,12 +22,14 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Evidence is a piece of information about a Dependency.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class Evidence implements Serializable, Comparable<Evidence> {
|
||||
|
||||
/**
|
||||
@@ -44,6 +46,31 @@ public class Evidence implements Serializable, Comparable<Evidence> {
|
||||
*/
|
||||
private static final int MAGIC_HASH_MULTIPLIER = 67;
|
||||
|
||||
/**
|
||||
* The name of the evidence.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The source of the evidence.
|
||||
*/
|
||||
private String source;
|
||||
|
||||
/**
|
||||
* The value of the evidence.
|
||||
*/
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* A value indicating if the Evidence has been "used" (aka read).
|
||||
*/
|
||||
private boolean used;
|
||||
|
||||
/**
|
||||
* The confidence level for the evidence.
|
||||
*/
|
||||
private Confidence confidence;
|
||||
|
||||
/**
|
||||
* Creates a new Evidence object.
|
||||
*/
|
||||
@@ -65,11 +92,6 @@ public class Evidence implements Serializable, Comparable<Evidence> {
|
||||
this.confidence = confidence;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the evidence.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Get the value of name.
|
||||
*
|
||||
@@ -88,11 +110,6 @@ public class Evidence implements Serializable, Comparable<Evidence> {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source of the evidence.
|
||||
*/
|
||||
private String source;
|
||||
|
||||
/**
|
||||
* Get the value of source.
|
||||
*
|
||||
@@ -111,11 +128,6 @@ public class Evidence implements Serializable, Comparable<Evidence> {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of the evidence.
|
||||
*/
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* Get the value of value.
|
||||
*
|
||||
@@ -148,11 +160,6 @@ public class Evidence implements Serializable, Comparable<Evidence> {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* A value indicating if the Evidence has been "used" (aka read).
|
||||
*/
|
||||
private boolean used;
|
||||
|
||||
/**
|
||||
* Get the value of used.
|
||||
*
|
||||
@@ -171,11 +178,6 @@ public class Evidence implements Serializable, Comparable<Evidence> {
|
||||
this.used = used;
|
||||
}
|
||||
|
||||
/**
|
||||
* The confidence level for the evidence.
|
||||
*/
|
||||
private Confidence confidence;
|
||||
|
||||
/**
|
||||
* Get the value of confidence.
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.owasp.dependencycheck.utils.DependencyVersion;
|
||||
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
|
||||
@@ -37,6 +38,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class EvidenceCollection implements Serializable, Iterable<Evidence> {
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,12 +18,14 @@
|
||||
package org.owasp.dependencycheck.dependency;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* In identifier such as a CPE or dependency coordinates (i.e. GAV).
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class Identifier implements Serializable, Comparable<Identifier> {
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="fields">
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package org.owasp.dependencycheck.dependency;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
|
||||
/**
|
||||
@@ -26,6 +27,7 @@ import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class Reference implements Serializable, Comparable<Reference> {
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
|
||||
/**
|
||||
@@ -30,6 +31,7 @@ import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class Vulnerability implements Serializable, Comparable<Vulnerability> {
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,12 +19,14 @@ package org.owasp.dependencycheck.dependency;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Comparator;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Comparator for Vulnerability objects.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class VulnerabilityComparator implements Comparator<Vulnerability>, Serializable {
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,16 +20,19 @@ package org.owasp.dependencycheck.dependency;
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.owasp.dependencycheck.data.cpe.IndexEntry;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A record containing information about vulnerable software. This is referenced from a vulnerability.
|
||||
* A record containing information about vulnerable software. This is referenced
|
||||
* from a vulnerability.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class VulnerableSoftware extends IndexEntry implements Serializable, Comparable<VulnerableSoftware> {
|
||||
|
||||
/**
|
||||
@@ -41,6 +44,26 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
||||
*/
|
||||
private static final long serialVersionUID = 307319490326651052L;
|
||||
|
||||
/**
|
||||
* If present, indicates that previous version are vulnerable.
|
||||
*/
|
||||
private String previousVersion;
|
||||
|
||||
/**
|
||||
* The name of the cpe.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The product version number.
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* The product update version.
|
||||
*/
|
||||
private String update;
|
||||
|
||||
/**
|
||||
* Parse a CPE entry from the cpe string representation.
|
||||
*
|
||||
@@ -58,7 +81,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses a name attribute value, from the cpe.xml, into its corresponding parts: vendor, product, version, update.</p>
|
||||
* Parses a name attribute value, from the cpe.xml, into its corresponding
|
||||
* parts: vendor, product, version, update.</p>
|
||||
* <p>
|
||||
* Example:</p>
|
||||
* <code> cpe:/a:apache:struts:1.1:rc2</code>
|
||||
@@ -93,10 +117,6 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* If present, indicates that previous version are vulnerable.
|
||||
*/
|
||||
private String previousVersion;
|
||||
|
||||
/**
|
||||
* Indicates if previous versions of this software are vulnerable.
|
||||
@@ -126,7 +146,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard equals implementation to compare this VulnerableSoftware to another object.
|
||||
* Standard equals implementation to compare this VulnerableSoftware to
|
||||
* another object.
|
||||
*
|
||||
* @param obj the object to compare
|
||||
* @return whether or not the objects are equal
|
||||
@@ -156,7 +177,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard toString() implementation display the name and whether or not previous versions are also affected.
|
||||
* Standard toString() implementation display the name and whether or not
|
||||
* previous versions are also affected.
|
||||
*
|
||||
* @return a string representation of the object
|
||||
*/
|
||||
@@ -224,10 +246,9 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the string passed in is a positive integer.
|
||||
* To be counted as a positive integer, the string must only contain 0-9
|
||||
* and must not have any leading zeros (though "0" is a valid positive
|
||||
* integer).
|
||||
* Determines if the string passed in is a positive integer. To be counted
|
||||
* as a positive integer, the string must only contain 0-9 and must not have
|
||||
* any leading zeros (though "0" is a valid positive integer).
|
||||
*
|
||||
* @param str the string to test
|
||||
* @return true if the string only contains 0-9, otherwise false.
|
||||
@@ -251,10 +272,6 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* The name of the cpe.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Get the value of name.
|
||||
@@ -273,10 +290,6 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
/**
|
||||
* The product version number.
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* Get the value of version.
|
||||
@@ -295,10 +308,6 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
/**
|
||||
* The product update version.
|
||||
*/
|
||||
private String update;
|
||||
|
||||
/**
|
||||
* Get the value of update.
|
||||
@@ -341,7 +350,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces '+' with '%2B' and then URL Decodes the string attempting first UTF-8, then ASCII, then default.
|
||||
* Replaces '+' with '%2B' and then URL Decodes the string attempting first
|
||||
* UTF-8, then ASCII, then default.
|
||||
*
|
||||
* @param string the string to URL Decode
|
||||
* @return the URL Decoded string
|
||||
@@ -362,7 +372,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
||||
}
|
||||
|
||||
/**
|
||||
* Call {@link java.net.URLDecoder#decode(String)} to URL decode using the default encoding.
|
||||
* Call {@link java.net.URLDecoder#decode(String)} to URL decode using the
|
||||
* default encoding.
|
||||
*
|
||||
* @param text www-form-encoded URL to decode
|
||||
* @return the newly decoded String
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.exception;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* An exception used when a dependency could not be found.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class DependencyNotFoundException extends Exception {
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,12 +21,14 @@ import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
/**
|
||||
* A collection of several exceptions.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class ExceptionCollection extends Exception {
|
||||
/**
|
||||
* The serial version uid.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user