converted hint analyzer to use an externalized configuration file to simplify the resolution of issue #522

This commit is contained in:
Jeremy Long
2016-07-04 07:10:07 -04:00
parent 519b82c620
commit ebb52995a5
8 changed files with 634 additions and 0 deletions

View File

@@ -0,0 +1,160 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2016 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.xml.hints;
import java.util.ArrayList;
import java.util.List;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.suppression.PropertyType;
/**
* A collection of product and vendor evidence to match; if any evidence is
* matched the addVendor and addProduct evidence should be added to the
* dependency.
*
* @author Jeremy Long
*/
public class HintRule {
/**
* The list of file names to match.
*/
private final List<PropertyType> filenames = new ArrayList<PropertyType>();
/**
* Adds the filename evidence to the collection.
*
* @param filename the filename to add
*/
public void addFilename(PropertyType filename) {
this.filenames.add(filename);
}
/**
* Returns the list of filename evidence to match against.
*
* @return the list of filename evidence to match against
*/
public List<PropertyType> getFilenames() {
return filenames;
}
/**
* The list of product evidence that is being matched.
*/
private final List<Evidence> givenProduct = new ArrayList<Evidence>();
/**
* Adds a given product to the list of evidence to matched.
*
* @param source the source of the evidence
* @param name the name of the evidence
* @param value the value of the evidence
* @param confidence the confidence of the evidence
*/
public void addGivenProduct(String source, String name, String value, Confidence confidence) {
givenProduct.add(new Evidence(source, name, value, confidence));
}
/**
* Get the value of givenProduct
*
* @return the value of givenProduct.
*/
public List<Evidence> getGivenProduct() {
return givenProduct;
}
/**
* The list of vendor evidence that is being matched.
*/
private final List<Evidence> givenVendor = new ArrayList<Evidence>();
/**
* Adds a given vendors to the list of evidence to matched.
*
* @param source the source of the evidence
* @param name the name of the evidence
* @param value the value of the evidence
* @param confidence the confidence of the evidence
*/
public void addGivenVendor(String source, String name, String value, Confidence confidence) {
givenVendor.add(new Evidence(source, name, value, confidence));
}
/**
* Get the value of givenVendor.
*
* @return the value of givenVendor
*/
public List<Evidence> getGivenVendor() {
return givenVendor;
}
/**
* The list of product evidence to add.
*/
private final List<Evidence> addProduct = new ArrayList<Evidence>();
/**
* Adds a given product to the list of evidence to add when matched.
*
* @param source the source of the evidence
* @param name the name of the evidence
* @param value the value of the evidence
* @param confidence the confidence of the evidence
*/
public void addAddProduct(String source, String name, String value, Confidence confidence) {
addProduct.add(new Evidence(source, name, value, confidence));
}
/**
* Get the value of addProduct.
*
* @return the value of addProduct
*/
public List<Evidence> getAddProduct() {
return addProduct;
}
/**
* The list of vendor hints to add.
*/
private final List<Evidence> addVendor = new ArrayList<Evidence>();
/**
* Adds a given vendor to the list of evidence to add when matched.
*
* @param source the source of the evidence
* @param name the name of the evidence
* @param value the value of the evidence
* @param confidence the confidence of the evidence
*/
public void addAddVendor(String source, String name, String value, Confidence confidence) {
addVendor.add(new Evidence(source, name, value, confidence));
}
/**
* Get the value of addVendor.
*
* @return the value of addVendor
*/
public List<Evidence> getAddVendor() {
return addVendor;
}
}

View File

@@ -0,0 +1,75 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2016 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.xml.hints;
import java.util.List;
/**
* A collection of hint rules.
*
* @author Jeremy Long
*/
public class Hints {
/**
* The list of hint rules.
*/
private List<HintRule> hintRules;
/**
* Get the value of hintRules
*
* @return the value of hintRules
*/
public List<HintRule> getHintRules() {
return hintRules;
}
/**
* Set the value of hintRules
*
* @param hintRules new value of hintRules
*/
public void setHintRules(List<HintRule> hintRules) {
this.hintRules = hintRules;
}
/**
* The duplicating hint rules.
*/
private List<VendorDuplicatingHintRule> vendorDuplicatingHintRules;
/**
* Get the value of vendorDuplicatingHintRules
*
* @return the value of vendorDuplicatingHintRules
*/
public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() {
return vendorDuplicatingHintRules;
}
/**
* Set the value of vendorDuplicatingHintRules
*
* @param vendorDuplicatingHintRules new value of vendorDuplicatingHintRules
*/
public void setVendorDuplicatingHintRules(List<VendorDuplicatingHintRule> vendorDuplicatingHintRules) {
this.vendorDuplicatingHintRules = vendorDuplicatingHintRules;
}
}

