View Javadoc
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) 2020 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.data.nvdcve;
19  
20  import com.google.common.base.Strings;
21  import java.sql.Connection;
22  import java.sql.PreparedStatement;
23  import java.sql.ResultSet;
24  import java.sql.SQLException;
25  import java.sql.Types;
26  import org.h2.tools.SimpleResultSet;
27  
28  /**
29   * Stored procedures for the H2 database.
30   *
31   * @author Jeremy Long
32   */
33  public final class H2Functions {
34  
35      private H2Functions() {
36          //empty constructor for utility class
37      }
38  
39      //CSOFF: ParameterNumber
40      /**
41       * Adds a CPE to a vulnerability; if the CPE is not contained in the
42       * database it is first added.
43       *
44       * @param conn the database connection
45       * @param vulnerabilityId the vulnerability id
46       * @param part the CPE part
47       * @param vendor the CPE vendor
48       * @param product the CPE product
49       * @param version the CPE version
50       * @param update the CPE update version
51       * @param edition the CPE edition
52       * @param language the CPE language
53       * @param swEdition the CPE software edition
54       * @param targetSw the CPE target software
55       * @param targetHw the CPE target hardware
56       * @param other the CPE other
57       * @param ecosystem the ecosystem
58       * @param versionEndExcluding a version range to identify the software
59       * @param versionEndIncluding a version range to identify the software
60       * @param versionStartExcluding a version range to identify the software
61       * @param versionStartIncluding a version range to identify the software
62       * @param vulnerable a flag indicating whether or not the software is
63       * vulnerable
64       * @throws SQLException thrown if there is an error adding the CPE or
65       * software reference
66       */
67      public static void insertSoftware(final Connection conn, int vulnerabilityId, String part, String vendor,
68              String product, String version, String update, String edition, String language, String swEdition,
69              String targetSw, String targetHw, String other, String ecosystem, String versionEndExcluding,
70              String versionEndIncluding, String versionStartExcluding, String versionStartIncluding, Boolean vulnerable) throws SQLException {
71          int cpeID = 0;
72          try (PreparedStatement selectCpeId = conn.prepareStatement("SELECT id, ecosystem FROM cpeEntry WHERE part=? AND vendor=? AND product=? "
73                  + "AND version=? AND update_version=? AND edition=? AND lang=? AND sw_edition=? AND target_sw=? AND target_hw=? AND other=?")) {
74              selectCpeId.setString(1, part);
75              selectCpeId.setString(2, vendor);
76              selectCpeId.setString(3, product);
77              selectCpeId.setString(4, version);
78              selectCpeId.setString(5, update);
79              selectCpeId.setString(6, edition);
80              selectCpeId.setString(7, language);
81              selectCpeId.setString(8, swEdition);
82              selectCpeId.setString(9, targetSw);
83              selectCpeId.setString(10, targetHw);
84              selectCpeId.setString(11, other);
85  
86              try (ResultSet rs = selectCpeId.executeQuery()) {
87                  if (rs.next()) {
88                      cpeID = rs.getInt(1);
89                      final String e = rs.getString(2);
90                      if (e == null && ecosystem != null) {
91                          try (PreparedStatement updateEcosystem = conn.prepareStatement("UPDATE cpeEntry SET ecosystem=? WHERE id=?")) {
92                              updateEcosystem.setString(1, ecosystem);
93                              updateEcosystem.setInt(2, cpeID);
94                              updateEcosystem.execute();
95                          }
96                      }
97                  }
98              }
99          }
100         if (cpeID == 0) {
101             final String[] returnedColumns = {"id"};
102             try (PreparedStatement insertCpe = conn.prepareStatement("INSERT INTO cpeEntry (part, vendor, product, version, update_version, "
103                     + "edition, lang, sw_edition, target_sw, target_hw, other, ecosystem) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
104                     returnedColumns)) {
105                 insertCpe.setString(1, part);
106                 insertCpe.setString(2, vendor);
107                 insertCpe.setString(3, product);
108                 insertCpe.setString(4, version);
109                 insertCpe.setString(5, update);
110                 insertCpe.setString(6, edition);
111                 insertCpe.setString(7, language);
112                 insertCpe.setString(8, swEdition);
113                 insertCpe.setString(9, targetSw);
114                 insertCpe.setString(10, targetHw);
115                 insertCpe.setString(11, other);
116                 setStringOrNull(insertCpe, 12, ecosystem);
117                 insertCpe.executeUpdate();
118                 try (ResultSet rs = insertCpe.getGeneratedKeys()) {
119                     if (rs.next()) {
120                         cpeID = rs.getInt(1);
121                     }
122                 }
123             }
124         }
125         //CSON: ParameterNumber
126 
127         try (PreparedStatement insertSoftware = conn.prepareStatement("INSERT INTO software (cveid, cpeEntryId, "
128                 + "versionEndExcluding, versionEndIncluding, versionStartExcluding, versionStartIncluding, "
129                 + "vulnerable) VALUES (?, ?, ?, ?, ?, ?, ?)")) {
130             insertSoftware.setInt(1, vulnerabilityId);
131             insertSoftware.setInt(2, cpeID);
132 
133             setStringOrNull(insertSoftware, 3, versionEndExcluding);
134             setStringOrNull(insertSoftware, 4, versionEndIncluding);
135             setStringOrNull(insertSoftware, 5, versionStartExcluding);
136             setStringOrNull(insertSoftware, 6, versionStartIncluding);
137             setBooleanOrNull(insertSoftware, 7, vulnerable);
138             insertSoftware.execute();
139         }
140     }
141 
142     //CSOFF: ParameterNumber
143     /**
144      * Updates or inserts the vulnerability into the database. If updating a
145      * vulnerability the method will delete all software, CWE, and references
146      * and new entries will be added later.
147      *
148      * @param conn the database connection
149      * @param cve the CVE identifier
150      * @param description the vulnerability description
151      * @param v2Severity the CVSS v2 severity
152      * @param v2ExploitabilityScore the CVSS v2 exploitability score
153      * @param v2ImpactScore the CVSS v2 impact score
154      * @param v2AcInsufInfo the CVSS v2 AcInsufInfo
155      * @param v2ObtainAllPrivilege the CVSS v2 obtain all privilege flag
156      * @param v2ObtainUserPrivilege the CVSS v2 obtain user privilege flag
157      * @param v2ObtainOtherPrivilege the CVSS v2 obtain other privilege flag
158      * @param v2UserInteractionRequired the CVSS v2 user interaction required
159      * flag
160      * @param v2Score the CVSS v2 score
161      * @param v2AccessVector the CVSS v2 access vector
162      * @param v2AccessComplexity the CVSS v2 access complexity
163      * @param v2Authentication the CVSS v2 authentication
164      * @param v2ConfidentialityImpact the CVSS v2 confidentiality impact
165      * @param v2IntegrityImpact the CVSS v2 integrity impact
166      * @param v2AvailabilityImpact the CVSS v2 availability impact
167      * @param v2Version the CVSS v2 version
168      * @param v3ExploitabilityScore the CVSS v3 exploitability score
169      * @param v3ImpactScore the CVSS v3 impact score
170      * @param v3AttackVector the CVSS v3 attack vector
171      * @param v3AttackComplexity the CVSS v3 attack complexity
172      * @param v3PrivilegesRequired the CVSS v3 privilege required flag
173      * @param v3UserInteraction the CVSS v3 user interaction required flag
174      * @param v3Scope the CVSS v3 scope
175      * @param v3ConfidentialityImpact the CVSS v3 confidentiality impact
176      * @param v3IntegrityImpact the CVSS v3 integrity impact
177      * @param v3AvailabilityImpact the CVSS v3 availability impact
178      * @param v3BaseScore the CVSS v3 base score
179      * @param v3BaseSeverity the CVSS v3 base severity
180      * @param v3Version the CVSS v3 version
181      * @param v4version CVSS v4 data
182      * @param v4attackVector CVSS v4 data
183      * @param v4attackComplexity CVSS v4 data
184      * @param v4attackRequirements CVSS v4 data
185      * @param v4privilegesRequired CVSS v4 data
186      * @param v4userInteraction CVSS v4 data
187      * @param v4vulnConfidentialityImpact CVSS v4 data
188      * @param v4vulnIntegrityImpact CVSS v4 data
189      * @param v4vulnAvailabilityImpact CVSS v4 data
190      * @param v4subConfidentialityImpact CVSS v4 data
191      * @param v4subIntegrityImpact CVSS v4 data
192      * @param v4subAvailabilityImpact CVSS v4 data
193      * @param v4exploitMaturity CVSS v4 data
194      * @param v4confidentialityRequirement CVSS v4 data
195      * @param v4integrityRequirement CVSS v4 data
196      * @param v4availabilityRequirement CVSS v4 data
197      * @param v4modifiedAttackVector CVSS v4 data
198      * @param v4modifiedAttackComplexity CVSS v4 data
199      * @param v4modifiedAttackRequirements CVSS v4 data
200      * @param v4modifiedPrivilegesRequired CVSS v4 data
201      * @param v4modifiedUserInteraction CVSS v4 data
202      * @param v4modifiedVulnConfidentialityImpact CVSS v4 data
203      * @param v4modifiedVulnIntegrityImpact CVSS v4 data
204      * @param v4modifiedVulnAvailabilityImpact CVSS v4 data
205      * @param v4modifiedSubConfidentialityImpact CVSS v4 data
206      * @param v4modifiedSubIntegrityImpact CVSS v4 data
207      * @param v4modifiedSubAvailabilityImpact CVSS v4 data
208      * @param v4safety CVSS v4 data
209      * @param v4automatable CVSS v4 data
210      * @param v4recovery CVSS v4 data
211      * @param v4valueDensity CVSS v4 data
212      * @param v4vulnerabilityResponseEffort CVSS v4 data
213      * @param v4providerUrgency CVSS v4 data
214      * @param v4baseScore CVSS v4 data
215      * @param v4baseSeverity CVSS v4 data
216      * @param v4threatScore CVSS v4 data
217      * @param v4threatSeverity CVSS v4 data
218      * @param v4environmentalScore CVSS v4 data
219      * @param v4environmentalSeverity CVSS v4 data
220      * @param v4source CVSS v4 data
221      * @param v4type CVSS v4 data
222      * @return a result set containing the vulnerability id
223      * @throws SQLException thrown if there is an error updating or inserting
224      * the vulnerability
225      */
226     public static ResultSet updateVulnerability(final Connection conn, String cve,
227             String description, String v2Severity, Float v2ExploitabilityScore,
228             Float v2ImpactScore, Boolean v2AcInsufInfo, Boolean v2ObtainAllPrivilege,
229             Boolean v2ObtainUserPrivilege, Boolean v2ObtainOtherPrivilege, Boolean v2UserInteractionRequired,
230             Float v2Score, String v2AccessVector, String v2AccessComplexity,
231             String v2Authentication, String v2ConfidentialityImpact, String v2IntegrityImpact,
232             String v2AvailabilityImpact, String v2Version, Float v3ExploitabilityScore,
233             Float v3ImpactScore, String v3AttackVector, String v3AttackComplexity,
234             String v3PrivilegesRequired, String v3UserInteraction, String v3Scope,
235             String v3ConfidentialityImpact, String v3IntegrityImpact, String v3AvailabilityImpact,
236             Float v3BaseScore, String v3BaseSeverity, String v3Version, String v4version, 
237             String v4attackVector, String v4attackComplexity, String v4attackRequirements, 
238             String v4privilegesRequired, String v4userInteraction, String v4vulnConfidentialityImpact, 
239             String v4vulnIntegrityImpact, String v4vulnAvailabilityImpact, String v4subConfidentialityImpact, 
240             String v4subIntegrityImpact, String v4subAvailabilityImpact, String v4exploitMaturity,
241             String v4confidentialityRequirement, String v4integrityRequirement, String v4availabilityRequirement,
242             String v4modifiedAttackVector, String v4modifiedAttackComplexity, String v4modifiedAttackRequirements,
243             String v4modifiedPrivilegesRequired, String v4modifiedUserInteraction, String v4modifiedVulnConfidentialityImpact,
244             String v4modifiedVulnIntegrityImpact, String v4modifiedVulnAvailabilityImpact, String v4modifiedSubConfidentialityImpact,
245             String v4modifiedSubIntegrityImpact, String v4modifiedSubAvailabilityImpact, String v4safety,
246             String v4automatable, String v4recovery, String v4valueDensity, String v4vulnerabilityResponseEffort,
247             String v4providerUrgency, Float v4baseScore, String v4baseSeverity, Float v4threatScore,
248             String v4threatSeverity, Float v4environmentalScore, String v4environmentalSeverity, 
249             String v4source, String v4type) throws SQLException {
250 
251         final SimpleResultSet ret = new SimpleResultSet();
252         ret.addColumn("id", Types.INTEGER, 10, 0);
253         final String url = conn.getMetaData().getURL();
254         if ("jdbc:columnlist:connection".equals(url)) {
255             // Virtual Table Functions get called multiple times by H2
256             // JDBC URL jdbc:columnlist:connection indicates that H2 only wants to discover
257             // the metadata (list of result columns) of the result and is not interested in the actual
258             // execution of the function, so we should exit early with an empty resultset.
259             return ret;
260         }
261 
262         int vulnerabilityId = 0;
263         try (PreparedStatement selectVulnerabilityId = conn.prepareStatement("SELECT id FROM VULNERABILITY CVE WHERE cve=?")) {
264             selectVulnerabilityId.setString(1, cve);
265             try (ResultSet rs = selectVulnerabilityId.executeQuery()) {
266                 if (rs.next()) {
267                     vulnerabilityId = rs.getInt(1);
268                 }
269             }
270         }
271         PreparedStatement merge = null;
272         try {
273             if (vulnerabilityId > 0) {
274                 //do deletes and updates
275                 try (PreparedStatement refs = conn.prepareStatement("DELETE FROM reference WHERE cveid = ?")) {
276                     refs.setInt(1, vulnerabilityId);
277                     refs.executeUpdate();
278                 }
279                 try (PreparedStatement software = conn.prepareStatement("DELETE FROM software WHERE cveid = ?")) {
280                     software.setInt(1, vulnerabilityId);
281                     software.executeUpdate();
282                 }
283                 try (PreparedStatement cwe = conn.prepareStatement("DELETE FROM cweEntry WHERE cveid = ?")) {
284                     cwe.setInt(1, vulnerabilityId);
285                     cwe.executeUpdate();
286                 }
287                 merge = conn.prepareStatement("UPDATE VULNERABILITY SET description=?, "
288                         + "v2Severity=?, v2ExploitabilityScore=?, "
289                         + "v2ImpactScore=?, v2AcInsufInfo=?, v2ObtainAllPrivilege=?, "
290                         + "v2ObtainUserPrivilege=?, v2ObtainOtherPrivilege=?, v2UserInteractionRequired=?, "
291                         + "v2Score=?, v2AccessVector=?, v2AccessComplexity=?, "
292                         + "v2Authentication=?, v2ConfidentialityImpact=?, v2IntegrityImpact=?, "
293                         + "v2AvailabilityImpact=?, v2Version=?, v3ExploitabilityScore=?, "
294                         + "v3ImpactScore=?, v3AttackVector=?, v3AttackComplexity=?, "
295                         + "v3PrivilegesRequired=?, v3UserInteraction=?, v3Scope=?, "
296                         + "v3ConfidentialityImpact=?, v3IntegrityImpact=?, v3AvailabilityImpact=?, "
297                         + "v3BaseScore=?, v3BaseSeverity=?, v3Version=?, v4version=?, v4attackVector=?, "
298                         + "v4attackComplexity=?, v4attackRequirements=?, v4privilegesRequired=?, "
299                         + "v4userInteraction=?, v4vulnConfidentialityImpact=?, v4vulnIntegrityImpact=?, "
300                         + "v4vulnAvailabilityImpact=?, v4subConfidentialityImpact=?, v4subIntegrityImpact=?, "
301                         + "v4subAvailabilityImpact=?, v4exploitMaturity=?, "
302                         + "v4confidentialityRequirement=?, v4integrityRequirement=?, "
303                         + "v4availabilityRequirement=?, v4modifiedAttackVector=?, "
304                         + "v4modifiedAttackComplexity=?, v4modifiedAttackRequirements=?, "
305                         + "v4modifiedPrivilegesRequired=?, v4modifiedUserInteraction=?, "
306                         + "v4modifiedVulnConfidentialityImpact=?, v4modifiedVulnIntegrityImpact=?, "
307                         + "v4modifiedVulnAvailabilityImpact=?, v4modifiedSubConfidentialityImpact=?, "
308                         + "v4modifiedSubIntegrityImpact=?, v4modifiedSubAvailabilityImpact=?, "
309                         + "v4safety=?, v4automatable=?, v4recovery=?, v4valueDensity=?, "
310                         + "v4vulnerabilityResponseEffort=?, v4providerUrgency=?, v4baseScore=?, "
311                         + "v4baseSeverity=?, v4threatScore=?, v4threatSeverity=?, v4environmentalScore=?, "
312                         + "v4environmentalSeverity=?, v4source=?, v4type=?"
313                         + "WHERE id=?");
314             } else {
315                 //just do insert
316                 final String[] returnedColumns = {"id"};
317                 merge = conn.prepareStatement("INSERT INTO VULNERABILITY (description, "
318                         + "v2Severity, v2ExploitabilityScore, "
319                         + "v2ImpactScore, v2AcInsufInfo, v2ObtainAllPrivilege, "
320                         + "v2ObtainUserPrivilege, v2ObtainOtherPrivilege, v2UserInteractionRequired, "
321                         + "v2Score, v2AccessVector, v2AccessComplexity, "
322                         + "v2Authentication, v2ConfidentialityImpact, v2IntegrityImpact, "
323                         + "v2AvailabilityImpact, v2Version, v3ExploitabilityScore, "
324                         + "v3ImpactScore, v3AttackVector, v3AttackComplexity, "
325                         + "v3PrivilegesRequired, v3UserInteraction, v3Scope, "
326                         + "v3ConfidentialityImpact, v3IntegrityImpact, v3AvailabilityImpact, "
327                         + "v3BaseScore, v3BaseSeverity, v3Version, v4version, v4attackVector, "
328                         + "v4attackComplexity, v4attackRequirements, v4privilegesRequired, "
329                         + "v4userInteraction, v4vulnConfidentialityImpact, v4vulnIntegrityImpact, "
330                         + "v4vulnAvailabilityImpact, v4subConfidentialityImpact, v4subIntegrityImpact, "
331                         + "v4subAvailabilityImpact, v4exploitMaturity,v4confidentialityRequirement, "
332                         + "v4integrityRequirement, v4availabilityRequirement,v4modifiedAttackVector, "
333                         + "v4modifiedAttackComplexity, v4modifiedAttackRequirements,v4modifiedPrivilegesRequired, "
334                         + "v4modifiedUserInteraction, v4modifiedVulnConfidentialityImpact,v4modifiedVulnIntegrityImpact, "
335                         + "v4modifiedVulnAvailabilityImpact, v4modifiedSubConfidentialityImpact,v4modifiedSubIntegrityImpact, "
336                         + "v4modifiedSubAvailabilityImpact, v4safety, v4automatable, v4recovery, v4valueDensity, "
337                         + "v4vulnerabilityResponseEffort, v4providerUrgency, v4baseScore, v4baseSeverity, "
338                         + "v4threatScore,v4threatSeverity, v4environmentalScore, v4environmentalSeverity, "
339                         + "v4source, v4type, cve) VALUES (?, ?, ?, ?, ?, ?, "
340                         + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
341                         + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
342                         + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
343                         returnedColumns);
344             }
345 
346             merge.setString(1, description);
347 
348             setStringOrNull(merge, 2, v2Severity);
349             setFloatOrNull(merge, 3, v2ExploitabilityScore);
350             setFloatOrNull(merge, 4, v2ImpactScore);
351             setBooleanOrNull(merge, 5, v2AcInsufInfo);
352             setBooleanOrNull(merge, 6, v2ObtainAllPrivilege);
353             setBooleanOrNull(merge, 7, v2ObtainUserPrivilege);
354             setBooleanOrNull(merge, 8, v2ObtainOtherPrivilege);
355             setBooleanOrNull(merge, 9, v2UserInteractionRequired);
356             setFloatOrNull(merge, 10, v2Score);
357             setStringOrNull(merge, 11, v2AccessVector);
358             setStringOrNull(merge, 12, v2AccessComplexity);
359             setStringOrNull(merge, 13, v2Authentication);
360             setStringOrNull(merge, 14, v2ConfidentialityImpact);
361             setStringOrNull(merge, 15, v2IntegrityImpact);
362             setStringOrNull(merge, 16, v2AvailabilityImpact);
363             setStringOrNull(merge, 17, v2Version);
364             setFloatOrNull(merge, 18, v3ExploitabilityScore);
365             setFloatOrNull(merge, 19, v3ImpactScore);
366             setStringOrNull(merge, 20, v3AttackVector);
367             setStringOrNull(merge, 21, v3AttackComplexity);
368             setStringOrNull(merge, 22, v3PrivilegesRequired);
369             setStringOrNull(merge, 23, v3UserInteraction);
370             setStringOrNull(merge, 24, v3Scope);
371             setStringOrNull(merge, 25, v3ConfidentialityImpact);
372             setStringOrNull(merge, 26, v3IntegrityImpact);
373             setStringOrNull(merge, 27, v3AvailabilityImpact);
374             setFloatOrNull(merge, 28, v3BaseScore);
375             setStringOrNull(merge, 29, v3BaseSeverity);
376             setStringOrNull(merge, 30, v3Version);
377             
378             
379 
380             setStringOrNull(merge, 31, v4version);
381             setStringOrNull(merge, 32, v4attackVector);
382             setStringOrNull(merge, 33, v4attackComplexity);
383             setStringOrNull(merge, 34, v4attackRequirements);
384             setStringOrNull(merge, 35, v4privilegesRequired);
385             setStringOrNull(merge, 36, v4userInteraction);
386             setStringOrNull(merge, 37, v4vulnConfidentialityImpact);
387             setStringOrNull(merge, 38, v4vulnIntegrityImpact);
388             setStringOrNull(merge, 39, v4vulnAvailabilityImpact);
389             setStringOrNull(merge, 40, v4subConfidentialityImpact);
390             setStringOrNull(merge, 41, v4subIntegrityImpact);
391             setStringOrNull(merge, 42, v4subAvailabilityImpact);
392             setStringOrNull(merge, 43, v4exploitMaturity);
393             setStringOrNull(merge, 44, v4confidentialityRequirement);
394             setStringOrNull(merge, 45, v4integrityRequirement);
395             setStringOrNull(merge, 46, v4availabilityRequirement);
396             setStringOrNull(merge, 47, v4modifiedAttackVector);
397             setStringOrNull(merge, 48, v4modifiedAttackComplexity);
398             setStringOrNull(merge, 49, v4modifiedAttackRequirements);
399             setStringOrNull(merge, 50, v4modifiedPrivilegesRequired);
400             setStringOrNull(merge, 51, v4modifiedUserInteraction);
401             setStringOrNull(merge, 52, v4modifiedVulnConfidentialityImpact);
402             setStringOrNull(merge, 53, v4modifiedVulnIntegrityImpact);
403             setStringOrNull(merge, 54, v4modifiedVulnAvailabilityImpact);
404             setStringOrNull(merge, 55, v4modifiedSubConfidentialityImpact);
405             setStringOrNull(merge, 56, v4modifiedSubIntegrityImpact);
406             setStringOrNull(merge, 57, v4modifiedSubAvailabilityImpact);
407             setStringOrNull(merge, 58, v4safety);
408             setStringOrNull(merge, 59, v4automatable);
409             setStringOrNull(merge, 60, v4recovery);
410             setStringOrNull(merge, 61, v4valueDensity);
411             setStringOrNull(merge, 62, v4vulnerabilityResponseEffort);
412             setStringOrNull(merge, 63, v4providerUrgency);
413             setFloatOrNull(merge, 64, v4baseScore);
414             setStringOrNull(merge, 65, v4baseSeverity);
415             setFloatOrNull(merge, 66, v4threatScore);
416             setStringOrNull(merge, 67, v4threatSeverity);
417             setFloatOrNull(merge, 68, v4environmentalScore);
418             setStringOrNull(merge, 69, v4environmentalSeverity);
419             setStringOrNull(merge, 70, v4source);
420             setStringOrNull(merge, 71, v4type);
421 
422             //cve must be the last entry
423             if (vulnerabilityId == 0) {
424                 merge.setString(72, cve);
425             } else {
426                 merge.setInt(72, vulnerabilityId);
427             }
428             
429             final int count = merge.executeUpdate();
430             if (vulnerabilityId == 0) {
431                 try (ResultSet rs = merge.getGeneratedKeys()) {
432                     if (rs.next()) {
433                         vulnerabilityId = rs.getInt(1);
434                     }
435                 }
436             }
437         } finally {
438             if (merge != null) {
439                 merge.close();
440             }
441         }
442         ret.addRow(vulnerabilityId);
443         return ret;
444     }
445     //CSON: ParameterNumber
446 
447     //CSOFF: ParameterNumber
448     /**
449      * Update or insert a known exploited vulnerability.
450      *
451      * @param conn the connection
452      * @param cveId the id
453      * @param vendorProject the vendor/project
454      * @param product the product
455      * @param vulnerabilityName the vulnerability name
456      * @param dateAdded the date added
457      * @param shortDescription the short description
458      * @param requiredAction the action required
459      * @param dueDate the due date
460      * @param notes notes
461      * @throws SQLException
462      */
463     public static void mergeKnownExploited(final Connection conn, String cveId,
464             String vendorProject, String product, String vulnerabilityName,
465             String dateAdded, String shortDescription, String requiredAction,
466             String dueDate, String notes) throws SQLException {
467 
468         String id = "";
469         try (PreparedStatement selectVulnerabilityId = conn.prepareStatement("SELECT cveID FROM knownExploited cveID WHERE cveID=?")) {
470             selectVulnerabilityId.setString(1, cveId);
471             try (ResultSet rs = selectVulnerabilityId.executeQuery()) {
472                 if (rs.next()) {
473                     id = rs.getString(1);
474                 }
475             }
476         }
477         PreparedStatement merge = null;
478         try {
479             if (Strings.isNullOrEmpty(id)) {
480                 merge = conn.prepareStatement("INSERT INTO knownExploited ("
481                         + "vendorProject, product, vulnerabilityName, "
482                         + "dateAdded, shortDescription, requiredAction, "
483                         + "dueDate, notes, cveID) "
484                         + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
485             } else {
486                 merge = conn.prepareStatement("UPDATE knownExploited SET "
487                         + "vendorProject=?, product=?, vulnerabilityName=?, "
488                         + "dateAdded=?, shortDescription=?, requiredAction=?, "
489                         + "dueDate=?, notes=? WHERE cveID=?");
490             }
491 
492             setStringOrNull(merge, 1, vendorProject);
493             setStringOrNull(merge, 2, product);
494             setStringOrNull(merge, 3, vulnerabilityName);
495             setStringOrNull(merge, 4, dateAdded);
496             setStringOrNull(merge, 5, shortDescription);
497             setStringOrNull(merge, 6, requiredAction);
498             setStringOrNull(merge, 7, dueDate);
499             setStringOrNull(merge, 8, notes);
500             setStringOrNull(merge, 9, cveId);
501             merge.execute();
502         } finally {
503             if (merge != null) {
504                 merge.close();
505             }
506         }
507     }
508     //CSON: ParameterNumber
509 
510     /**
511      * Sets a parameter value on a prepared statement with null checks.
512      *
513      * @param ps the prepared statement
514      * @param i the parameter index
515      * @param value the value
516      * @throws SQLException thrown if there is an error setting the parameter
517      */
518     private static void setStringOrNull(PreparedStatement ps, int i, String value) throws SQLException {
519         if (value == null) {
520             ps.setNull(i, java.sql.Types.NULL);
521         } else {
522             ps.setString(i, value);
523         }
524     }
525 
526     /**
527      * Sets a parameter value on a prepared statement with null checks.
528      *
529      * @param ps the prepared statement
530      * @param i the parameter index
531      * @param value the value
532      * @throws SQLException thrown if there is an error setting the parameter
533      */
534     private static void setFloatOrNull(PreparedStatement ps, int i, Float value) throws SQLException {
535         if (value == null) {
536             ps.setNull(i, java.sql.Types.NULL);
537         } else {
538             ps.setFloat(i, value);
539         }
540     }
541 
542     /**
543      * Sets a parameter value on a prepared statement with null checks.
544      *
545      * @param ps the prepared statement
546      * @param i the parameter index
547      * @param value the value
548      * @throws SQLException thrown if there is an error setting the parameter
549      */
550     private static void setBooleanOrNull(PreparedStatement ps, int i, Boolean value) throws SQLException {
551         if (value == null) {
552             ps.setNull(i, java.sql.Types.NULL);
553         } else {
554             ps.setBoolean(i, value);
555         }
556     }
557 }