View Javadoc

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