Merge branch 'nuspec' of https://github.com/colezlaw/DependencyCheck into colezlaw-nuspec

Former-commit-id: 75cf8bb16a7e96614eadbe9215e426d31d624c61
This commit is contained in:
Jeremy Long
2014-01-27 06:12:15 -05:00
12 changed files with 698 additions and 2 deletions

View File

@@ -81,10 +81,17 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL;
/**
* The set of things we can handle with Zip methods
*/
private static final Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "nupkg");
/**
* The set of file extensions supported by this analyzer.
*/
private static final Set<String> EXTENSIONS = newHashSet("zip", "ear", "war", "tar", "gz", "tgz");
private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz");
static {
EXTENSIONS.addAll(ZIPPABLES);
}
/**
* Returns a list of file EXTENSIONS supported by this analyzer.
@@ -251,7 +258,7 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
}
final String archiveExt = org.owasp.dependencycheck.utils.FileUtils.getFileExtension(archive.getName()).toLowerCase();
try {
if ("zip".equals(archiveExt) || "war".equals(archiveExt) || "ear".equals(archiveExt)) {
if (ZIPPABLES.contains(archiveExt)) {
extractArchive(new ZipArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
} else if ("tar".equals(archiveExt)) {
extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine);

View File

@@ -0,0 +1,147 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import java.io.FileInputStream;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nuget.NugetPackage;
import org.owasp.dependencycheck.data.nuget.NuspecParser;
import org.owasp.dependencycheck.data.nuget.XPathNuspecParser;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
/**
* Analyzer which will parse a Nuspec file to gather module information.
*
* @author colezlaw
*/
public class NuspecAnalyzer extends AbstractAnalyzer {
/**
* The logger
*/
private static final Logger LOGGER = Logger.getLogger(NuspecAnalyzer.class.getName());
/**
* The name of the analyzer
*/
private static final String ANALYZER_NAME = "Nuspec Analyzer";
/**
* The phase in which the analyzer runs
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
/**
* The types of files on which this will work.
*/
private static final Set<String> SUPPORTED_EXTENSIONS = newHashSet("nuspec");
/**
* Initializes the analyzer once before any analysis is performed.
*
* @throws Exception if there's an error during initialization
*/
@Override
public void initialize() throws Exception {
}
/**
* Returns the analyzer's name.
*
* @return the name of the analyzer
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns the analysis phase under which the analyzer runs.
*
* @return the phase under which this analyzer runs
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* Returns the extensions for which this Analyzer runs.
*
* @return the extensions for which this Analyzer runs
*/
@Override
public Set<String> getSupportedExtensions() {
return SUPPORTED_EXTENSIONS;
}
/**
* Determines whether the incoming extension is supported.
*
* @param extension the extension to check for support
* @return whether the extension is supported
*/
@Override
public boolean supportsExtension(String extension) {
return SUPPORTED_EXTENSIONS.contains(extension);
}
/**
* Performs the analysis.
*
* @param dependency the dependency to analyze
* @param engine the engine
* @throws AnalysisException when there's an exception during analysis
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
LOGGER.log(Level.INFO, "Checking Nuspec file {0}", dependency.toString());
try {
final NuspecParser parser = new XPathNuspecParser();
NugetPackage np = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(dependency.getActualFilePath());
np = parser.parse(fis);
} finally {
if (fis != null) {
try { fis.close(); } catch (Exception e) { }
}
}
if (np.getOwners() != null) {
dependency.getVendorEvidence().addEvidence("nuspec", "owners", np.getOwners(), Confidence.HIGHEST);
}
dependency.getVendorEvidence().addEvidence("nuspec", "authors", np.getAuthors(), Confidence.HIGH);
dependency.getVersionEvidence().addEvidence("nuspec", "version", np.getVersion(), Confidence.HIGHEST);
dependency.getProductEvidence().addEvidence("nuspec", "id", np.getId(), Confidence.HIGHEST);
if (np.getTitle() != null) {
dependency.getProductEvidence().addEvidence("nuspec", "title", np.getTitle(), Confidence.MEDIUM);
}
} catch (Exception e) {
throw new AnalysisException(e);
}
}
}
// vim: cc=120:sw=4:ts=4:sts=4

View File

@@ -0,0 +1,186 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.nuget;
/**
* Represents the contents of a Nuspec manifest.
*
* @author colezlaw
*/
public class NugetPackage {
/**
* The id.
*/
private String id;
/**
* The version.
*/
private String version;
/**
* The title.
*/
private String title;
/**
* The authors.
*/
private String authors;
/**
* The owners.
*/
private String owners;
/**
* The licenseUrl.
*/
private String licenseUrl;
/**
* Creates an empty NugetPackage.
*/
public NugetPackage() {
}
/**
* Sets the id.
* @param id the id
*/
public void setId(String id) {
this.id = id;
}
/**
* Gets the id.
* @return the id
*/
public String getId() {
return id;
}
/**
* 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 title.
* @param title the title
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Gets the title.
* @return the title
*/
public String getTitle() {
return title;
}
/**
* Sets the authors.
* @param authors the authors
*/
public void setAuthors(String authors) {
this.authors = authors;
}
/**
* Gets the authors.
* @return the authors
*/
public String getAuthors() {
return authors;
}
/**
* Sets the owners.
* @param owners the owners
*/
public void setOwners(String owners) {
this.owners = owners;
}
/**
* Gets the owners.
* @return the owners
*/
public String getOwners() {
return owners;
}
/**
* Sets the licenseUrl.
* @param licenseUrl the licenseUrl
*/
public void setLicenseUrl(String licenseUrl) {
this.licenseUrl = licenseUrl;
}
/**
* Gets the licenseUrl.
* @return the licenseUrl
*/
public String getLicenseUrl() {
return licenseUrl;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other == null || other.getClass() != this.getClass()) {
return false;
}
final NugetPackage o = (NugetPackage) other;
return o.getId().equals(id)
&& o.getVersion().equals(version)
&& o.getTitle().equals(title)
&& o.getAuthors().equals(authors)
&& o.getOwners().equals(owners)
&& o.getLicenseUrl().equals(licenseUrl);
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + (null == id ? 0 : id.hashCode());
hash = 31 * hash + (null == version ? 0 : version.hashCode());
hash = 31 * hash + (null == title ? 0 : title.hashCode());
hash = 31 * hash + (null == authors ? 0 : authors.hashCode());
hash = 31 * hash + (null == owners ? 0 : owners.hashCode());
hash = 31 * hash + (null == licenseUrl ? 0 : licenseUrl.hashCode());
return hash;
}
}

