diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/MavenArtifact.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/MavenArtifact.java
new file mode 100644
index 000000000..943374088
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/MavenArtifact.java
@@ -0,0 +1,154 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.data.nexus;
+
+/**
+ * Simple bean representing a Maven Artifact.
+ *
+ * @author colezlaw
+ */
+public class MavenArtifact {
+ /**
+ * The groupId
+ */
+ private String groupId;
+
+ /**
+ * The artifactId
+ */
+ private String artifactId;
+
+ /**
+ * The version
+ */
+ private String version;
+
+ /**
+ * The artifact url. This may change depending on which Nexus
+ * server the search took place.
+ */
+ private String artifactUrl;
+
+
+ /**
+ * Creates an empty MavenArtifact.
+ */
+ public MavenArtifact() {
+ }
+
+ /**
+ * Creates a MavenArtifact with the given attributes.
+ *
+ * @param groupId the groupId
+ * @param artifactId the artifactId
+ * @param version the version
+ */
+ public MavenArtifact(String groupId, String artifactId, String version) {
+ setGroupId(groupId);
+ setArtifactId(artifactId);
+ setVersion(version);
+ }
+
+ /**
+ * Creates a MavenArtifact with the given attributes.
+ *
+ * @param groupId the groupId
+ * @param artifactId the artifactId
+ * @param version the version
+ * @param url the artifactLink url
+ */
+ public MavenArtifact(String groupId, String artifactId, String version, String url) {
+ setGroupId(groupId);
+ setArtifactId(artifactId);
+ setVersion(version);
+ setArtifactUrl(url);
+ }
+
+ /**
+ * Returns the Artifact coordinates as a String.
+ *
+ * @return the String representation of the artifact coordinates
+ */
+ @Override
+ public String toString() {
+ return String.format("%s:%s:%s", groupId, artifactId, version);
+ }
+
+ /**
+ * Sets the groupId.
+ *
+ * @param groupId the groupId
+ */
+ public void setGroupId(String groupId) { this.groupId = groupId; }
+
+ /**
+ * Gets the groupId.
+ *
+ * @return the groupId
+ */
+ public String getGroupId() { return groupId; }
+
+ /**
+ * Sets the artifactId.
+ *
+ * @param artifactId the artifactId
+ */
+ public void setArtifactId(String artifactId) { this.artifactId = artifactId; }
+
+ /**
+ * Gets the artifactId.
+ *
+ * @return the artifactId
+ */
+ public String getArtifactId() { return artifactId; }
+
+ /**
+ * Sets the version.
+ *
+ * @param version the version
+ */
+ public void setVersion(String version) { this.version = version; }
+
+ /**
+ * Gets the version.
+ *
+ * @return the version
+ */
+ public String getVersion() { return version; }
+
+ /**
+ * Sets the artifactUrl.
+ *
+ * @param artifactUrl the artifactUrl
+ */
+ public void setArtifactUrl(String artifactUrl) {
+ this.artifactUrl = artifactUrl;
+ }
+
+ /**
+ * Gets the artifactUrl.
+ *
+ * @return the artifactUrl
+ */
+ public String getArtifactUrl() {
+ return artifactUrl;
+ }
+}
+
+// vim: cc=120:sw=4:ts=4:sts=4
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java
new file mode 100644
index 000000000..d8db3392d
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java
@@ -0,0 +1,105 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.data.nexus;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.logging.Logger;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathFactory;
+import org.w3c.dom.Document;
+
+/**
+ * Class of methods to search Nexus repositories.
+ *
+ * @author colezlaw
+ */
+public class NexusSearch {
+ /**
+ * The root URL for the Nexus repository service
+ */
+ private final URL rootURL;
+
+ /**
+ * Used for logging.
+ */
+ private static final Logger LOGGER = Logger.getLogger(NexusSearch.class.getName());
+
+ /**
+ * Creates a NexusSearch for the given repository URL.
+ *
+ * @param rootURL the root URL of the repository on which searches should execute.
+ * full URL's are calculated relative to this URL, so it should end with a /
+ */
+ public NexusSearch(URL rootURL) {
+ this.rootURL = rootURL;
+ }
+
+ /**
+ * Searches the configured Nexus repository for the given sha1
+ * hash. If the artifact is found, a MavenArtifact is populated
+ * with the coordinate information.
+ *
+ * @param sha1 The SHA-1 hash string for which to search
+ * @return the populated Maven coordinates
+ * @throws IOException if it's unable to connect to the specified repositor or
+ * if the specified artifact is not found.
+ */
+ public MavenArtifact searchSha1(String sha1) throws IOException {
+ if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
+ throw new IllegalArgumentException("Invalid SHA1 format");
+ }
+
+ final URL url = new URL(rootURL, String.format("identify/sha1/%s", sha1.toLowerCase()));
+
+ LOGGER.fine(String.format("Searching Nexus url %s", url.toString()));
+
+ final URLConnection conn = url.openConnection();
+ conn.setDoOutput(true);
+
+ // JSON would be more elegant, but there's not currently a dependency
+ // on JSON, so don't want to add one just for this
+ conn.addRequestProperty("Accept", "application/xml");
+ conn.connect();
+
+ try {
+ final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ final Document doc = builder.parse(conn.getInputStream());
+ final XPath xpath = XPathFactory.newInstance().newXPath();
+ final String groupId = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/groupId", doc);
+ final String artifactId = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/artifactId", doc);
+ final String version = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/version", doc);
+ final String link = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink", doc);
+ return new MavenArtifact(groupId, artifactId, version, link);
+ } catch (FileNotFoundException fnfe) {
+ // This is what we get when the SHA1 they sent doesn't exist in Nexus. This
+ // is useful upstream for recovery, so we just re-throw it
+ throw fnfe;
+ } catch (Exception e) {
+ // Anything else is jacked-up XML stuff that we really can't recover from well
+ throw new IOException(e.getMessage(), e);
+ }
+ }
+}
+
+// vim: cc=120:sw=4:ts=4:sts=4
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/package-info.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/package-info.java
new file mode 100644
index 000000000..33f810a3a
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/package-info.java
@@ -0,0 +1,12 @@
+/**
+ *
+ *
Contains classes related to searching a Nexus repository.
+ *These are used to abstract Nexus searching away from + * OWASP Dependency Check so they can be reused elsewhere.
+ * + * + */ diff --git a/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer b/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer index 26e4c2427..0ed6a16cb 100644 --- a/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer +++ b/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer @@ -7,4 +7,5 @@ org.owasp.dependencycheck.analyzer.FalsePositiveAnalyzer org.owasp.dependencycheck.analyzer.CpeSuppressionAnalyzer org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer org.owasp.dependencycheck.analyzer.NvdCveAnalyzer -org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer \ No newline at end of file +org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer +org.owasp.dependencycheck.analyzer.NexusAnalyzer diff --git a/dependency-check-core/src/main/resources/dependencycheck.properties b/dependency-check-core/src/main/resources/dependencycheck.properties index 73629aa2b..3dbea7bed 100644 --- a/dependency-check-core/src/main/resources/dependencycheck.properties +++ b/dependency-check-core/src/main/resources/dependencycheck.properties @@ -46,3 +46,8 @@ cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modifie cve.startyear=2002 cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml + +# the URL for searching Nexus for SHA-1 hashes and whether it's enabled +analyzer.nexus.enabled=true +analyzer.nexus.url=http://repository.sonatype.org/service/local/ + diff --git a/dependency-check-core/src/test/resources/dependencycheck.properties b/dependency-check-core/src/test/resources/dependencycheck.properties index 89d1279b7..37e5291dd 100644 --- a/dependency-check-core/src/test/resources/dependencycheck.properties +++ b/dependency-check-core/src/test/resources/dependencycheck.properties @@ -46,3 +46,7 @@ cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modifie cve.startyear=2013 cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml + +# the URL for searching Nexus for SHA-1 hashes and whether it's enabled +analyzer.nexus.enabled=false +analyzer.nexus.url=http://repository.sonatype.org/service/local/