Coverage Report - org.owasp.dependencycheck.data.nvdcve.NvdCve20Handler
 
Classes in this File Line Coverage Branch Coverage Complexity
NvdCve20Handler
76%
97/126
84%
73/86
3
NvdCve20Handler$Element
94%
18/19
N/A
3
 
 1  
 /*
 2  
  * This file is part of dependency-check-core.
 3  
  *
 4  
  * Dependency-check-core is free software: you can redistribute it and/or modify it
 5  
  * under the terms of the GNU General Public License as published by the Free
 6  
  * Software Foundation, either version 3 of the License, or (at your option) any
 7  
  * later version.
 8  
  *
 9  
  * Dependency-check-core is distributed in the hope that it will be useful, but
 10  
  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 12  
  * details.
 13  
  *
 14  
  * You should have received a copy of the GNU General Public License along with
 15  
  * dependency-check-core. If not, see http://www.gnu.org/licenses/.
 16  
  *
 17  
  * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
 18  
  */
 19  
 package org.owasp.dependencycheck.data.nvdcve;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 import java.util.logging.Level;
 25  
 import java.util.logging.Logger;
 26  
 import org.apache.lucene.index.CorruptIndexException;
 27  
 import org.owasp.dependencycheck.data.cpe.CpeIndexWriter;
 28  
 import org.owasp.dependencycheck.dependency.Reference;
 29  
 import org.owasp.dependencycheck.dependency.Vulnerability;
 30  
 import org.owasp.dependencycheck.dependency.VulnerableSoftware;
 31  
 import org.xml.sax.Attributes;
 32  
 import org.xml.sax.SAXException;
 33  
 import org.xml.sax.SAXNotSupportedException;
 34  
 import org.xml.sax.helpers.DefaultHandler;
 35  
 
 36  
 /**
 37  
  * A SAX Handler that will parse the NVD CVE XML (schema version 2.0).
 38  
  *
 39  
  * @author Jeremy Long (jeremy.long@owasp.org)
 40  
  */
 41  1
 public class NvdCve20Handler extends DefaultHandler {
 42  
 
 43  
     /**
 44  
      * the current supported schema version.
 45  
      */
 46  
     private static final String CURRENT_SCHEMA_VERSION = "2.0";
 47  
     /**
 48  
      * the current element.
 49  
      */
 50  1
     private final Element current = new Element();
 51  
     /**
 52  
      * the text of the node.
 53  
      */
 54  
     private StringBuilder nodeText;
 55  
     /**
 56  
      * the vulnerability.
 57  
      */
 58  
     private Vulnerability vulnerability;
 59  
     /**
 60  
      * a reference for the cve.
 61  
      */
 62  
     private Reference reference;
 63  
     /**
 64  
      * flag indicating whether the application has a cpe.
 65  
      */
 66  1
     private boolean hasApplicationCpe = false;
 67  
     /**
 68  
      * The total number of entries parsed.
 69  
      */
 70  
     private int totalNumberOfEntries;
 71  
 
 72  
     /**
 73  
      * Get the value of totalNumberOfEntries.
 74  
      *
 75  
      * @return the value of totalNumberOfEntries
 76  
      */
 77  
     public int getTotalNumberOfEntries() {
 78  0
         return totalNumberOfEntries;
 79  
     }
 80  
     /**
 81  
      * The total number of application entries parsed.
 82  
      */
 83  
     private int totalNumberOfApplicationEntries;
 84  
 
 85  
     /**
 86  
      * Get the value of totalNumberOfApplicationEntries.
 87  
      *
 88  
      * @return the value of totalNumberOfApplicationEntries
 89  
      */
 90  
     public int getTotalNumberOfApplicationEntries() {
 91  0
         return totalNumberOfApplicationEntries;
 92  
     }
 93  
 
 94  
     @Override
 95  
     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
 96  2412
         current.setNode(qName);
 97  2412
         if (current.isEntryNode()) {
 98  27
             hasApplicationCpe = false;
 99  27
             vulnerability = new Vulnerability();
 100  27
             vulnerability.setName(attributes.getValue("id"));
 101  2385
         } else if (current.isVulnProductNode()) {
 102  727
             nodeText = new StringBuilder(100);
 103  1658
         } else if (current.isVulnReferencesNode()) {
 104  90
             final String lang = attributes.getValue("xml:lang");
 105  90
             if ("en".equals(lang)) {
 106  90
                 reference = new Reference();
 107  
             } else {
 108  0
                 reference = null;
 109  
             }
 110  90
         } else if (reference != null && current.isVulnReferenceNode()) {
 111  90
             reference.setUrl(attributes.getValue("href"));
 112  90
             nodeText = new StringBuilder(130);
 113  1478
         } else if (reference != null && current.isVulnSourceNode()) {
 114  90
             nodeText = new StringBuilder(30);
 115  1388
         } else if (current.isVulnSummaryNode()) {
 116  27
             nodeText = new StringBuilder(500);
 117  1361
         } else if (current.isNVDNode()) {
 118  1
             final String nvdVer = attributes.getValue("nvd_xml_version");
 119  1
             if (!CURRENT_SCHEMA_VERSION.equals(nvdVer)) {
 120  0
                 throw new SAXNotSupportedException("Schema version " + nvdVer + " is not supported");
 121  
             }
 122  1
         } else if (current.isVulnCWENode()) {
 123  19
             vulnerability.setCwe(attributes.getValue("id"));
 124  1341
         } else if (current.isCVSSScoreNode()) {
 125  26
             nodeText = new StringBuilder(5);
 126  1315
         } else if (current.isCVSSAccessVectorNode()) {
 127  26
             nodeText = new StringBuilder(20);
 128  1289
         } else if (current.isCVSSAccessComplexityNode()) {
 129  26
             nodeText = new StringBuilder(20);
 130  1263
         } else if (current.isCVSSAuthenticationNode()) {
 131  26
             nodeText = new StringBuilder(20);
 132  1237
         } else if (current.isCVSSAvailabilityImpactNode()) {
 133  26
             nodeText = new StringBuilder(20);
 134  1211
         } else if (current.isCVSSConfidentialityImpactNode()) {
 135  26
             nodeText = new StringBuilder(20);
 136  1185
         } else if (current.isCVSSIntegrityImpactNode()) {
 137  26
             nodeText = new StringBuilder(20);
 138  
         }
 139  2412
     }
 140  
 
 141  
     @Override
 142  
     public void characters(char[] ch, int start, int length) throws SAXException {
 143  3993
         if (nodeText != null) {
 144  1148
             nodeText.append(ch, start, length);
 145  
         }
 146  3993
     }
 147  
 
 148  
     @Override
 149  
     public void endElement(String uri, String localName, String qName) throws SAXException {
 150  2412
         current.setNode(qName);
 151  2412
         if (current.isEntryNode()) {
 152  27
             totalNumberOfEntries += 1;
 153  27
             if (hasApplicationCpe) {
 154  18
                 totalNumberOfApplicationEntries += 1;
 155  
                 try {
 156  18
                     saveEntry(vulnerability);
 157  0
                 } catch (DatabaseException ex) {
 158  0
                     throw new SAXException(ex);
 159  0
                 } catch (CorruptIndexException ex) {
 160  0
                     throw new SAXException(ex);
 161  0
                 } catch (IOException ex) {
 162  0
                     throw new SAXException(ex);
 163  18
                 }
 164  
             }
 165  27
             vulnerability = null;
 166  2385
         } else if (current.isCVSSScoreNode()) {
 167  
             try {
 168  26
                 final float score = Float.parseFloat(nodeText.toString());
 169  26
                 vulnerability.setCvssScore(score);
 170  0
             } catch (NumberFormatException ex) {
 171  0
                 Logger.getLogger(NvdCve20Handler.class.getName()).log(Level.SEVERE, "Error parsing CVSS Score.");
 172  0
                 Logger.getLogger(NvdCve20Handler.class.getName()).log(Level.FINE, null, ex);
 173  26
             }
 174  26
             nodeText = null;
 175  2359
         } else if (current.isCVSSAccessVectorNode()) {
 176  26
             vulnerability.setCvssAccessVector(nodeText.toString());
 177  26
             nodeText = null;
 178  2333
         } else if (current.isCVSSAccessComplexityNode()) {
 179  26
             vulnerability.setCvssAccessComplexity(nodeText.toString());
 180  26
             nodeText = null;
 181  2307
         } else if (current.isCVSSAuthenticationNode()) {
 182  26
             vulnerability.setCvssAuthentication(nodeText.toString());
 183  26
             nodeText = null;
 184  2281
         } else if (current.isCVSSAvailabilityImpactNode()) {
 185  26
             vulnerability.setCvssAvailabilityImpact(nodeText.toString());
 186  26
             nodeText = null;
 187  2255
         } else if (current.isCVSSConfidentialityImpactNode()) {
 188  26
             vulnerability.setCvssConfidentialityImpact(nodeText.toString());
 189  26
             nodeText = null;
 190  2229
         } else if (current.isCVSSIntegrityImpactNode()) {
 191  26
             vulnerability.setCvssIntegrityImpact(nodeText.toString());
 192  26
             nodeText = null;
 193  2203
         } else if (current.isVulnProductNode()) {
 194  727
             final String cpe = nodeText.toString();
 195  727
             if (cpe.startsWith("cpe:/a:")) {
 196  614
                 hasApplicationCpe = true;
 197  614
                 vulnerability.addVulnerableSoftware(cpe);
 198  
             }
 199  727
             nodeText = null;
 200  727
         } else if (reference != null && current.isVulnReferencesNode()) {
 201  90
             vulnerability.addReference(reference);
 202  90
             reference = null;
 203  1386
         } else if (reference != null && current.isVulnReferenceNode()) {
 204  90
             reference.setName(nodeText.toString());
 205  90
             nodeText = null;
 206  1296
         } else if (reference != null && current.isVulnSourceNode()) {
 207  90
             reference.setSource(nodeText.toString());
 208  90
             nodeText = null;
 209  1206
         } else if (current.isVulnSummaryNode()) {
 210  27
             vulnerability.setDescription(nodeText.toString());
 211  27
             nodeText = null;
 212  
         }
 213  2412
     }
 214  
     /**
 215  
      * the cve database.
 216  
      */
 217  
     private CveDB cveDB;
 218  
 
 219  
     /**
 220  
      * Sets the cveDB.
 221  
      *
 222  
      * @param db a reference to the CveDB
 223  
      */
 224  
     public void setCveDB(CveDB db) {
 225  0
         cveDB = db;
 226  0
     }
 227  
     /**
 228  
      * A list of CVE entries and associated VulnerableSoftware entries that
 229  
      * contain previous entries.
 230  
      */
 231  
     private Map<String, List<VulnerableSoftware>> prevVersionVulnMap;
 232  
 
 233  
     /**
 234  
      * Sets the prevVersionVulnMap.
 235  
      *
 236  
      * @param map the map of vulnerable software with previous versions being
 237  
      * vulnerable
 238  
      */
 239  
     public void setPrevVersionVulnMap(Map<String, List<VulnerableSoftware>> map) {
 240  0
         prevVersionVulnMap = map;
 241  0
     }
 242  
 
 243  
     /**
 244  
      * Saves a vulnerability to the CVE Database. This is a callback method
 245  
      * called by the Sax Parser Handler
 246  
      * {@link org.owasp.dependencycheck.data.nvdcve.xml.NvdCve20Handler}.
 247  
      *
 248  
      * @param vuln the vulnerability to store in the database
 249  
      * @throws DatabaseException thrown if there is an error writing to the
 250  
      * database
 251  
      * @throws CorruptIndexException is thrown if the CPE Index is corrupt
 252  
      * @throws IOException thrown if there is an IOException with the CPE Index
 253  
      */
 254  
     public void saveEntry(Vulnerability vuln) throws DatabaseException, CorruptIndexException, IOException {
 255  18
         if (cveDB == null) {
 256  18
             return;
 257  
         }
 258  0
         final String cveName = vuln.getName();
 259  0
         if (prevVersionVulnMap.containsKey(cveName)) {
 260  0
             final List<VulnerableSoftware> vulnSoftware = prevVersionVulnMap.get(cveName);
 261  0
             for (VulnerableSoftware vs : vulnSoftware) {
 262  0
                 vuln.updateVulnerableSoftware(vs);
 263  
             }
 264  
         }
 265  0
         for (VulnerableSoftware vs : vuln.getVulnerableSoftware()) {
 266  0
             if (cpeIndex != null) {
 267  0
                 cpeIndex.saveEntry(vs);
 268  
             }
 269  
         }
 270  0
         cveDB.updateVulnerability(vuln);
 271  0
     }
 272  
     /**
 273  
      * the cpe index.
 274  
      */
 275  
     private CpeIndexWriter cpeIndex;
 276  
 
 277  
     /**
 278  
      * Sets the cpe index writer.
 279  
      *
 280  
      * @param index the CPE Lucene Index
 281  
      */
 282  
     public void setCpeIndex(CpeIndexWriter index) {
 283  0
         cpeIndex = index;
 284  0
     }
 285  
 
 286  
     // <editor-fold defaultstate="collapsed" desc="The Element Class that maintains state information about the current node">
 287  
     /**
 288  
      * A simple class to maintain information about the current element while
 289  
      * parsing the NVD CVE XML.
 290  
      */
 291  1
     protected static class Element {
 292  
 
 293  
         /**
 294  
          * A node type in the NVD CVE Schema 2.0
 295  
          */
 296  
         public static final String NVD = "nvd";
 297  
         /**
 298  
          * A node type in the NVD CVE Schema 2.0
 299  
          */
 300  
         public static final String ENTRY = "entry";
 301  
         /**
 302  
          * A node type in the NVD CVE Schema 2.0
 303  
          */
 304  
         public static final String VULN_PRODUCT = "vuln:product";
 305  
         /**
 306  
          * A node type in the NVD CVE Schema 2.0
 307  
          */
 308  
         public static final String VULN_REFERENCES = "vuln:references";
 309  
         /**
 310  
          * A node type in the NVD CVE Schema 2.0
 311  
          */
 312  
         public static final String VULN_SOURCE = "vuln:source";
 313  
         /**
 314  
          * A node type in the NVD CVE Schema 2.0
 315  
          */
 316  
         public static final String VULN_REFERENCE = "vuln:reference";
 317  
         /**
 318  
          * A node type in the NVD CVE Schema 2.0
 319  
          */
 320  
         public static final String VULN_SUMMARY = "vuln:summary";
 321  
         /**
 322  
          * A node type in the NVD CVE Schema 2.0
 323  
          */
 324  
         public static final String VULN_CWE = "vuln:cwe";
 325  
         /**
 326  
          * A node type in the NVD CVE Schema 2.0
 327  
          */
 328  
         public static final String CVSS_SCORE = "cvss:score";
 329  
         /**
 330  
          * A node type in the NVD CVE Schema 2.0
 331  
          */
 332  
         public static final String CVSS_ACCESS_VECTOR = "cvss:access-vector";
 333  
         /**
 334  
          * A node type in the NVD CVE Schema 2.0
 335  
          */
 336  
         public static final String CVSS_ACCESS_COMPLEXITY = "cvss:access-complexity";
 337  
         /**
 338  
          * A node type in the NVD CVE Schema 2.0
 339  
          */
 340  
         public static final String CVSS_AUTHENTICATION = "cvss:authentication";
 341  
         /**
 342  
          * A node type in the NVD CVE Schema 2.0
 343  
          */
 344  
         public static final String CVSS_CONFIDENTIALITY_IMPACT = "cvss:confidentiality-impact";
 345  
         /**
 346  
          * A node type in the NVD CVE Schema 2.0
 347  
          */
 348  
         public static final String CVSS_INTEGRITY_IMPACT = "cvss:integrity-impact";
 349  
         /**
 350  
          * A node type in the NVD CVE Schema 2.0
 351  
          */
 352  
         public static final String CVSS_AVAILABILITY_IMPACT = "cvss:availability-impact";
 353  
         /**
 354  
          * The current node.
 355  
          */
 356  
         private String node;
 357  
 
 358  
         /**
 359  
          * Gets the value of node.
 360  
          *
 361  
          * @return the value of node
 362  
          */
 363  
         public String getNode() {
 364  0
             return this.node;
 365  
         }
 366  
 
 367  
         /**
 368  
          * Sets the value of node.
 369  
          *
 370  
          * @param node new value of node
 371  
          */
 372  
         public void setNode(String node) {
 373  4824
             this.node = node;
 374  4824
         }
 375  
 
 376  
         /**
 377  
          * Checks if the handler is at the NVD node.
 378  
          *
 379  
          * @return true or false
 380  
          */
 381  
         public boolean isNVDNode() {
 382  1361
             return NVD.equals(node);
 383  
         }
 384  
 
 385  
         /**
 386  
          * Checks if the handler is at the ENTRY node.
 387  
          *
 388  
          * @return true or false
 389  
          */
 390  
         public boolean isEntryNode() {
 391  4824
             return ENTRY.equals(node);
 392  
         }
 393  
 
 394  
         /**
 395  
          * Checks if the handler is at the VULN_PRODUCT node.
 396  
          *
 397  
          * @return true or false
 398  
          */
 399  
         public boolean isVulnProductNode() {
 400  4588
             return VULN_PRODUCT.equals(node);
 401  
         }
 402  
 
 403  
         /**
 404  
          * Checks if the handler is at the REFERENCES node.
 405  
          *
 406  
          * @return true or false
 407  
          */
 408  
         public boolean isVulnReferencesNode() {
 409  1928
             return VULN_REFERENCES.equals(node);
 410  
         }
 411  
 
 412  
         /**
 413  
          * Checks if the handler is at the REFERENCE node.
 414  
          *
 415  
          * @return true or false
 416  
          */
 417  
         public boolean isVulnReferenceNode() {
 418  360
             return VULN_REFERENCE.equals(node);
 419  
         }
 420  
 
 421  
         /**
 422  
          * Checks if the handler is at the VULN_SOURCE node.
 423  
          *
 424  
          * @return true or false
 425  
          */
 426  
         public boolean isVulnSourceNode() {
 427  180
             return VULN_SOURCE.equals(node);
 428  
         }
 429  
 
 430  
         /**
 431  
          * Checks if the handler is at the VULN_SUMMARY node.
 432  
          *
 433  
          * @return true or false
 434  
          */
 435  
         public boolean isVulnSummaryNode() {
 436  2594
             return VULN_SUMMARY.equals(node);
 437  
         }
 438  
 
 439  
         /**
 440  
          * Checks if the handler is at the VULN_CWE node.
 441  
          *
 442  
          * @return true or false
 443  
          */
 444  
         public boolean isVulnCWENode() {
 445  1360
             return VULN_CWE.equals(node);
 446  
         }
 447  
 
 448  
         /**
 449  
          * Checks if the handler is at the CVSS_SCORE node.
 450  
          *
 451  
          * @return true or false
 452  
          */
 453  
         public boolean isCVSSScoreNode() {
 454  3726
             return CVSS_SCORE.equals(node);
 455  
         }
 456  
 
 457  
         /**
 458  
          * Checks if the handler is at the CVSS_ACCESS_VECTOR node.
 459  
          *
 460  
          * @return true or false
 461  
          */
 462  
         public boolean isCVSSAccessVectorNode() {
 463  3674
             return CVSS_ACCESS_VECTOR.equals(node);
 464  
         }
 465  
 
 466  
         /**
 467  
          * Checks if the handler is at the CVSS_ACCESS_COMPLEXITY node.
 468  
          *
 469  
          * @return true or false
 470  
          */
 471  
         public boolean isCVSSAccessComplexityNode() {
 472  3622
             return CVSS_ACCESS_COMPLEXITY.equals(node);
 473  
         }
 474  
 
 475  
         /**
 476  
          * Checks if the handler is at the CVSS_AUTHENTICATION node.
 477  
          *
 478  
          * @return true or false
 479  
          */
 480  
         public boolean isCVSSAuthenticationNode() {
 481  3570
             return CVSS_AUTHENTICATION.equals(node);
 482  
         }
 483  
 
 484  
         /**
 485  
          * Checks if the handler is at the CVSS_CONFIDENTIALITY_IMPACT node.
 486  
          *
 487  
          * @return true or false
 488  
          */
 489  
         public boolean isCVSSConfidentialityImpactNode() {
 490  3466
             return CVSS_CONFIDENTIALITY_IMPACT.equals(node);
 491  
         }
 492  
 
 493  
         /**
 494  
          * Checks if the handler is at the CVSS_INTEGRITY_IMPACT node.
 495  
          *
 496  
          * @return true or false
 497  
          */
 498  
         public boolean isCVSSIntegrityImpactNode() {
 499  3414
             return CVSS_INTEGRITY_IMPACT.equals(node);
 500  
         }
 501  
 
 502  
         /**
 503  
          * Checks if the handler is at the CVSS_AVAILABILITY_IMPACT node.
 504  
          *
 505  
          * @return true or false
 506  
          */
 507  
         public boolean isCVSSAvailabilityImpactNode() {
 508  3518
             return CVSS_AVAILABILITY_IMPACT.equals(node);
 509  
         }
 510  
     }
 511  
     // </editor-fold>
 512  
 }