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             setStringOrNull(merge, 31, v4version);
379             setStringOrNull(merge, 32, v4attackVector);
380             setStringOrNull(merge, 33, v4attackComplexity);
381             setStringOrNull(merge, 34, v4attackRequirements);
382             setStringOrNull(merge, 35, v4privilegesRequired);
383             setStringOrNull(merge, 36, v4userInteraction);
384             setStringOrNull(merge, 37, v4vulnConfidentialityImpact);
385             setStringOrNull(merge, 38, v4vulnIntegrityImpact);
386             setStringOrNull(merge, 39, v4vulnAvailabilityImpact);
387             setStringOrNull(merge, 40, v4subConfidentialityImpact);
388             setStringOrNull(merge, 41, v4subIntegrityImpact);
389             setStringOrNull(merge, 42, v4subAvailabilityImpact);
390             setStringOrNull(merge, 43, v4exploitMaturity);
391             setStringOrNull(merge, 44, v4confidentialityRequirement);
392             setStringOrNull(merge, 45, v4integrityRequirement);
393             setStringOrNull(merge, 46, v4availabilityRequirement);
394             setStringOrNull(merge, 47, v4modifiedAttackVector);
395             setStringOrNull(merge, 48, v4modifiedAttackComplexity);
396             setStringOrNull(merge, 49, v4modifiedAttackRequirements);
397             setStringOrNull(merge, 50, v4modifiedPrivilegesRequired);
398             setStringOrNull(merge, 51, v4modifiedUserInteraction);
399             setStringOrNull(merge, 52, v4modifiedVulnConfidentialityImpact);
400             setStringOrNull(merge, 53, v4modifiedVulnIntegrityImpact);
401             setStringOrNull(merge, 54, v4modifiedVulnAvailabilityImpact);
402             setStringOrNull(merge, 55, v4modifiedSubConfidentialityImpact);
403             setStringOrNull(merge, 56, v4modifiedSubIntegrityImpact);
404             setStringOrNull(merge, 57, v4modifiedSubAvailabilityImpact);
405             setStringOrNull(merge, 58, v4safety);
406             setStringOrNull(merge, 59, v4automatable);
407             setStringOrNull(merge, 60, v4recovery);
408             setStringOrNull(merge, 61, v4valueDensity);
409             setStringOrNull(merge, 62, v4vulnerabilityResponseEffort);
410             setStringOrNull(merge, 63, v4providerUrgency);
411             setFloatOrNull(merge, 64, v4baseScore);
412             setStringOrNull(merge, 65, v4baseSeverity);
413             setFloatOrNull(merge, 66, v4threatScore);
414             setStringOrNull(merge, 67, v4threatSeverity);
415             setFloatOrNull(merge, 68, v4environmentalScore);
416             setStringOrNull(merge, 69, v4environmentalSeverity);
417             setStringOrNull(merge, 70, v4source);
418             setStringOrNull(merge, 71, v4type);
419 
420             //cve must be the last entry
421             if (vulnerabilityId == 0) {
422                 merge.setString(72, cve);
423             } else {
424                 merge.setInt(72, vulnerabilityId);
425             }
426 
427             final int count = merge.executeUpdate();
428             if (vulnerabilityId == 0) {
429                 try (ResultSet rs = merge.getGeneratedKeys()) {
430                     if (rs.next()) {
431                         vulnerabilityId = rs.getInt(1);
432                     }
433                 }
434             }
435         } finally {
436             if (merge != null) {
437                 merge.close();
438             }
439         }
440         ret.addRow(vulnerabilityId);
441         return ret;
442     }
443     //CSON: ParameterNumber
444 
445     //CSOFF: ParameterNumber
446     /**
447      * Update or insert a known exploited vulnerability.
448      *
449      * @param conn the connection
450      * @param cveId the id
451      * @param vendorProject the vendor/project
452      * @param product the product
453      * @param vulnerabilityName the vulnerability name
454      * @param dateAdded the date added
455      * @param shortDescription the short description
456      * @param requiredAction the action required
457      * @param dueDate the due date
458      * @param notes notes
459      * @throws SQLException thrown if there is a database error merging the
460      * Known Exploited information to the database
461      */
462     public static void mergeKnownExploited(final Connection conn, String cveId,
463             String vendorProject, String product, String vulnerabilityName,
464             String dateAdded, String shortDescription, String requiredAction,
465             String dueDate, String notes) throws SQLException {
466 
467         String id = "";
468         try (PreparedStatement selectVulnerabilityId = conn.prepareStatement("SELECT cveID FROM knownExploited cveID WHERE cveID=?")) {
469             selectVulnerabilityId.setString(1, cveId);
470             try (ResultSet rs = selectVulnerabilityId.executeQuery()) {
471                 if (rs.next()) {
472                     id = rs.getString(1);
473                 }
474             }
475         }
476         PreparedStatement merge = null;
477         try {
478             if (Strings.isNullOrEmpty(id)) {
479                 merge = conn.prepareStatement("INSERT INTO knownExploited ("
480                         + "vendorProject, product, vulnerabilityName, "
481                         + "dateAdded, shortDescription, requiredAction, "
482                         + "dueDate, notes, cveID) "
483                         + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
484             } else {
485                 merge = conn.prepareStatement("UPDATE knownExploited SET "
486                         + "vendorProject=?, product=?, vulnerabilityName=?, "
487                         + "dateAdded=?, shortDescription=?, requiredAction=?, "
488                         + "dueDate=?, notes=? WHERE cveID=?");
489             }
490 
491             setStringOrNull(merge, 1, vendorProject);
492             setStringOrNull(merge, 2, product);
493             setStringOrNull(merge, 3, vulnerabilityName);
494             setStringOrNull(merge, 4, dateAdded);
495             setStringOrNull(merge, 5, shortDescription);
496             setStringOrNull(merge, 6, requiredAction);
497             setStringOrNull(merge, 7, dueDate);
498             setStringOrNull(merge, 8, notes);
499             setStringOrNull(merge, 9, cveId);
500             merge.execute();
501         } finally {
502             if (merge != null) {
503                 merge.close();
504             }
505         }
506     }
507     //CSON: ParameterNumber
508 
509     /**
510      * Sets a parameter value on a prepared statement with null checks.
511      *
512      * @param ps the prepared statement
513      * @param i the parameter index
514      * @param value the value
515      * @throws SQLException thrown if there is an error setting the parameter
516      */
517     private static void setStringOrNull(PreparedStatement ps, int i, String value) throws SQLException {
518         if (value == null) {
519             ps.setNull(i, java.sql.Types.NULL);
520         } else {
521             ps.setString(i, value);
522         }
523     }
524 
525     /**
526      * Sets a parameter value on a prepared statement with null checks.
527      *
528      * @param ps the prepared statement
529      * @param i the parameter index
530      * @param value the value
531      * @throws SQLException thrown if there is an error setting the parameter
532      */
533     private static void setFloatOrNull(PreparedStatement ps, int i, Float value) throws SQLException {
534         if (value == null) {
535             ps.setNull(i, java.sql.Types.NULL);
536         } else {
537             ps.setFloat(i, value);
538         }
539     }
540 
541     /**
542      * Sets a parameter value on a prepared statement with null checks.
543      *
544      * @param ps the prepared statement
545      * @param i the parameter index
546      * @param value the value
547      * @throws SQLException thrown if there is an error setting the parameter
548      */
549     private static void setBooleanOrNull(PreparedStatement ps, int i, Boolean value) throws SQLException {
550         if (value == null) {
551             ps.setNull(i, java.sql.Types.NULL);
552         } else {
553             ps.setBoolean(i, value);
554         }
555     }
556 }