View File

@@ -0,0 +1,85 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2016 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.xml.hints;
/**
* Used to duplicate vendor evidence within a collection. The intent is if any evidence
* is found in a collection that matches the value given the evidence will be
* duplicated and the value replaced with the value indicated.
*
* @author Jeremy Long
*/
public class VendorDuplicatingHintRule {
/**
* Constructs a new duplicating rule.
*
* @param value the value to duplicate the evidence if found
* @param duplicate the value to replace within the duplicated evidence
*/
public VendorDuplicatingHintRule(String value, String duplicate) {
this.value = value;
this.duplicate = duplicate;
}
/**
* The evidence value to duplicate if found.
*/
private String value;
/**
* Get the value of value.
*
* @return the value of value
*/
public String getValue() {
return value;
}
/**
* Set the value of value.
*
* @param value new value of value
*/
public void setValue(String value) {
this.value = value;
}
/**
* The value to replace when duplicating the evidence.
*/
private String duplicate;
/**
* Get the value of duplicate.
*
* @return the value of duplicate
*/
public String getDuplicate() {
return duplicate;
}
/**
* Set the value of duplicate.
*
* @param duplicate new value of duplicate
*/
public void setDuplicate(String duplicate) {
this.duplicate = duplicate;
}
}

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<hints xmlns="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.0.xsd">
<hint>
<given>
<evidence type="product" source="Manifest" name="Implementation-Title" value="Spring Framework" confidence="HIGH"/>
<evidence type="product" source="Manifest" name="Implementation-Title" value="org.springframework.core" confidence="HIGH"/>
<evidence type="product" source="Manifest" name="Implementation-Title" value="spring-core" confidence="HIGH"/>
</given>
<add>
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
</add>
</hint>
<hint>
<given>
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
<fileName contains="spring"/>
</given>
<add>
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
</add>
</hint>
<hint>
<given>
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
</given>
<add>
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
</add>
</hint>
<hint>
<given>
<evidence type="product" source="Manifest" name="Bundle-Name" value="Spring Security Core" confidence="MEDIUM"/>
<evidence type="product" source="pom" name="artifactid" value="spring-security-core" confidence="HIGH"/>
</given>
<add>
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
</add>
</hint>
<hint>
<given>
<evidence type="vendor" source="composer.lock" name="vendor" value="symfony" confidence="HIGHEST"/>
</given>
<add>
<evidence type="vendor" source="hint analyzer" name="vendor" value="sensiolabs" confidence="HIGHEST"/>
</add>
</hint>
<hint>
<given>
<evidence type="vendor" source="composer.lock" name="vendor" value="zendframework" confidence="HIGHEST"/>
</given>
<add>
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend" confidence="HIGHEST"/>
</add>
</hint>
<hint>
<given>
<evidence type="product" source="composer.lock" name="product" value="zendframework" confidence="HIGHEST"/>
</given>
<add>
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend_framework" confidence="HIGHEST"/>
</add>
</hint>
<vendorDuplicatingHint value="sun" duplicate="oracle"/>
<vendorDuplicatingHint value="oracle" duplicate="sun"/>
</hints>

View File

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema id="hints"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.0.xsd"
xmlns:dc="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.0.xsd">
<xs:simpleType name="type">
<xs:restriction base="xs:string">
<xs:enumeration value="vendor"/>
<xs:enumeration value="product"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="confidence">
<xs:restriction base="xs:string">
<xs:enumeration value="HIGHEST"/>
<xs:enumeration value="HIGH"/>
<xs:enumeration value="MEDIUM"/>
<xs:enumeration value="LOW"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="evidence">
<xs:attribute name="type" use="required" type="dc:type"/>
<xs:attribute name="source" use="required" type="xs:string"/>
<xs:attribute name="name" use="required" type="xs:string"/>
<xs:attribute name="value" use="required" type="xs:string"/>
<xs:attribute name="confidence" use="required" type="dc:confidence"/>
</xs:complexType>
<xs:complexType name="fileName">
<xs:attribute name="contains" use="required" type="xs:string"/>
<xs:attribute name="regex" use="optional" type="xs:boolean" default="false"/>
<xs:attribute name="caseSensitive" use="optional" type="xs:boolean" default="false"/>
</xs:complexType>
<xs:complexType name="given">
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="evidence" type="dc:evidence"/>
<xs:element name="fileName" type="dc:fileName"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="add">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="evidence" type="dc:evidence"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="hint">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="given" type="dc:given"/>
<xs:element name="add" type="dc:add"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="duplicatingHint">
<xs:attribute name="value" use="required" type="xs:string"/>
<xs:attribute name="duplicate" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="hints">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="hint" type="dc:hint"/>
</xs:sequence>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="vendorDuplicatingHint" type="dc:duplicatingHint"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -0,0 +1,77 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2016 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.xml.hints;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.Test;
import static org.junit.Assert.*;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.suppression.SuppressionErrorHandler;
import org.owasp.dependencycheck.suppression.SuppressionHandler;
import org.owasp.dependencycheck.suppression.SuppressionParser;
import org.owasp.dependencycheck.suppression.SuppressionRule;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
/**
*
* @author Jeremy Long
*/
public class HintHandlerTest extends BaseTest {
@Test
public void testHandler() throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException, SAXException, FileNotFoundException, UnsupportedEncodingException, IOException {
File file = BaseTest.getResourceAsFile(this, "hints.xml");
File schema = BaseTest.getResourceAsFile(this, "schema/dependency-hint.1.0.xsd");
HintHandler handler = new HintHandler();
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
SAXParser saxParser = factory.newSAXParser();
saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA);
saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, schema);
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setErrorHandler(new HintErrorHandler());
xmlReader.setContentHandler(handler);
InputStream inputStream = new FileInputStream(file);
Reader reader = new InputStreamReader(inputStream, "UTF-8");
InputSource in = new InputSource(reader);
xmlReader.parse(in);
List<HintRule> result = handler.getHintRules();
assertEquals("two hint rules should have been loaded",2,result.size());
}
}

