1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.dependency;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.io.Serializable;
23 import java.security.NoSuchAlgorithmException;
24 import java.util.ArrayList;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.SortedSet;
29 import java.util.TreeSet;
30
31 import org.apache.commons.lang3.builder.EqualsBuilder;
32 import org.apache.commons.lang3.builder.HashCodeBuilder;
33 import org.owasp.dependencycheck.data.nexus.MavenArtifact;
34 import org.owasp.dependencycheck.utils.Checksum;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38
39
40
41
42
43
44
45
46 public class Dependency implements Serializable, Comparable<Dependency> {
47
48
49
50
51 private static final long serialVersionUID = 1L;
52
53
54
55 private static final Logger LOGGER = LoggerFactory.getLogger(Dependency.class);
56
57
58
59 private static final int MAGIC_HASH_INIT_VALUE = 3;
60
61
62
63 private static final int MAGIC_HASH_MULTIPLIER = 47;
64
65
66
67 private String actualFilePath;
68
69
70
71 private String filePath;
72
73
74
75 private String fileName;
76
77
78
79
80 private String packagePath;
81
82
83
84
85
86
87 public String getPackagePath() {
88 return packagePath;
89 }
90
91
92
93
94
95
96 public void setPackagePath(String packagePath) {
97 this.packagePath = packagePath;
98 }
99
100
101
102
103 private String md5sum;
104
105
106
107 private String sha1sum;
108
109
110
111 private Set<Identifier> identifiers;
112
113
114
115 private final EvidenceCollection vendorEvidence;
116
117
118
119 private final EvidenceCollection productEvidence;
120
121
122
123 private final EvidenceCollection versionEvidence;
124
125
126
127
128 public Dependency() {
129 vendorEvidence = new EvidenceCollection();
130 productEvidence = new EvidenceCollection();
131 versionEvidence = new EvidenceCollection();
132 identifiers = new TreeSet<Identifier>();
133 vulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
134 suppressedIdentifiers = new TreeSet<Identifier>();
135 suppressedVulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
136 }
137
138
139
140
141
142
143 public Dependency(File file) {
144 this();
145 this.actualFilePath = file.getAbsolutePath();
146 this.filePath = this.actualFilePath;
147 this.fileName = file.getName();
148 this.packagePath = filePath;
149 determineHashes(file);
150 }
151
152
153
154
155
156
157 public String getFileName() {
158 return this.fileName;
159 }
160
161
162
163
164
165
166
167
168
169 public String getFileNameForJavaScript() {
170 return this.fileName.replace("\\", "\\\\");
171 }
172
173
174
175
176
177
178 public void setFileName(String fileName) {
179 this.fileName = fileName;
180 }
181
182
183
184
185
186
187 public void setActualFilePath(String actualFilePath) {
188 this.actualFilePath = actualFilePath;
189 if (this.sha1sum == null) {
190 final File file = new File(this.actualFilePath);
191 determineHashes(file);
192 }
193 }
194
195
196
197
198
199
200 public String getActualFilePath() {
201 return this.actualFilePath;
202 }
203
204
205
206
207
208
209 public File getActualFile() {
210 return new File(this.actualFilePath);
211 }
212
213
214
215
216
217
218 public void setFilePath(String filePath) {
219 if (this.packagePath == null || this.packagePath.equals(this.filePath)) {
220 this.packagePath = filePath;
221 }
222 this.filePath = filePath;
223 }
224
225
226
227
228 private String displayName = null;
229
230
231
232
233
234
235 public void setDisplayFileName(String displayName) {
236 this.displayName = displayName;
237 }
238
239
240
241
242
243
244
245 public String getDisplayFileName() {
246 if (displayName == null) {
247 return this.fileName;
248 }
249 return this.displayName;
250 }
251
252
253
254
255
256
257
258
259
260
261
262 public String getFilePath() {
263 return this.filePath;
264 }
265
266
267
268
269
270
271 public String getMd5sum() {
272 return this.md5sum;
273 }
274
275
276
277
278
279
280 public void setMd5sum(String md5sum) {
281 this.md5sum = md5sum;
282 }
283
284
285
286
287
288
289 public String getSha1sum() {
290 return this.sha1sum;
291 }
292
293
294
295
296
297
298 public void setSha1sum(String sha1sum) {
299 this.sha1sum = sha1sum;
300 }
301
302
303
304
305
306
307 public Set<Identifier> getIdentifiers() {
308 return this.identifiers;
309 }
310
311
312
313
314
315
316 public void setIdentifiers(Set<Identifier> identifiers) {
317 this.identifiers = identifiers;
318 }
319
320
321
322
323
324
325
326
327
328 public void addIdentifier(String type, String value, String url) {
329 final Identifier i = new Identifier(type, value, url);
330 this.identifiers.add(i);
331 }
332
333
334
335
336
337
338
339
340
341
342 public void addIdentifier(String type, String value, String url, Confidence confidence) {
343 final Identifier i = new Identifier(type, value, url);
344 i.setConfidence(confidence);
345 this.identifiers.add(i);
346 }
347
348
349
350
351
352
353
354
355 public void addAsEvidence(String source, MavenArtifact mavenArtifact, Confidence confidence) {
356 if (mavenArtifact.getGroupId() != null && !mavenArtifact.getGroupId().isEmpty()) {
357 this.getVendorEvidence().addEvidence(source, "groupid", mavenArtifact.getGroupId(), confidence);
358 }
359 if (mavenArtifact.getArtifactId() != null && !mavenArtifact.getArtifactId().isEmpty()) {
360 this.getProductEvidence().addEvidence(source, "artifactid", mavenArtifact.getArtifactId(), confidence);
361 }
362 if (mavenArtifact.getVersion() != null && !mavenArtifact.getVersion().isEmpty()) {
363 this.getVersionEvidence().addEvidence(source, "version", mavenArtifact.getVersion(), confidence);
364 }
365 if (mavenArtifact.getArtifactUrl() != null && !mavenArtifact.getArtifactUrl().isEmpty()) {
366 boolean found = false;
367 for (Identifier i : this.getIdentifiers()) {
368 if ("maven".equals(i.getType()) && i.getValue().equals(mavenArtifact.toString())) {
369 found = true;
370 i.setConfidence(Confidence.HIGHEST);
371 final String url = "http://search.maven.org/#search|ga|1|1%3A%22" + this.getSha1sum() + "%22";
372 i.setUrl(url);
373
374 LOGGER.debug("Already found identifier {}. Confidence set to highest", i.getValue());
375 break;
376 }
377 }
378 if (!found) {
379 LOGGER.debug("Adding new maven identifier {}", mavenArtifact);
380 this.addIdentifier("maven", mavenArtifact.toString(), mavenArtifact.getArtifactUrl(), Confidence.HIGHEST);
381 }
382 }
383 }
384
385
386
387
388
389
390
391 public void addIdentifier(Identifier identifier) {
392 this.identifiers.add(identifier);
393 }
394
395
396
397
398 private Set<Identifier> suppressedIdentifiers;
399
400
401
402
403
404
405 public Set<Identifier> getSuppressedIdentifiers() {
406 return suppressedIdentifiers;
407 }
408
409
410
411
412
413
414 public void setSuppressedIdentifiers(Set<Identifier> suppressedIdentifiers) {
415 this.suppressedIdentifiers = suppressedIdentifiers;
416 }
417
418
419
420
421
422
423 public void addSuppressedIdentifier(Identifier identifier) {
424 this.suppressedIdentifiers.add(identifier);
425 }
426
427
428
429
430 private SortedSet<Vulnerability> suppressedVulnerabilities;
431
432
433
434
435
436
437 public SortedSet<Vulnerability> getSuppressedVulnerabilities() {
438 return suppressedVulnerabilities;
439 }
440
441
442
443
444
445
446 public void setSuppressedVulnerabilities(SortedSet<Vulnerability> suppressedVulnerabilities) {
447 this.suppressedVulnerabilities = suppressedVulnerabilities;
448 }
449
450
451
452
453
454
455 public void addSuppressedVulnerability(Vulnerability vulnerability) {
456 this.suppressedVulnerabilities.add(vulnerability);
457 }
458
459
460
461
462
463
464 public EvidenceCollection getEvidence() {
465 return EvidenceCollection.merge(this.productEvidence, this.vendorEvidence, this.versionEvidence);
466 }
467
468
469
470
471
472
473 public Set<Evidence> getEvidenceForDisplay() {
474 return EvidenceCollection.mergeForDisplay(this.productEvidence, this.vendorEvidence, this.versionEvidence);
475 }
476
477
478
479
480
481
482 public EvidenceCollection getEvidenceUsed() {
483 return EvidenceCollection.mergeUsed(this.productEvidence, this.vendorEvidence, this.versionEvidence);
484 }
485
486
487
488
489
490
491 public EvidenceCollection getVendorEvidence() {
492 return this.vendorEvidence;
493 }
494
495
496
497
498
499
500 public EvidenceCollection getProductEvidence() {
501 return this.productEvidence;
502 }
503
504
505
506
507
508
509 public EvidenceCollection getVersionEvidence() {
510 return this.versionEvidence;
511 }
512
513
514
515
516 private String description;
517
518
519
520
521
522
523 public String getDescription() {
524 return description;
525 }
526
527
528
529
530
531
532 public void setDescription(String description) {
533 this.description = description;
534 }
535
536
537
538
539 private String license;
540
541
542
543
544
545
546 public String getLicense() {
547 return license;
548 }
549
550
551
552
553
554
555 public void setLicense(String license) {
556 this.license = license;
557 }
558
559
560
561
562 private SortedSet<Vulnerability> vulnerabilities;
563
564
565
566
567
568
569 public SortedSet<Vulnerability> getVulnerabilities() {
570 return vulnerabilities;
571 }
572
573
574
575
576
577
578 public void setVulnerabilities(SortedSet<Vulnerability> vulnerabilities) {
579 this.vulnerabilities = vulnerabilities;
580 }
581
582
583
584
585
586
587 private void determineHashes(File file) {
588 String md5 = null;
589 String sha1 = null;
590 try {
591 md5 = Checksum.getMD5Checksum(file);
592 sha1 = Checksum.getSHA1Checksum(file);
593 } catch (IOException ex) {
594 LOGGER.warn("Unable to read '{}' to determine hashes.", file.getName());
595 LOGGER.debug("", ex);
596 } catch (NoSuchAlgorithmException ex) {
597 LOGGER.warn("Unable to use MD5 of SHA1 checksums.");
598 LOGGER.debug("", ex);
599 }
600 this.setMd5sum(md5);
601 this.setSha1sum(sha1);
602 }
603
604
605
606
607
608
609 public void addVulnerability(Vulnerability vulnerability) {
610 this.vulnerabilities.add(vulnerability);
611 }
612
613
614
615
616 private Set<Dependency> relatedDependencies = new TreeSet<Dependency>();
617
618
619
620
621
622
623
624
625 public Set<Dependency> getRelatedDependencies() {
626 return relatedDependencies;
627 }
628
629
630
631
632 private Set<String> projectReferences = new HashSet<String>();
633
634
635
636
637
638
639 public Set<String> getProjectReferences() {
640 return projectReferences;
641 }
642
643
644
645
646
647
648 public void setProjectReferences(Set<String> projectReferences) {
649 this.projectReferences = projectReferences;
650 }
651
652
653
654
655
656
657 public void addProjectReference(String projectReference) {
658 this.projectReferences.add(projectReference);
659 }
660
661
662
663
664
665
666 public void addAllProjectReferences(Set<String> projectReferences) {
667 this.projectReferences.addAll(projectReferences);
668 }
669
670
671
672
673
674
675 public void setRelatedDependencies(Set<Dependency> relatedDependencies) {
676 this.relatedDependencies = relatedDependencies;
677 }
678
679
680
681
682
683
684
685
686
687
688 public void addRelatedDependency(Dependency dependency) {
689 if (this == dependency) {
690 LOGGER.warn("Attempted to add a circular reference - please post the log file to issue #172 here "
691 + "https://github.com/jeremylong/DependencyCheck/issues/172");
692 LOGGER.debug("this: {}", this);
693 LOGGER.debug("dependency: {}", dependency);
694 } else if (!relatedDependencies.add(dependency)) {
695 LOGGER.debug("Failed to add dependency, likely due to referencing the same file as another dependency in the set.");
696 LOGGER.debug("this: {}", this);
697 LOGGER.debug("dependency: {}", dependency);
698 }
699 }
700
701
702
703
704 private List<String> availableVersions = new ArrayList<String>();
705
706
707
708
709
710
711 public List<String> getAvailableVersions() {
712 return availableVersions;
713 }
714
715
716
717
718
719
720 public void setAvailableVersions(List<String> availableVersions) {
721 this.availableVersions = availableVersions;
722 }
723
724
725
726
727
728
729 public void addAvailableVersion(String version) {
730 this.availableVersions.add(version);
731 }
732
733
734
735
736
737
738
739
740 @Override
741 public int compareTo(Dependency o) {
742 return this.getFilePath().compareToIgnoreCase(o.getFilePath());
743 }
744
745
746
747
748
749
750
751 @Override
752 public boolean equals(Object obj) {
753 if (obj == null || getClass() != obj.getClass()) {
754 return false;
755 }
756 final Dependency other = (Dependency) obj;
757 return new EqualsBuilder()
758 .appendSuper(super.equals(obj))
759 .append(this.actualFilePath, other.actualFilePath)
760 .append(this.filePath, other.filePath)
761 .append(this.fileName, other.fileName)
762 .append(this.packagePath, other.packagePath)
763 .append(this.md5sum, other.md5sum)
764 .append(this.sha1sum, other.sha1sum)
765 .append(this.identifiers, other.identifiers)
766 .append(this.vendorEvidence, other.vendorEvidence)
767 .append(this.productEvidence, other.productEvidence)
768 .append(this.versionEvidence, other.versionEvidence)
769 .append(this.description, other.description)
770 .append(this.license, other.license)
771 .append(this.vulnerabilities, other.vulnerabilities)
772
773 .append(this.projectReferences, other.projectReferences)
774 .append(this.availableVersions, other.availableVersions)
775 .isEquals();
776 }
777
778
779
780
781
782
783 @Override
784 public int hashCode() {
785 return new HashCodeBuilder(MAGIC_HASH_INIT_VALUE, MAGIC_HASH_MULTIPLIER)
786 .append(actualFilePath)
787 .append(filePath)
788 .append(fileName)
789 .append(md5sum)
790 .append(sha1sum)
791 .append(identifiers)
792 .append(vendorEvidence)
793 .append(productEvidence)
794 .append(versionEvidence)
795 .append(description)
796 .append(license)
797 .append(vulnerabilities)
798
799 .append(projectReferences)
800 .append(availableVersions)
801 .toHashCode();
802 }
803
804
805
806
807
808
809
810 @Override
811 public String toString() {
812 return "Dependency{ fileName='" + fileName + "', actualFilePath='" + actualFilePath
813 + "', filePath='" + filePath + "', packagePath='" + packagePath + "'}";
814 }
815 }