1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.data.nvdcve;
19
20 import java.io.IOException;
21 import java.io.UnsupportedEncodingException;
22 import java.sql.Connection;
23 import java.sql.PreparedStatement;
24 import java.sql.ResultSet;
25 import java.sql.SQLException;
26 import java.sql.Statement;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Locale;
32 import java.util.Map;
33 import java.util.Map.Entry;
34 import java.util.MissingResourceException;
35 import java.util.Properties;
36 import java.util.ResourceBundle;
37 import java.util.Set;
38 import org.owasp.dependencycheck.data.cwe.CweDB;
39 import org.owasp.dependencycheck.dependency.Reference;
40 import org.owasp.dependencycheck.dependency.Vulnerability;
41 import org.owasp.dependencycheck.dependency.VulnerableSoftware;
42 import org.owasp.dependencycheck.utils.DBUtils;
43 import org.owasp.dependencycheck.utils.DependencyVersion;
44 import org.owasp.dependencycheck.utils.DependencyVersionUtil;
45 import org.owasp.dependencycheck.utils.Pair;
46 import org.owasp.dependencycheck.utils.Settings;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50
51
52
53
54
55 public class CveDB {
56
57
58
59
60 private static final Logger LOGGER = LoggerFactory.getLogger(CveDB.class);
61
62
63
64 private Connection conn;
65
66
67
68 private ResourceBundle statementBundle = null;
69
70
71
72
73
74
75 private boolean batchSupported;
76
77
78
79
80
81
82
83
84 public CveDB() throws DatabaseException {
85 super();
86 try {
87 open();
88 try {
89 final String databaseProductName = conn.getMetaData().getDatabaseProductName();
90 LOGGER.debug("Database dialect: {}", databaseProductName);
91 final Locale dbDialect = new Locale(databaseProductName);
92 statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect);
93 if ("mysql".equalsIgnoreCase(databaseProductName)) {
94 batchSupported = false;
95 }
96 } catch (SQLException se) {
97 LOGGER.warn("Problem loading database specific dialect!", se);
98 statementBundle = ResourceBundle.getBundle("data/dbStatements");
99 }
100 databaseProperties = new DatabaseProperties(this);
101 } catch (DatabaseException ex) {
102 throw ex;
103 }
104 }
105
106
107
108
109
110
111 protected Connection getConnection() {
112 return conn;
113 }
114
115
116
117
118
119
120
121
122 public final synchronized void open() throws DatabaseException {
123 if (!isOpen()) {
124 conn = ConnectionFactory.getConnection();
125 }
126 }
127
128
129
130
131
132 public synchronized void close() {
133 if (conn != null) {
134 try {
135 conn.close();
136 } catch (SQLException ex) {
137 LOGGER.error("There was an error attempting to close the CveDB, see the log for more details.");
138 LOGGER.debug("", ex);
139 } catch (Throwable ex) {
140 LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details.");
141 LOGGER.debug("", ex);
142 }
143 conn = null;
144 }
145 }
146
147
148
149
150
151
152 public synchronized boolean isOpen() {
153 return conn != null;
154 }
155
156
157
158
159
160
161 public synchronized void commit() throws SQLException {
162
163
164
165
166 }
167
168
169
170
171
172
173 @Override
174 @SuppressWarnings("FinalizeDeclaration")
175 protected void finalize() throws Throwable {
176 LOGGER.debug("Entering finalize");
177 close();
178 super.finalize();
179 }
180
181
182
183
184 private DatabaseProperties databaseProperties;
185
186
187
188
189
190
191 public DatabaseProperties getDatabaseProperties() {
192 return databaseProperties;
193 }
194
195
196
197
198
199
200
201
202
203
204
205 public synchronized Set<VulnerableSoftware> getCPEs(String vendor, String product) {
206 final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>();
207 ResultSet rs = null;
208 PreparedStatement ps = null;
209 try {
210 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ENTRIES"));
211 ps.setString(1, vendor);
212 ps.setString(2, product);
213 rs = ps.executeQuery();
214
215 while (rs.next()) {
216 final VulnerableSoftware vs = new VulnerableSoftware();
217 vs.setCpe(rs.getString(1));
218 cpe.add(vs);
219 }
220 } catch (SQLException ex) {
221 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
222 LOGGER.debug("", ex);
223 } finally {
224 DBUtils.closeResultSet(rs);
225 DBUtils.closeStatement(ps);
226 }
227 return cpe;
228 }
229
230
231
232
233
234
235
236
237 public synchronized Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
238 final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>();
239 ResultSet rs = null;
240 PreparedStatement ps = null;
241 try {
242 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_VENDOR_PRODUCT_LIST"));
243 rs = ps.executeQuery();
244 while (rs.next()) {
245 data.add(new Pair<String, String>(rs.getString(1), rs.getString(2)));
246 }
247 } catch (SQLException ex) {
248 final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
249 throw new DatabaseException(msg, ex);
250 } finally {
251 DBUtils.closeResultSet(rs);
252 DBUtils.closeStatement(ps);
253 }
254 return data;
255 }
256
257
258
259
260
261
262 synchronized Properties getProperties() {
263 final Properties prop = new Properties();
264 PreparedStatement ps = null;
265 ResultSet rs = null;
266 try {
267 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_PROPERTIES"));
268 rs = ps.executeQuery();
269 while (rs.next()) {
270 prop.setProperty(rs.getString(1), rs.getString(2));
271 }
272 } catch (SQLException ex) {
273 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
274 LOGGER.debug("", ex);
275 } finally {
276 DBUtils.closeStatement(ps);
277 DBUtils.closeResultSet(rs);
278 }
279 return prop;
280 }
281
282
283
284
285
286
287
288 synchronized void saveProperty(String key, String value) {
289 try {
290 try {
291 final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY"));
292 try {
293 mergeProperty.setString(1, key);
294 mergeProperty.setString(2, value);
295 mergeProperty.executeUpdate();
296 } finally {
297 DBUtils.closeStatement(mergeProperty);
298 }
299 } catch (MissingResourceException mre) {
300
301 PreparedStatement updateProperty = null;
302 PreparedStatement insertProperty = null;
303 try {
304 updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY"));
305 updateProperty.setString(1, value);
306 updateProperty.setString(2, key);
307 if (updateProperty.executeUpdate() == 0) {
308 insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY"));
309 insertProperty.setString(1, key);
310 insertProperty.setString(2, value);
311 insertProperty.executeUpdate();
312 }
313 } finally {
314 DBUtils.closeStatement(updateProperty);
315 DBUtils.closeStatement(insertProperty);
316 }
317 }
318 } catch (SQLException ex) {
319 LOGGER.warn("Unable to save property '{}' with a value of '{}' to the database", key, value);
320 LOGGER.debug("", ex);
321 }
322 }
323
324
325
326
327
328
329
330
331 public synchronized List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException {
332 final VulnerableSoftware cpe = new VulnerableSoftware();
333 try {
334 cpe.parseName(cpeStr);
335 } catch (UnsupportedEncodingException ex) {
336 LOGGER.trace("", ex);
337 }
338 final DependencyVersion detectedVersion = parseDependencyVersion(cpe);
339 final List<Vulnerability> vulnerabilities = new ArrayList<Vulnerability>();
340
341 PreparedStatement ps = null;
342 ResultSet rs = null;
343 try {
344 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CVE_FROM_SOFTWARE"));
345 ps.setString(1, cpe.getVendor());
346 ps.setString(2, cpe.getProduct());
347 rs = ps.executeQuery();
348 String currentCVE = "";
349
350 final Map<String, Boolean> vulnSoftware = new HashMap<String, Boolean>();
351 while (rs.next()) {
352 final String cveId = rs.getString(1);
353 if (!currentCVE.equals(cveId)) {
354 final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion);
355 if (matchedCPE != null) {
356 final Vulnerability v = getVulnerability(currentCVE);
357 v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null);
358 vulnerabilities.add(v);
359 }
360 vulnSoftware.clear();
361 currentCVE = cveId;
362 }
363
364 final String cpeId = rs.getString(2);
365 final String previous = rs.getString(3);
366 final Boolean p = previous != null && !previous.isEmpty();
367 vulnSoftware.put(cpeId, p);
368 }
369
370 final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion);
371 if (matchedCPE != null) {
372 final Vulnerability v = getVulnerability(currentCVE);
373 v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null);
374 vulnerabilities.add(v);
375 }
376 } catch (SQLException ex) {
377 throw new DatabaseException("Exception retrieving vulnerability for " + cpeStr, ex);
378 } finally {
379 DBUtils.closeResultSet(rs);
380 DBUtils.closeStatement(ps);
381 }
382 return vulnerabilities;
383 }
384
385
386
387
388
389
390
391
392 public synchronized Vulnerability getVulnerability(String cve) throws DatabaseException {
393 PreparedStatement psV = null;
394 PreparedStatement psR = null;
395 PreparedStatement psS = null;
396 ResultSet rsV = null;
397 ResultSet rsR = null;
398 ResultSet rsS = null;
399 Vulnerability vuln = null;
400
401 try {
402 psV = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY"));
403 psV.setString(1, cve);
404 rsV = psV.executeQuery();
405 if (rsV.next()) {
406 vuln = new Vulnerability();
407 vuln.setName(cve);
408 vuln.setDescription(rsV.getString(2));
409 String cwe = rsV.getString(3);
410 if (cwe != null) {
411 final String name = CweDB.getCweName(cwe);
412 if (name != null) {
413 cwe += ' ' + name;
414 }
415 }
416 final int cveId = rsV.getInt(1);
417 vuln.setCwe(cwe);
418 vuln.setCvssScore(rsV.getFloat(4));
419 vuln.setCvssAccessVector(rsV.getString(5));
420 vuln.setCvssAccessComplexity(rsV.getString(6));
421 vuln.setCvssAuthentication(rsV.getString(7));
422 vuln.setCvssConfidentialityImpact(rsV.getString(8));
423 vuln.setCvssIntegrityImpact(rsV.getString(9));
424 vuln.setCvssAvailabilityImpact(rsV.getString(10));
425
426 psR = getConnection().prepareStatement(statementBundle.getString("SELECT_REFERENCES"));
427 psR.setInt(1, cveId);
428 rsR = psR.executeQuery();
429 while (rsR.next()) {
430 vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3));
431 }
432 psS = getConnection().prepareStatement(statementBundle.getString("SELECT_SOFTWARE"));
433 psS.setInt(1, cveId);
434 rsS = psS.executeQuery();
435 while (rsS.next()) {
436 final String cpe = rsS.getString(1);
437 final String prevVersion = rsS.getString(2);
438 if (prevVersion == null) {
439 vuln.addVulnerableSoftware(cpe);
440 } else {
441 vuln.addVulnerableSoftware(cpe, prevVersion);
442 }
443 }
444 }
445 } catch (SQLException ex) {
446 throw new DatabaseException("Error retrieving " + cve, ex);
447 } finally {
448 DBUtils.closeResultSet(rsV);
449 DBUtils.closeResultSet(rsR);
450 DBUtils.closeResultSet(rsS);
451 DBUtils.closeStatement(psV);
452 DBUtils.closeStatement(psR);
453 DBUtils.closeStatement(psS);
454 }
455 return vuln;
456 }
457
458
459
460
461
462
463
464
465 public synchronized void updateVulnerability(Vulnerability vuln) throws DatabaseException {
466 PreparedStatement selectVulnerabilityId = null;
467 PreparedStatement deleteVulnerability = null;
468 PreparedStatement deleteReferences = null;
469 PreparedStatement deleteSoftware = null;
470 PreparedStatement updateVulnerability = null;
471 PreparedStatement insertVulnerability = null;
472 PreparedStatement insertReference = null;
473 PreparedStatement selectCpeId = null;
474 PreparedStatement insertCpe = null;
475 PreparedStatement insertSoftware = null;
476
477 try {
478 selectVulnerabilityId = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY_ID"));
479 deleteVulnerability = getConnection().prepareStatement(statementBundle.getString("DELETE_VULNERABILITY"));
480 deleteReferences = getConnection().prepareStatement(statementBundle.getString("DELETE_REFERENCE"));
481 deleteSoftware = getConnection().prepareStatement(statementBundle.getString("DELETE_SOFTWARE"));
482 updateVulnerability = getConnection().prepareStatement(statementBundle.getString("UPDATE_VULNERABILITY"));
483 final String[] ids = {"id"};
484 insertVulnerability = getConnection().prepareStatement(statementBundle.getString("INSERT_VULNERABILITY"),
485
486 ids);
487 insertReference = getConnection().prepareStatement(statementBundle.getString("INSERT_REFERENCE"));
488 selectCpeId = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ID"));
489 insertCpe = getConnection().prepareStatement(statementBundle.getString("INSERT_CPE"),
490
491 ids);
492 insertSoftware = getConnection().prepareStatement(statementBundle.getString("INSERT_SOFTWARE"));
493 int vulnerabilityId = 0;
494 selectVulnerabilityId.setString(1, vuln.getName());
495 ResultSet rs = selectVulnerabilityId.executeQuery();
496 if (rs.next()) {
497 vulnerabilityId = rs.getInt(1);
498
499 deleteReferences.setInt(1, vulnerabilityId);
500 deleteReferences.execute();
501 deleteSoftware.setInt(1, vulnerabilityId);
502 deleteSoftware.execute();
503 }
504 DBUtils.closeResultSet(rs);
505 rs = null;
506
507 if (vulnerabilityId != 0) {
508 if (vuln.getDescription().contains("** REJECT **")) {
509 deleteVulnerability.setInt(1, vulnerabilityId);
510 deleteVulnerability.executeUpdate();
511 } else {
512 updateVulnerability.setString(1, vuln.getDescription());
513 updateVulnerability.setString(2, vuln.getCwe());
514 updateVulnerability.setFloat(3, vuln.getCvssScore());
515 updateVulnerability.setString(4, vuln.getCvssAccessVector());
516 updateVulnerability.setString(5, vuln.getCvssAccessComplexity());
517 updateVulnerability.setString(6, vuln.getCvssAuthentication());
518 updateVulnerability.setString(7, vuln.getCvssConfidentialityImpact());
519 updateVulnerability.setString(8, vuln.getCvssIntegrityImpact());
520 updateVulnerability.setString(9, vuln.getCvssAvailabilityImpact());
521 updateVulnerability.setInt(10, vulnerabilityId);
522 updateVulnerability.executeUpdate();
523 }
524 } else {
525 insertVulnerability.setString(1, vuln.getName());
526 insertVulnerability.setString(2, vuln.getDescription());
527 insertVulnerability.setString(3, vuln.getCwe());
528 insertVulnerability.setFloat(4, vuln.getCvssScore());
529 insertVulnerability.setString(5, vuln.getCvssAccessVector());
530 insertVulnerability.setString(6, vuln.getCvssAccessComplexity());
531 insertVulnerability.setString(7, vuln.getCvssAuthentication());
532 insertVulnerability.setString(8, vuln.getCvssConfidentialityImpact());
533 insertVulnerability.setString(9, vuln.getCvssIntegrityImpact());
534 insertVulnerability.setString(10, vuln.getCvssAvailabilityImpact());
535 insertVulnerability.execute();
536 try {
537 rs = insertVulnerability.getGeneratedKeys();
538 rs.next();
539 vulnerabilityId = rs.getInt(1);
540 } catch (SQLException ex) {
541 final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", vuln.getName());
542 throw new DatabaseException(msg, ex);
543 } finally {
544 DBUtils.closeResultSet(rs);
545 rs = null;
546 }
547 }
548
549 for (Reference r : vuln.getReferences()) {
550 insertReference.setInt(1, vulnerabilityId);
551 insertReference.setString(2, r.getName());
552 insertReference.setString(3, r.getUrl());
553 insertReference.setString(4, r.getSource());
554
555 if (batchSupported) {
556 insertReference.addBatch();
557 } else {
558 insertReference.execute();
559 }
560 }
561
562 if (batchSupported) {
563 insertReference.executeBatch();
564 }
565
566 for (VulnerableSoftware s : vuln.getVulnerableSoftware()) {
567 int cpeProductId = 0;
568 selectCpeId.setString(1, s.getName());
569 try {
570 rs = selectCpeId.executeQuery();
571 if (rs.next()) {
572 cpeProductId = rs.getInt(1);
573 }
574 } catch (SQLException ex) {
575 throw new DatabaseException("Unable to get primary key for new cpe: " + s.getName(), ex);
576 } finally {
577 DBUtils.closeResultSet(rs);
578 rs = null;
579 }
580
581 if (cpeProductId == 0) {
582 insertCpe.setString(1, s.getName());
583 insertCpe.setString(2, s.getVendor());
584 insertCpe.setString(3, s.getProduct());
585 insertCpe.executeUpdate();
586 cpeProductId = DBUtils.getGeneratedKey(insertCpe);
587 }
588 if (cpeProductId == 0) {
589 throw new DatabaseException("Unable to retrieve cpeProductId - no data returned");
590 }
591
592 insertSoftware.setInt(1, vulnerabilityId);
593 insertSoftware.setInt(2, cpeProductId);
594
595 if (s.getPreviousVersion() == null) {
596 insertSoftware.setNull(3, java.sql.Types.VARCHAR);
597 } else {
598 insertSoftware.setString(3, s.getPreviousVersion());
599 }
600 if (batchSupported) {
601 insertSoftware.addBatch();
602 } else {
603 try {
604 insertSoftware.execute();
605 } catch (SQLException ex) {
606 if (ex.getMessage().contains("Duplicate entry")) {
607 final String msg = String.format("Duplicate software key identified in '%s:%s'", vuln.getName(), s.getName());
608 LOGGER.debug(msg, ex);
609 } else {
610 throw ex;
611 }
612 }
613 }
614 }
615 if (batchSupported) {
616 insertSoftware.executeBatch();
617 }
618 } catch (SQLException ex) {
619 final String msg = String.format("Error updating '%s'", vuln.getName());
620 LOGGER.debug(msg, ex);
621 throw new DatabaseException(msg, ex);
622 } finally {
623 DBUtils.closeStatement(selectVulnerabilityId);
624 DBUtils.closeStatement(deleteReferences);
625 DBUtils.closeStatement(deleteSoftware);
626 DBUtils.closeStatement(updateVulnerability);
627 DBUtils.closeStatement(deleteVulnerability);
628 DBUtils.closeStatement(insertVulnerability);
629 DBUtils.closeStatement(insertReference);
630 DBUtils.closeStatement(selectCpeId);
631 DBUtils.closeStatement(insertCpe);
632 DBUtils.closeStatement(insertSoftware);
633 }
634 }
635
636
637
638
639
640
641 public synchronized boolean dataExists() {
642 Statement cs = null;
643 ResultSet rs = null;
644 try {
645 cs = conn.createStatement();
646 rs = cs.executeQuery("SELECT COUNT(*) records FROM cpeEntry");
647 if (rs.next()) {
648 if (rs.getInt(1) > 0) {
649 return true;
650 }
651 }
652 } catch (SQLException ex) {
653 String dd;
654 try {
655 dd = Settings.getDataDirectory().getAbsolutePath();
656 } catch (IOException ex1) {
657 dd = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
658 }
659 LOGGER.error("Unable to access the local database.\n\nEnsure that '{}' is a writable directory. "
660 + "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please "
661 + "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at "
662 + "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n",
663 dd, dd, Settings.getString(Settings.KEYS.APPLICATION_NAME));
664 LOGGER.debug("", ex);
665 } finally {
666 DBUtils.closeResultSet(rs);
667 DBUtils.closeStatement(cs);
668 }
669 return false;
670 }
671
672
673
674
675
676
677 public synchronized void cleanupDatabase() {
678 PreparedStatement ps = null;
679 try {
680 ps = getConnection().prepareStatement(statementBundle.getString("CLEANUP_ORPHANS"));
681 if (ps != null) {
682 ps.executeUpdate();
683 }
684 } catch (SQLException ex) {
685 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
686 LOGGER.debug("", ex);
687 } finally {
688 DBUtils.closeStatement(ps);
689 }
690 }
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706 Entry<String, Boolean> getMatchingSoftware(Map<String, Boolean> vulnerableSoftware, String vendor, String product,
707 DependencyVersion identifiedVersion) {
708
709 final boolean isVersionTwoADifferentProduct = "apache".equals(vendor) && "struts".equals(product);
710
711 final Set<String> majorVersionsAffectingAllPrevious = new HashSet<String>();
712 final boolean matchesAnyPrevious = identifiedVersion == null || "-".equals(identifiedVersion.toString());
713 String majorVersionMatch = null;
714 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
715 final DependencyVersion v = parseDependencyVersion(entry.getKey());
716 if (v == null || "-".equals(v.toString())) {
717 return entry;
718 }
719 if (entry.getValue()) {
720 if (matchesAnyPrevious) {
721 return entry;
722 }
723 if (identifiedVersion != null && identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0))) {
724 majorVersionMatch = v.getVersionParts().get(0);
725 }
726 majorVersionsAffectingAllPrevious.add(v.getVersionParts().get(0));
727 }
728 }
729 if (matchesAnyPrevious) {
730 return null;
731 }
732
733 final boolean canSkipVersions = majorVersionMatch != null && majorVersionsAffectingAllPrevious.size() > 1;
734
735
736 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
737 if (!entry.getValue()) {
738 final DependencyVersion v = parseDependencyVersion(entry.getKey());
739
740 if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) {
741 continue;
742 }
743
744
745 if (identifiedVersion.equals(v)) {
746 return entry;
747 }
748 }
749 }
750 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
751 if (entry.getValue()) {
752 final DependencyVersion v = parseDependencyVersion(entry.getKey());
753
754 if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) {
755 continue;
756 }
757
758
759 if (entry.getValue() && identifiedVersion.compareTo(v) <= 0) {
760 if (!(isVersionTwoADifferentProduct && !identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0)))) {
761 return entry;
762 }
763 }
764 }
765 }
766 return null;
767 }
768
769
770
771
772
773
774
775
776 private DependencyVersion parseDependencyVersion(String cpeStr) {
777 final VulnerableSoftware cpe = new VulnerableSoftware();
778 try {
779 cpe.parseName(cpeStr);
780 } catch (UnsupportedEncodingException ex) {
781
782 LOGGER.trace("", ex);
783 }
784 return parseDependencyVersion(cpe);
785 }
786
787
788
789
790
791
792
793
794 private DependencyVersion parseDependencyVersion(VulnerableSoftware cpe) {
795 final DependencyVersion cpeVersion;
796 if (cpe.getVersion() != null && !cpe.getVersion().isEmpty()) {
797 final String versionText;
798 if (cpe.getUpdate() != null && !cpe.getUpdate().isEmpty()) {
799 versionText = String.format("%s.%s", cpe.getVersion(), cpe.getUpdate());
800 } else {
801 versionText = cpe.getVersion();
802 }
803 cpeVersion = DependencyVersionUtil.parseVersion(versionText);
804 } else {
805 cpeVersion = new DependencyVersion("-");
806 }
807 return cpeVersion;
808 }
809
810
811
812
813
814
815 public synchronized void deleteUnusedCpe() {
816 PreparedStatement ps = null;
817 try {
818 ps = getConnection().prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE"));
819 ps.executeUpdate();
820 } catch (SQLException ex) {
821 LOGGER.error("Unable to delete CPE dictionary entries", ex);
822 } finally {
823 DBUtils.closeStatement(ps);
824 }
825 }
826
827
828
829
830
831
832
833
834
835
836
837 public synchronized void addCpe(String cpe, String vendor, String product) {
838 PreparedStatement ps = null;
839 try {
840 ps = getConnection().prepareStatement(statementBundle.getString("ADD_DICT_CPE"));
841 ps.setString(1, cpe);
842 ps.setString(2, vendor);
843 ps.setString(3, product);
844 ps.executeUpdate();
845 } catch (SQLException ex) {
846 LOGGER.error("Unable to add CPE dictionary entry", ex);
847 } finally {
848 DBUtils.closeStatement(ps);
849 }
850 }
851 }