View File

@@ -0,0 +1,68 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.nuget;
/**
* Exception during the parsing of a Nuspec file.
*
* @author colezlaw
*/
public class NuspecParseException extends Exception {
/**
* The serialVersionUID
*/
private static final long serialVersionUID = 1;
/**
* 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)}.
*/
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).
*
* @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);
}
/**
* 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>
* automatically incorporated in this exception's detail message.
*
* @param message the detail message (whcih 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);
}
}

View File

@@ -0,0 +1,37 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.nuget;
import java.io.InputStream;
/**
* Interface defining methods for parsing a Nuspec file.
*
* @author willstranathan
*
*/
public interface NuspecParser {
/**
* Parse an input stream and return the resulting {@link NugetPackage}.
*
* @param stream the input stream to parse
* @return the populated bean
* @throws NuspecParseException when an exception occurs
*/
NugetPackage parse(InputStream stream) throws NuspecParseException;
}

View File

@@ -0,0 +1,82 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.nuget;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
/**
* Parse a Nuspec file using XPath.
*
* @author willstranathan
*/
public class XPathNuspecParser implements NuspecParser {
/**
* Gets the string value of a node or null if it's not present
*
* @param n the node to test
* @return the string content of the node, or null if the node itself is null
*/
private String getOrNull(Node n) {
if (n != null) {
return n.getTextContent();
} else {
return null;
}
}
/**
* Parse an input stream and return the resulting {@link NugetPackage}.
*
* @param stream the input stream to parse
* @return the populated bean
* @throws NuspecParseException when an exception occurs
*/
@Override
public NugetPackage parse(InputStream stream) throws NuspecParseException {
try {
final Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(stream);
final XPath xpath = XPathFactory.newInstance().newXPath();
final NugetPackage nuspec = new NugetPackage();
if (xpath.evaluate("/package/metadata/id", d, XPathConstants.NODE) == null
|| xpath.evaluate("/package/metadata/version", d, XPathConstants.NODE) == null
|| xpath.evaluate("/package/metadata/authors", d, XPathConstants.NODE) == null
|| xpath.evaluate("/package/metadata/description", d, XPathConstants.NODE) == null) {
throw new NuspecParseException("Invalid Nuspec format");
}
nuspec.setId(xpath.evaluate("/package/metadata/id", d));
nuspec.setVersion(xpath.evaluate("/package/metadata/version", d));
nuspec.setAuthors(xpath.evaluate("/package/metadata/authors", d));
nuspec.setOwners(getOrNull((Node) xpath.evaluate("/package/metadata/owners", d, XPathConstants.NODE)));
nuspec.setLicenseUrl(getOrNull((Node) xpath.evaluate("/package/metadata/licenseUrl", d, XPathConstants.NODE)));
nuspec.setTitle(getOrNull((Node) xpath.evaluate("/package/metadata/title", d, XPathConstants.NODE)));
return nuspec;
} catch (Exception e) {
throw new NuspecParseException("Unable to parse nuspec", e);
}
}
}

View File