View File

@@ -0,0 +1,69 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2016 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.xml.hints;
import java.io.File;
import java.io.InputStream;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.owasp.dependencycheck.BaseTest;
/**
*
* @author Jeremy Long
*/
public class HintParserTest extends BaseTest {
/**
* Test of parseHints method, of class HintParser.
*/
@Test
public void testParseHints_File() throws Exception {
File file = BaseTest.getResourceAsFile(this, "hints.xml");
HintParser instance = new HintParser();
Hints results = instance.parseHints(file);
assertEquals("Two duplicating hints should have been read", 2, results.getVendorDuplicatingHintRules().size());
assertEquals("Two hint rules should have been read", 2, results.getHintRules().size());
}
/**
* Test of parseHints method, of class HintParser.
*/
@Test
public void testParseHints_InputStream() throws Exception {
InputStream ins = BaseTest.getResourceAsStream(this, "hints.xml");
HintParser instance = new HintParser();
Hints results = instance.parseHints(ins);
assertEquals("Two duplicating hints should have been read", 2, results.getVendorDuplicatingHintRules().size());
assertEquals("Two hint rules should have been read", 2, results.getHintRules().size());
assertEquals("One add product should have been read", 1, results.getHintRules().get(0).getAddProduct().size());
assertEquals("One add vendor should have been read", 1, results.getHintRules().get(0).getAddVendor().size());
assertEquals("Two file name should have been read", 2, results.getHintRules().get(1).getFilenames().size());
assertEquals("add product name not found", "add product name", results.getHintRules().get(0).getAddProduct().get(0).getName());
assertEquals("add vendor name not found", "add vendor name", results.getHintRules().get(0).getAddVendor().get(0).getName());
assertEquals("given product name not found", "given product name", results.getHintRules().get(0).getGivenProduct().get(0).getName());
assertEquals("given vendor name not found", "given vendor name", results.getHintRules().get(0).getGivenVendor().get(0).getName());
assertEquals("spring file name not found", "spring", results.getHintRules().get(1).getFilenames().get(0).getValue());
assertEquals("file name 1 should not be case sensitive", false, results.getHintRules().get(1).getFilenames().get(0).isCaseSensitive());
assertEquals("file name 1 should not be a regex", false, results.getHintRules().get(1).getFilenames().get(0).isRegex());
assertEquals("file name 2 should be case sensitive", true, results.getHintRules().get(1).getFilenames().get(1).isCaseSensitive());
assertEquals("file name 2 should be a regex", true, results.getHintRules().get(1).getFilenames().get(1).isRegex());
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<hints xmlns="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.0.xsd">
<hint>
<given>
<evidence type="product" source="product source" name="given product name" value="value" confidence="HIGH"/>
<evidence type="vendor" source="vendor source" name="given vendor name" value="value" confidence="HIGH"/>
</given>
<add>
<evidence type="product" source="hint analyzer" name="add product name" value="product" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="add vendor name" value="vendor" confidence="HIGH"/>
</add>
</hint>
<hint>
<given>
<fileName contains="spring"/>
<fileName contains="struts" regex="true" caseSensitive="true"/>
</given>
<add>
<evidence type="product" source="hint analyzer" name="product" value="product" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="vendor" confidence="HIGH"/>
</add>
</hint>
<vendorDuplicatingHint value="sun" duplicate="oracle"/>
<vendorDuplicatingHint value="oracle" duplicate="sun"/>
</hints>