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.update;
    20
    21  import java.io.File;
    22  import java.io.IOException;
    23  import java.net.MalformedURLException;
    24  import java.sql.SQLException;
    25  import java.util.List;
    26  import java.util.Map;
    27  import java.util.logging.Level;
    28  import java.util.logging.Logger;
    29  import javax.xml.parsers.ParserConfigurationException;
    30  import javax.xml.parsers.SAXParser;
    31  import javax.xml.parsers.SAXParserFactory;
    32  import org.owasp.dependencycheck.data.UpdateException;
    33  import org.owasp.dependencycheck.data.cpe.CpeIndexWriter;
    34  import org.owasp.dependencycheck.data.nvdcve.CveDB;
    35  import org.owasp.dependencycheck.utils.FileUtils;
    36  import org.owasp.dependencycheck.utils.Settings;
    37  import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
    38  import org.owasp.dependencycheck.data.nvdcve.NvdCve12Handler;
    39  import org.owasp.dependencycheck.data.nvdcve.NvdCve20Handler;
    40  import org.owasp.dependencycheck.dependency.VulnerableSoftware;
    41  import org.owasp.dependencycheck.utils.DownloadFailedException;
    42  import org.xml.sax.SAXException;
    43
    44  /**
    45   * Class responsible for updating the CPE and NVDCVE data stores.
    46   *
    47   * @author Jeremy Long (jeremy.long@owasp.org)
    48   */
    49  public abstract class AbstractUpdateTask implements UpdateTask {
    50
    51      /**
    52       * Initializes the AbstractUpdateTask.
    53       *
    54       * @param properties information about the data store
    55       * @throws MalformedURLException thrown if the configuration contains a
    56       * malformed url
    57       * @throws DownloadFailedException thrown if the timestamp on a file cannot
    58       * be checked
    59       * @throws UpdateException thrown if the update fails
    60       */
    61      public AbstractUpdateTask(DataStoreMetaInfo properties) throws MalformedURLException, DownloadFailedException, UpdateException {
    62          this.properties = properties;
    63          this.updateable = updatesNeeded();
    64      }
    65      /**
    66       * A collection of updateable NVD CVE items.
    67       */
    68      private Updateable updateable;
    69      /**
    70       * Utility to read and write meta-data about the data.
    71       */
    72      private DataStoreMetaInfo properties = null;
    73
    74      /**
    75       * Returns the data store properties.
    76       *
    77       * @return the data store properties
    78       */
    79      protected DataStoreMetaInfo getProperties() {
    80          return properties;
    81      }
    82      /**
    83       * Reference to the Cve Database.
    84       */
    85      private CveDB cveDB = null;
    86
    87      /**
    88       * Returns the CveDB.
    89       *
    90       * @return the CveDB
    91       */
    92      protected CveDB getCveDB() {
    93          return cveDB;
    94      }
    95      /**
    96       * Reference to the Cpe Index.
    97       */
    98      private CpeIndexWriter cpeIndex = null;
    99
    100     /**
    101      * Returns the CpeIndex.
    102      *
    103      * @return the CpeIndex
    104      */
    105     protected CpeIndexWriter getCpeIndex() {
    106         return cpeIndex;
    107     }
    108
    109     /**
    110      * Gets whether or not an update is needed.
    111      *
    112      * @return true or false depending on whether an update is needed
    113      */
    114     public boolean isUpdateNeeded() {
    115         return updateable.isUpdateNeeded();
    116     }
    117
    118     /**
    119      * Gets the updateable NVD CVE Entries.
    120      *
    121      * @return an Updateable object containing the NVD CVE entries
    122      */
    123     protected Updateable getUpdateable() {
    124         return updateable;
    125     }
    126
    127     /**
    128      * Determines if the index needs to be updated.
    129      *
    130      * @return a collection of updateable resources.
    131      * @throws MalformedURLException is thrown if the URL for the NVD CVE Meta
    132      * data is incorrect.
    133      * @throws DownloadFailedException is thrown if there is an error.
    134      * downloading the NVD CVE download data file.
    135      * @throws UpdateException Is thrown if there is an issue with the last
    136      * updated properties file.
    137      */
    138     protected abstract Updateable updatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException;
    139
    140     /**
    141      * <p>Updates the data store to the latest version.</p>
    142      *
    143      * @throws UpdateException is thrown if there is an error updating the
    144      * database
    145      */
    146     public abstract void update() throws UpdateException;
    147     /**
    148      * A flag indicating whether or not the current data store should be
    149      * deleted.
    150      */
    151     private boolean deleteAndRecreate = false;
    152
    153     /**
    154      * Get the value of deleteAndRecreate.
    155      *
    156      * @return the value of deleteAndRecreate
    157      */
    158     public boolean shouldDeleteAndRecreate() {
    159         return deleteAndRecreate;
    160     }
    161
    162     /**
    163      * Set the value of deleteAndRecreate.
    164      *
    165      * @param deleteAndRecreate new value of deleteAndRecreate
    166      */
    167     protected void setDeleteAndRecreate(boolean deleteAndRecreate) {
    168         this.deleteAndRecreate = deleteAndRecreate;
    169     }
    170
    171     /**
    172      * Deletes the existing data directories.
    173      *
    174      * @throws IOException thrown if the directory cannot be deleted
    175      */
    176     protected void deleteExistingData() throws IOException {
    177         File data = Settings.getFile(Settings.KEYS.CVE_DATA_DIRECTORY);
    178         if (data.exists()) {
    179             FileUtils.delete(data);
    180         }
    181         data = Settings.getFile(Settings.KEYS.CPE_DATA_DIRECTORY);
    182         if (data.exists()) {
    183             FileUtils.delete(data);
    184         }
    185         data = DataStoreMetaInfo.getPropertiesFile();
    186         if (data.exists()) {
    187             FileUtils.delete(data);
    188         }
    189     }
    190
    191     /**
    192      * Closes the CVE and CPE data stores.
    193      */
    194     protected void closeDataStores() {
    195         if (cveDB != null) {
    196             try {
    197                 cveDB.close();
    198             } catch (Exception ignore) {
    199                 Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINEST, "Error closing the cveDB", ignore);
    200             }
    201         }
    202         if (cpeIndex != null) {
    203             try {
    204                 cpeIndex.close();
    205             } catch (Exception ignore) {
    206                 Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINEST, "Error closing the cpeIndex", ignore);
    207             }
    208         }
    209     }
    210
    211     /**
    212      * Opens the CVE and CPE data stores.
    213      *
    214      * @throws UpdateException thrown if a data store cannot be opened
    215      */
    216     protected void openDataStores() throws UpdateException {
    217         //open the cve and cpe data stores
    218         try {
    219             cveDB = new CveDB();
    220             cveDB.open();
    221             cpeIndex = new CpeIndexWriter();
    222             cpeIndex.open();
    223         } catch (IOException ex) {
    224             closeDataStores();
    225             Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "IO Error opening databases", ex);
    226             throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
    227         } catch (SQLException ex) {
    228             closeDataStores();
    229             Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "SQL Exception opening databases", ex);
    230             throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
    231         } catch (DatabaseException ex) {
    232             closeDataStores();
    233             Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "Database Exception opening databases", ex);
    234             throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
    235         } catch (ClassNotFoundException ex) {
    236             closeDataStores();
    237             Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "Class not found exception opening databases", ex);
    238             throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
    239         }
    240     }
    241
    242     /**
    243      * Determines if the epoch date is within the range specified of the
    244      * compareTo epoch time. This takes the (compareTo-date)/1000/60/60/24 to
    245      * get the number of days. If the calculated days is less then the range the
    246      * date is considered valid.
    247      *
    248      * @param date the date to be checked.
    249      * @param compareTo the date to compare to.
    250      * @param range the range in days to be considered valid.
    251      * @return whether or not the date is within the range.
    252      */
    253     protected boolean withinRange(long date, long compareTo, int range) {
    254         final double differenceInDays = (compareTo - date) / 1000.0 / 60.0 / 60.0 / 24.0;
    255         return differenceInDays < range;
    256     }
    257
    258     /**
    259      * Imports the NVD CVE XML File into the Lucene Index.
    260      *
    261      * @param file the file containing the NVD CVE XML
    262      * @param oldVersion contains the file containing the NVD CVE XML 1.2
    263      * @throws ParserConfigurationException is thrown if there is a parser
    264      * configuration exception
    265      * @throws SAXException is thrown if there is a SAXException
    266      * @throws IOException is thrown if there is a IO Exception
    267      * @throws SQLException is thrown if there is a SQL exception
    268      * @throws DatabaseException is thrown if there is a database exception
    269      * @throws ClassNotFoundException thrown if the h2 database driver cannot be
    270      * loaded
    271      */
    272     protected void importXML(File file, File oldVersion)
    273             throws ParserConfigurationException, SAXException, IOException, SQLException, DatabaseException, ClassNotFoundException {
    274
    275         final SAXParserFactory factory = SAXParserFactory.newInstance();
    276         final SAXParser saxParser = factory.newSAXParser();
    277
    278         final NvdCve12Handler cve12Handler = new NvdCve12Handler();
    279         saxParser.parse(oldVersion, cve12Handler);
    280         final Map<String, List<VulnerableSoftware>> prevVersionVulnMap = cve12Handler.getVulnerabilities();
    281
    282         final NvdCve20Handler cve20Handler = new NvdCve20Handler();
    283         cve20Handler.setCveDB(cveDB);
    284         cve20Handler.setPrevVersionVulnMap(prevVersionVulnMap);
    285         cve20Handler.setCpeIndex(cpeIndex);
    286         saxParser.parse(file, cve20Handler);
    287     }
    288 }