@@ -0,0 +1,15 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.data.nuget</title>
* </head>
* <body>
* <p>
* Contains classes related to parsing Nuget related files</p>
* <p>
* These are used to abstract away Nuget-related handling from Dependency Check
* so they can be used elsewhere.</p>
* </body>
* </html>
*/
package org.owasp.dependencycheck.data.nuget;

View File

@@ -9,3 +9,4 @@ org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer
org.owasp.dependencycheck.analyzer.NvdCveAnalyzer
org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer
org.owasp.dependencycheck.analyzer.NexusAnalyzer
org.owasp.dependencycheck.analyzer.NuspecAnalyzer

View File

@@ -69,6 +69,7 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase {
expResult.add("zip");
expResult.add("war");
expResult.add("ear");
expResult.add("nupkg");
expResult.add("tar");
expResult.add("gz");
expResult.add("tgz");
@@ -110,6 +111,10 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase {
extension = "zip"; //supported
result = instance.supportsExtension(extension);
assertEquals(expResult, result);
extension = "nupkg"; //supported
result = instance.supportsExtension(extension);
assertEquals(expResult, result);
}
/**

View File

@@ -0,0 +1,55 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class NuspecAnalyzerTest {
private NuspecAnalyzer instance;
@Before
public void setUp() {
instance = new NuspecAnalyzer();
}
@Test
public void testGetAnalyzerName() {
assertEquals("Nuspec Analyzer", instance.getName());
}
@Test
public void testGetSupportedExtensions() {
assertTrue(instance.getSupportedExtensions().contains("nuspec"));
assertFalse(instance.getSupportedExtensions().contains("nupkg"));
}
@Test
public void testSupportsExtension() {
assertTrue(instance.supportsExtension("nuspec"));
assertFalse(instance.supportsExtension("nupkg"));
}
@Test
public void testGetAnalysisPhaze() {
assertEquals(AnalysisPhase.INFORMATION_COLLECTION, instance.getAnalysisPhase());
}
}
// vim: cc=120:sw=4:ts=4:sts=4

View File

@@ -0,0 +1,73 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.nuget;
import java.io.InputStream;
import org.junit.Test;
import static org.junit.Assert.*;
/**
*
* @author willstranathan
*
*/
public class XPathNuspecParserTest {
/**
* Test all the valid components.
*
* @throws Exception if anything goes sideways.
*/
@Test
public void testGoodDocument() throws Exception {
NuspecParser parser = new XPathNuspecParser();
InputStream is = XPathNuspecParserTest.class.getClassLoader().getResourceAsStream("log4net.2.0.3.nuspec");
NugetPackage np = parser.parse(is);
assertEquals("log4net", np.getId());
assertEquals("2.0.3", np.getVersion());
assertEquals("log4net [1.2.13]", np.getTitle());
assertEquals("Apache Software Foundation", np.getAuthors());
assertEquals("Apache Software Foundation", np.getOwners());
assertEquals("http://logging.apache.org/log4net/license.html", np.getLicenseUrl());
}
/**
* Expect a NuspecParseException when what we pass isn't even XML.
*
* @throws Exception we expect this.
*/
@Test(expected=NuspecParseException.class)
public void testMissingDocument() throws Exception {
NuspecParser parser = new XPathNuspecParser();
InputStream is = XPathNuspecParserTest.class.getClassLoader().getResourceAsStream("dependencycheck.properties");
NugetPackage np = parser.parse(is);
}
/**
* Expect a NuspecParseException when it's valid XML, but not a Nuspec.
*
* @throws Exception we expect this.
*/
@Test(expected=NuspecParseException.class)
public void testNotNuspec() throws Exception {
NuspecParser parser = new XPathNuspecParser();
InputStream is = XPathNuspecParserTest.class.getClassLoader().getResourceAsStream("suppressions.xml");
NugetPackage np = parser.parse(is);
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>log4net</id>
<version>2.0.3</version>
<title>log4net [1.2.13]</title>
<authors>Apache Software Foundation</authors>
<owners>Apache Software Foundation</owners>
<licenseUrl>http://logging.apache.org/log4net/license.html</licenseUrl>
<projectUrl>http://logging.apache.org/log4net/</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>log4net is a tool to help the programmer output log statements to a variety of output targets. In case of problems with an application, it is helpful to enable logging so that the problem can be located. With log4net it is possible to enable logging at runtime without modifying the application binary. The log4net package is designed so that log statements can remain in shipped code without incurring a high performance cost. It follows that the speed of logging (or rather not logging) is crucial.
At the same time, log output can be so voluminous that it quickly becomes overwhelming. One of the distinctive features of log4net is the notion of hierarchical loggers. Using these loggers it is possible to selectively control which log statements are output at arbitrary granularity.
log4net is designed with two distinct goals in mind: speed and flexibility</description>
<summary>The Apache log4net library is a tool to help the programmer output log statements to a variety of output targets.</summary>
<tags>logging log tracing logfiles</tags>
</metadata>
</package>