| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| NvdCve12Handler |
|
| 2.6;2.6 | ||||
| NvdCve12Handler$Element |
|
| 2.6;2.6 |
| 1 | /* | |
| 2 | * This file is part of dependency-check-core. | |
| 3 | * | |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
| 5 | * you may not use this file except in compliance with the License. | |
| 6 | * You may obtain a copy of the License at | |
| 7 | * | |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 9 | * | |
| 10 | * Unless required by applicable law or agreed to in writing, software | |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 | * See the License for the specific language governing permissions and | |
| 14 | * limitations under the License. | |
| 15 | * | |
| 16 | * Copyright (c) 2012 Jeremy Long. All Rights Reserved. | |
| 17 | */ | |
| 18 | package org.owasp.dependencycheck.data.update.xml; | |
| 19 | ||
| 20 | import java.util.ArrayList; | |
| 21 | import java.util.HashMap; | |
| 22 | import java.util.List; | |
| 23 | import java.util.Map; | |
| 24 | import org.owasp.dependencycheck.dependency.VulnerableSoftware; | |
| 25 | import org.xml.sax.Attributes; | |
| 26 | import org.xml.sax.SAXException; | |
| 27 | import org.xml.sax.SAXNotSupportedException; | |
| 28 | import org.xml.sax.helpers.DefaultHandler; | |
| 29 | ||
| 30 | /** | |
| 31 | * A SAX Handler that will parse the NVD CVE XML (schema version 1.2). This parses the xml and retrieves a listing of | |
| 32 | * CPEs that have previous versions specified. The previous version information is not in the 2.0 version of the schema | |
| 33 | * and is useful to ensure accurate identification (or at least complete). | |
| 34 | * | |
| 35 | * @author Jeremy Long <jeremy.long@owasp.org> | |
| 36 | */ | |
| 37 | 0 | public class NvdCve12Handler extends DefaultHandler { |
| 38 | ||
| 39 | /** | |
| 40 | * the supported schema version. | |
| 41 | */ | |
| 42 | private static final String CURRENT_SCHEMA_VERSION = "1.2"; | |
| 43 | /** | |
| 44 | * the current vulnerability. | |
| 45 | */ | |
| 46 | private String vulnerability; | |
| 47 | /** | |
| 48 | * a list of vulnerable software. | |
| 49 | */ | |
| 50 | private List<VulnerableSoftware> software; | |
| 51 | /** | |
| 52 | * the vendor name. | |
| 53 | */ | |
| 54 | private String vendor; | |
| 55 | /** | |
| 56 | * the product name. | |
| 57 | */ | |
| 58 | private String product; | |
| 59 | /** | |
| 60 | * if the nvd cve should be skipped because it was rejected. | |
| 61 | */ | |
| 62 | 0 | private boolean skip = false; |
| 63 | /** | |
| 64 | * flag indicating if there is a previous version. | |
| 65 | */ | |
| 66 | 0 | private boolean hasPreviousVersion = false; |
| 67 | /** | |
| 68 | * The current element. | |
| 69 | */ | |
| 70 | 0 | private final Element current = new Element(); |
| 71 | /** | |
| 72 | * a map of vulnerabilities. | |
| 73 | */ | |
| 74 | private Map<String, List<VulnerableSoftware>> vulnerabilities; | |
| 75 | ||
| 76 | /** | |
| 77 | * Get the value of vulnerabilities. | |
| 78 | * | |
| 79 | * @return the value of vulnerabilities | |
| 80 | */ | |
| 81 | public Map<String, List<VulnerableSoftware>> getVulnerabilities() { | |
| 82 | return vulnerabilities; | |
| 83 | } | |
| 84 | ||
| 85 | @Override | |
| 86 | public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { | |
| 87 | 0 | current.setNode(qName); |
| 88 | 0 | if (current.isEntryNode()) { |
| 89 | 0 | vendor = null; |
| 90 | 0 | product = null; |
| 91 | 0 | hasPreviousVersion = false; |
| 92 | 0 | final String reject = attributes.getValue("reject"); |
| 93 | 0 | skip = "1".equals(reject); |
| 94 | 0 | if (!skip) { |
| 95 | 0 | vulnerability = attributes.getValue("name"); |
| 96 | 0 | software = new ArrayList<VulnerableSoftware>(); |
| 97 | } else { | |
| 98 | 0 | vulnerability = null; |
| 99 | 0 | software = null; |
| 100 | } | |
| 101 | 0 | } else if (!skip && current.isProdNode()) { |
| 102 | ||
| 103 | 0 | vendor = attributes.getValue("vendor"); |
| 104 | 0 | product = attributes.getValue("name"); |
| 105 | 0 | } else if (!skip && current.isVersNode()) { |
| 106 | 0 | final String prev = attributes.getValue("prev"); |
| 107 | 0 | if (prev != null && "1".equals(prev)) { |
| 108 | 0 | hasPreviousVersion = true; |
| 109 | 0 | final String edition = attributes.getValue("edition"); |
| 110 | 0 | final String num = attributes.getValue("num"); |
| 111 | ||
| 112 | /*yes yes, this may not actually be an "a" - it could be an OS, etc. but for our | |
| 113 | purposes this is good enough as we won't use this if we don't find a corresponding "a" | |
| 114 | in the nvd cve 2.0. */ | |
| 115 | 0 | String cpe = "cpe:/a:" + vendor + ":" + product; |
| 116 | 0 | if (num != null) { |
| 117 | 0 | cpe += ":" + num; |
| 118 | } | |
| 119 | 0 | if (edition != null) { |
| 120 | 0 | cpe += ":" + edition; |
| 121 | } | |
| 122 | 0 | final VulnerableSoftware vs = new VulnerableSoftware(); |
| 123 | 0 | vs.setCpe(cpe); |
| 124 | 0 | vs.setPreviousVersion(prev); |
| 125 | 0 | software.add(vs); |
| 126 | } | |
| 127 | 0 | } else if (current.isNVDNode()) { |
| 128 | 0 | final String nvdVer = attributes.getValue("nvd_xml_version"); |
| 129 | 0 | if (!CURRENT_SCHEMA_VERSION.equals(nvdVer)) { |
| 130 | 0 | throw new SAXNotSupportedException("Schema version " + nvdVer + " is not supported"); |
| 131 | } | |
| 132 | 0 | vulnerabilities = new HashMap<String, List<VulnerableSoftware>>(); |
| 133 | } | |
| 134 | 0 | } |
| 135 | ||
| 136 | @Override | |
| 137 | public void endElement(String uri, String localName, String qName) throws SAXException { | |
| 138 | 0 | current.setNode(qName); |
| 139 | 0 | if (current.isEntryNode()) { |
| 140 | 0 | if (!skip && hasPreviousVersion) { |
| 141 | 0 | vulnerabilities.put(vulnerability, software); |
| 142 | } | |
| 143 | 0 | vulnerability = null; |
| 144 | 0 | software = null; |
| 145 | } | |
| 146 | 0 | } |
| 147 | ||
| 148 | // <editor-fold defaultstate="collapsed" desc="The Element Class that maintains state information about the current node"> | |
| 149 | /** | |
| 150 | * A simple class to maintain information about the current element while parsing the NVD CVE XML. | |
| 151 | */ | |
| 152 | 0 | protected static class Element { |
| 153 | ||
| 154 | /** | |
| 155 | * A node type in the NVD CVE Schema 1.2. | |
| 156 | */ | |
| 157 | public static final String NVD = "nvd"; | |
| 158 | /** | |
| 159 | * A node type in the NVD CVE Schema 1.2. | |
| 160 | */ | |
| 161 | public static final String ENTRY = "entry"; | |
| 162 | /** | |
| 163 | * A node type in the NVD CVE Schema 1.2. | |
| 164 | */ | |
| 165 | public static final String VULN_SOFTWARE = "vuln_soft"; | |
| 166 | /** | |
| 167 | * A node type in the NVD CVE Schema 1.2. | |
| 168 | */ | |
| 169 | public static final String PROD = "prod"; | |
| 170 | /** | |
| 171 | * A node type in the NVD CVE Schema 1.2. | |
| 172 | */ | |
| 173 | public static final String VERS = "vers"; | |
| 174 | /** | |
| 175 | * The name of the current node. | |
| 176 | */ | |
| 177 | private String node; | |
| 178 | ||
| 179 | /** | |
| 180 | * Gets the value of node. | |
| 181 | * | |
| 182 | * @return the value of node | |
| 183 | */ | |
| 184 | public String getNode() { | |
| 185 | return this.node; | |
| 186 | } | |
| 187 | ||
| 188 | /** | |
| 189 | * Sets the value of node. | |
| 190 | * | |
| 191 | * @param node new value of node | |
| 192 | */ | |
| 193 | public void setNode(String node) { | |
| 194 | this.node = node; | |
| 195 | } | |
| 196 | ||
| 197 | /** | |
| 198 | * Checks if the handler is at the NVD node. | |
| 199 | * | |
| 200 | * @return true or false | |
| 201 | */ | |
| 202 | public boolean isNVDNode() { | |
| 203 | 0 | return NVD.equals(node); |
| 204 | } | |
| 205 | ||
| 206 | /** | |
| 207 | * Checks if the handler is at the ENTRY node. | |
| 208 | * | |
| 209 | * @return true or false | |
| 210 | */ | |
| 211 | public boolean isEntryNode() { | |
| 212 | 0 | return ENTRY.equals(node); |
| 213 | } | |
| 214 | ||
| 215 | /** | |
| 216 | * Checks if the handler is at the VULN_SOFTWARE node. | |
| 217 | * | |
| 218 | * @return true or false | |
| 219 | */ | |
| 220 | public boolean isVulnSoftwareNode() { | |
| 221 | 0 | return VULN_SOFTWARE.equals(node); |
| 222 | } | |
| 223 | ||
| 224 | /** | |
| 225 | * Checks if the handler is at the PROD node. | |
| 226 | * | |
| 227 | * @return true or false | |
| 228 | */ | |
| 229 | public boolean isProdNode() { | |
| 230 | 0 | return PROD.equals(node); |
| 231 | } | |
| 232 | ||
| 233 | /** | |
| 234 | * Checks if the handler is at the VERS node. | |
| 235 | * | |
| 236 | * @return true or false | |
| 237 | */ | |
| 238 | public boolean isVersNode() { | |
| 239 | 0 | return VERS.equals(node); |
| 240 | } | |
| 241 | } | |
| 242 | // </editor-fold> | |
| 243 | } |