mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-15 00:03:43 +01:00
Compare commits
1386 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc2953d6a3 | ||
|
|
c888019068 | ||
|
|
56639d3965 | ||
|
|
09ff99823e | ||
|
|
5078e32dc7 | ||
|
|
ecaadff0d8 | ||
|
|
f2ad8cc7d1 | ||
|
|
c8d77eb213 | ||
|
|
fe3d9e8bf6 | ||
|
|
6c4171be75 | ||
|
|
4bbb466e43 | ||
|
|
c478415667 | ||
|
|
fc832b67c5 | ||
|
|
943a9ea97e | ||
|
|
2c7ab297d7 | ||
|
|
d8299f7db1 | ||
|
|
4deeb33f08 | ||
|
|
3bf4cf8c85 | ||
|
|
e0217fc6c3 | ||
|
|
62a3efa23a | ||
|
|
cc7ebe6d52 | ||
|
|
5d920e4b44 | ||
|
|
1264ea54a1 | ||
|
|
caa1d77d23 | ||
|
|
20a55b3342 | ||
|
|
8bfe67fc60 | ||
|
|
d42a1c6ab1 | ||
|
|
80a89ef6d1 | ||
|
|
1a0e605f0c | ||
|
|
573c8eb509 | ||
|
|
e676e3a14b | ||
|
|
af8c807ee0 | ||
|
|
dfaa5df965 | ||
|
|
32055ecdcc | ||
|
|
9db71c5f0c | ||
|
|
99856bf285 | ||
|
|
4d006b3e05 | ||
|
|
4e37165ba6 | ||
|
|
38a5834785 | ||
|
|
d6e1352869 | ||
|
|
bf1b7bd7a2 | ||
|
|
2306327057 | ||
|
|
2d389ba73f | ||
|
|
ce8d5bc635 | ||
|
|
8fdc2007e0 | ||
|
|
88a97769de | ||
|
|
589c761cb0 | ||
|
|
3e6787fd61 | ||
|
|
aff52ee3f5 | ||
|
|
4555b02592 | ||
|
|
e1d4599a93 | ||
|
|
1a1e141cb8 | ||
|
|
33218f41e8 | ||
|
|
8772cda47a | ||
|
|
512eb713e4 | ||
|
|
0f90d48c62 | ||
|
|
658860e396 | ||
|
|
7522dae557 | ||
|
|
e34e65a3ba | ||
|
|
5a001a2c32 | ||
|
|
13a03eb250 | ||
|
|
cd863b6cca | ||
|
|
83b182dda5 | ||
|
|
3b90d1a564 | ||
|
|
d724855dfc | ||
|
|
78008330fe | ||
|
|
e716aad224 | ||
|
|
aa0d7cb4e9 | ||
|
|
0cd43ce35c | ||
|
|
ac98c8e395 | ||
|
|
70a8fc09c6 | ||
|
|
5b00d05e2e | ||
|
|
28c1730a02 | ||
|
|
c54483d36f | ||
|
|
2dd02ff8cb | ||
|
|
46c5501b7a | ||
|
|
f154826749 | ||
|
|
96383ef985 | ||
|
|
ab4b19dbab | ||
|
|
cdc53ac570 | ||
|
|
143cc1912e | ||
|
|
0d90b676bc | ||
|
|
5fadbb3d25 | ||
|
|
0ec99a3e12 | ||
|
|
1efbc44cc4 | ||
|
|
735fcfeee2 | ||
|
|
4a77150566 | ||
|
|
180a420219 | ||
|
|
d12ba8f3ef | ||
|
|
f333ef76d9 | ||
|
|
af5ba6854e | ||
|
|
8b7ce06793 | ||
|
|
297a5e516f | ||
|
|
92b11526be | ||
|
|
299350f655 | ||
|
|
127eafc9b3 | ||
|
|
ad1ad3a997 | ||
|
|
82151c5b3f | ||
|
|
90457c89ff | ||
|
|
3f3ac86d38 | ||
|
|
aa126039e5 | ||
|
|
662815b1ee | ||
|
|
243c36849c | ||
|
|
52d5baaf3f | ||
|
|
89217f778e | ||
|
|
9bc9bc9169 | ||
|
|
6b73430473 | ||
|
|
5ca5bca3df | ||
|
|
89ab382a18 | ||
|
|
bad425c0d7 | ||
|
|
cdbbb1b94c | ||
|
|
0a9d8a9b22 | ||
|
|
e662041d06 | ||
|
|
155464bc87 | ||
|
|
06cd811ae4 | ||
|
|
1b2cd354db | ||
|
|
1b31268f59 | ||
|
|
b57ef7291f | ||
|
|
c3bf6aa3f8 | ||
|
|
d2fa14bbe2 | ||
|
|
9b6e55e90c | ||
|
|
afb07b651f | ||
|
|
e6806fdf2b | ||
|
|
e5ff2cff4e | ||
|
|
17d7d47b9a | ||
|
|
64e32061ab | ||
|
|
931110ba6c | ||
|
|
d90e7820cd | ||
|
|
824898dba5 | ||
|
|
761dd61ed4 | ||
|
|
89c63e6d87 | ||
|
|
a2361f9327 | ||
|
|
ea15205be8 | ||
|
|
0a45048535 | ||
|
|
1c51655ce3 | ||
|
|
7749f0da7c | ||
|
|
5695238f95 | ||
|
|
e1feeb7e21 | ||
|
|
84fecaf040 | ||
|
|
da77727673 | ||
|
|
f8c913a3e8 | ||
|
|
2024881ee1 | ||
|
|
35ed3a51e5 | ||
|
|
24b1c4d0a4 | ||
|
|
7ec2458fb5 | ||
|
|
175feaea23 | ||
|
|
dda6cf728b | ||
|
|
a7fd410b01 | ||
|
|
d281c36733 | ||
|
|
dc91e44c0a | ||
|
|
7967a858f4 | ||
|
|
2081407e38 | ||
|
|
976eabd527 | ||
|
|
b6d6a5de2b | ||
|
|
2d58cfe0ce | ||
|
|
9df8bdff5f | ||
|
|
c86b821951 | ||
|
|
4def086bf9 | ||
|
|
885c890d7d | ||
|
|
06060a6694 | ||
|
|
70667814f6 | ||
|
|
766b7a940c | ||
|
|
0c37586357 | ||
|
|
b4aa55ce1f | ||
|
|
109443ce77 | ||
|
|
5f38741831 | ||
|
|
c6f391501d | ||
|
|
d1f3105fbd | ||
|
|
8f88ca9d3d | ||
|
|
f9e4ca0cc2 | ||
|
|
5caf023677 | ||
|
|
35c2f4873c | ||
|
|
1ed7bab375 | ||
|
|
f0d1bfb777 | ||
|
|
42519ac843 | ||
|
|
8869e13385 | ||
|
|
8f9cbfe806 | ||
|
|
6481938626 | ||
|
|
9c7cc2acbf | ||
|
|
89a57d4ed3 | ||
|
|
732378592b | ||
|
|
19dc46660b | ||
|
|
4aad3471af | ||
|
|
533b455356 | ||
|
|
92bd305b00 | ||
|
|
f71eb09f74 | ||
|
|
83d4a7bc18 | ||
|
|
58807d9021 | ||
|
|
29595324c4 | ||
|
|
f9064e526f | ||
|
|
93ec2e8639 | ||
|
|
0e2a31709a | ||
|
|
c785b39eda | ||
|
|
8fab2f58da | ||
|
|
e44ee3bfe1 | ||
|
|
62065c9d28 | ||
|
|
c76275275f | ||
|
|
257f78879d | ||
|
|
894263809c | ||
|
|
bc9458101c | ||
|
|
c503935d6a | ||
|
|
d4756c9eb8 | ||
|
|
0004767775 | ||
|
|
74908642c7 | ||
|
|
aadfb71c98 | ||
|
|
1244af649d | ||
|
|
7bd48cc811 | ||
|
|
8f3ce38418 | ||
|
|
1b2d9b4245 | ||
|
|
c6b2b34fde | ||
|
|
e58fc13fdb | ||
|
|
922d53d2e4 | ||
|
|
fec53b3951 | ||
|
|
e72e2c6a02 | ||
|
|
08d001ee05 | ||
|
|
99d8a07f4a | ||
|
|
eef565134b | ||
|
|
9d78293437 | ||
|
|
fc0a556e5f | ||
|
|
b6b070584f | ||
|
|
e13225eee6 | ||
|
|
da20fb2922 | ||
|
|
459c2beb12 | ||
|
|
f1cc44dead | ||
|
|
d24cfdc382 | ||
|
|
ae4cc543f6 | ||
|
|
abdb3d17f9 | ||
|
|
4095c5da38 | ||
|
|
78fab728e4 | ||
|
|
52097a6867 | ||
|
|
cb990b55b5 | ||
|
|
5070fe303a | ||
|
|
b4405ebf3e | ||
|
|
d9e6bf5068 | ||
|
|
6822188f52 | ||
|
|
15858d03ff | ||
|
|
814a733258 | ||
|
|
3ce85d8ca9 | ||
|
|
d3bff2f39d | ||
|
|
f2272730ac | ||
|
|
fe19c97d86 | ||
|
|
d49556bf3d | ||
|
|
56b447493e | ||
|
|
e45b68eda7 | ||
|
|
8df1ef5986 | ||
|
|
dac34cda82 | ||
|
|
9925e30c8b | ||
|
|
dc5566b5ae | ||
|
|
8132ee651a | ||
|
|
f49a134a3d | ||
|
|
bd955cda06 | ||
|
|
c6dbc01912 | ||
|
|
fabe1aa940 | ||
|
|
ba5dbb94b8 | ||
|
|
6ccc053d7e | ||
|
|
cf21dfaa3a | ||
|
|
54ceb630de | ||
|
|
0a0c302cb2 | ||
|
|
f6eef54566 | ||
|
|
a69804f84d | ||
|
|
0b06b194b0 | ||
|
|
73f6ce304c | ||
|
|
195818a432 | ||
|
|
47c817de1c | ||
|
|
8b3894f213 | ||
|
|
a411252f07 | ||
|
|
d7626aeb3f | ||
|
|
3565098650 | ||
|
|
803fcf146b | ||
|
|
d9d646c5fb | ||
|
|
034a274b07 | ||
|
|
718d7af8bc | ||
|
|
860d3d9c8b | ||
|
|
f28b566992 | ||
|
|
1c261c7463 | ||
|
|
226b2482b1 | ||
|
|
ff346dc429 | ||
|
|
2dcef25175 | ||
|
|
46702bbb5c | ||
|
|
5600c9bc69 | ||
|
|
d7e46b1693 | ||
|
|
fe8c60ade1 | ||
|
|
288892441f | ||
|
|
e1179a8e22 | ||
|
|
4b06d0fd87 | ||
|
|
464d91f45a | ||
|
|
5cc7aa25cc | ||
|
|
20ec224070 | ||
|
|
9cbcc29ddb | ||
|
|
b9003a2f02 | ||
|
|
6b303410d1 | ||
|
|
8cae2f24b1 | ||
|
|
0a04d753ea | ||
|
|
35402c7bd3 | ||
|
|
847a97f61c | ||
|
|
fac27a6120 | ||
|
|
2e24eda00d | ||
|
|
7a653abf22 | ||
|
|
ae09229107 | ||
|
|
be35f48bdd | ||
|
|
846173844e | ||
|
|
59c28d8e51 | ||
|
|
abdfa3ccf6 | ||
|
|
99ad6634c4 | ||
|
|
84556fb055 | ||
|
|
26e14e0151 | ||
|
|
3df2daa5cb | ||
|
|
c55efddc81 | ||
|
|
a59c8908f0 | ||
|
|
a421c5f952 | ||
|
|
37b0612d45 | ||
|
|
07bc94f9f6 | ||
|
|
82511880ac | ||
|
|
2f5cc6a8a4 | ||
|
|
f9a0f5e7a1 | ||
|
|
47b083eaca | ||
|
|
8fcf5ee760 | ||
|
|
f2006206d3 | ||
|
|
c32361a428 | ||
|
|
ac83c2bc3c | ||
|
|
32808c16e7 | ||
|
|
e4e2433396 | ||
|
|
8196b6e69e | ||
|
|
8dd49b6156 | ||
|
|
c4ab83a801 | ||
|
|
2c51b7b835 | ||
|
|
bab49d04b7 | ||
|
|
6963d66240 | ||
|
|
8cbf3ffc6b | ||
|
|
2a4693f6ed | ||
|
|
217256746c | ||
|
|
6c90225024 | ||
|
|
92d8a894e3 | ||
|
|
c89d619808 | ||
|
|
31dd4f6305 | ||
|
|
ff9715ede7 | ||
|
|
ffd1e383c2 | ||
|
|
2cc4f8c2fe | ||
|
|
6f513eb359 | ||
|
|
b235a5bb49 | ||
|
|
25f1912573 | ||
|
|
d24d6f6b52 | ||
|
|
afdb156c84 | ||
|
|
643d3600b8 | ||
|
|
9c51bff55b | ||
|
|
81c91b3877 | ||
|
|
3d365eb258 | ||
|
|
6857f6d8f8 | ||
|
|
81bd9991bb | ||
|
|
056fa9ded2 | ||
|
|
a3792c474b | ||
|
|
ec233dbb46 | ||
|
|
d89cd789ac | ||
|
|
69088e162d | ||
|
|
ec53bd4125 | ||
|
|
35a264d21c | ||
|
|
0372c2eccc | ||
|
|
08c7ffc6d9 | ||
|
|
e386f6ac20 | ||
|
|
60ab893888 | ||
|
|
f2d960c3eb | ||
|
|
fb88aeaeb9 | ||
|
|
94561de719 | ||
|
|
89ed18cea3 | ||
|
|
b996fa234b | ||
|
|
f6cd5cb4b2 | ||
|
|
6ac8caaf5f | ||
|
|
e5a4145e37 | ||
|
|
2c8b408bfb | ||
|
|
58c5c04feb | ||
|
|
b0d6070d28 | ||
|
|
3728594f73 | ||
|
|
dc2f1eabb2 | ||
|
|
eda08e7454 | ||
|
|
1bf4b6daa9 | ||
|
|
f757266282 | ||
|
|
0321823125 | ||
|
|
33d190afaa | ||
|
|
ff16c4f127 | ||
|
|
134728438e | ||
|
|
754bd68a87 | ||
|
|
bd32eeeaa2 | ||
|
|
1b9a3bd4bd | ||
|
|
584d369b0b | ||
|
|
0ebe052752 | ||
|
|
535863bc52 | ||
|
|
dd925cd92b | ||
|
|
5529de3d95 | ||
|
|
ce6b65adb8 | ||
|
|
9897109332 | ||
|
|
cfc851a99b | ||
|
|
380178ccc8 | ||
|
|
3227ddd9f9 | ||
|
|
336be63237 | ||
|
|
37c9b9e1f5 | ||
|
|
ebb3e02dcc | ||
|
|
352505c54f | ||
|
|
0c7998712e | ||
|
|
b9a20e7ac5 | ||
|
|
7ab89b900c | ||
|
|
9620956727 | ||
|
|
9b85768b7e | ||
|
|
5276e1863d | ||
|
|
0fc1a30a2c | ||
|
|
8609b98b1c | ||
|
|
c85514a17a | ||
|
|
d00bef5546 | ||
|
|
b905f46f98 | ||
|
|
cdd4765d38 | ||
|
|
d62793f4ad | ||
|
|
d83d325a49 | ||
|
|
e5baf99814 | ||
|
|
b4aeab3501 | ||
|
|
039bfd372d | ||
|
|
1a92de71d1 | ||
|
|
d8279e11aa | ||
|
|
b1b8584641 | ||
|
|
11e75df1a9 | ||
|
|
25fc2bfbea | ||
|
|
a93c84ff64 | ||
|
|
986a4182d9 | ||
|
|
d38a8b109b | ||
|
|
711d8c8c6b | ||
|
|
0d1d22aeff | ||
|
|
ac2231f0f3 | ||
|
|
21344dacfc | ||
|
|
ca22ba5bbc | ||
|
|
fc64c34214 | ||
|
|
c35bc2476d | ||
|
|
222826af95 | ||
|
|
db28db0bc7 | ||
|
|
931f7d47ea | ||
|
|
987ed1cefc | ||
|
|
3e9a77abfa | ||
|
|
3879eb6b3a | ||
|
|
5e5a2040fc | ||
|
|
eea44d7de2 | ||
|
|
3fcbf075fb | ||
|
|
b2641494cc | ||
|
|
c48a794aee | ||
|
|
e53906aea8 | ||
|
|
05a4a1670f | ||
|
|
4bd35852a5 | ||
|
|
be4d56f8d2 | ||
|
|
dfbcd616f2 | ||
|
|
dc0106348d | ||
|
|
f2666d4a30 | ||
|
|
4220e58d26 | ||
|
|
07de43981a | ||
|
|
fa352c1a8f | ||
|
|
e5d582b30b | ||
|
|
8fb14ffdf3 | ||
|
|
c16e85e7db | ||
|
|
25a72e3508 | ||
|
|
20411da67b | ||
|
|
81bfdc69dd | ||
|
|
5e2829fe49 | ||
|
|
2aba09f090 | ||
|
|
38e27309fb | ||
|
|
6b586684e6 | ||
|
|
773e280339 | ||
|
|
297a67cd00 | ||
|
|
ceb61ebe74 | ||
|
|
6c85e3502e | ||
|
|
690192300f | ||
|
|
3ba963f474 | ||
|
|
9b2cacc3a0 | ||
|
|
315a616293 | ||
|
|
3c56cd6738 | ||
|
|
a48ac013e8 | ||
|
|
258602ce1a | ||
|
|
c85b547502 | ||
|
|
d6266c36bf | ||
|
|
fdd7f30e9a | ||
|
|
3994ef3619 | ||
|
|
633028a63f | ||
|
|
013374e9db | ||
|
|
4358b47e91 | ||
|
|
6decc1ce30 | ||
|
|
8a3dba3064 | ||
|
|
27bcead1bc | ||
|
|
acb9c01776 | ||
|
|
79fd23d51b | ||
|
|
776614d211 | ||
|
|
b03a498cd7 | ||
|
|
b612926fb6 | ||
|
|
b67377f505 | ||
|
|
2033acbe2a | ||
|
|
e435cfc489 | ||
|
|
a3199a52af | ||
|
|
99be870ab9 | ||
|
|
9b2ecb4701 | ||
|
|
be7443a0a0 | ||
|
|
0de6557872 | ||
|
|
258e890056 | ||
|
|
d84bbad79a | ||
|
|
07e6477686 | ||
|
|
acde161412 | ||
|
|
8d8f9c6d26 | ||
|
|
c7507d9743 | ||
|
|
ff970fde56 | ||
|
|
2c4a997c64 | ||
|
|
5c787e0b69 | ||
|
|
41da8435cc | ||
|
|
84ecc4c664 | ||
|
|
d18a36af22 | ||
|
|
b3e766aa50 | ||
|
|
0cee54c51b | ||
|
|
41e436a183 | ||
|
|
743fc19fa3 | ||
|
|
76e8c66b1b | ||
|
|
4379ea63f0 | ||
|
|
00ae54b4b2 | ||
|
|
3a7fd7d271 | ||
|
|
94a0c98bfe | ||
|
|
c2b2b2698d | ||
|
|
9bb630bae6 | ||
|
|
c47b2f5b18 | ||
|
|
ecdc9a968d | ||
|
|
c041ff66e2 | ||
|
|
fe0e2d5c2d | ||
|
|
2cf3bca8de | ||
|
|
b2a817e17b | ||
|
|
d1ca951ffa | ||
|
|
b3932ae8c5 | ||
|
|
35223d5737 | ||
|
|
9d263f11e5 | ||
|
|
3f28b30e95 | ||
|
|
d797abdb1f | ||
|
|
3b3a940ee4 | ||
|
|
1b5b61b25e | ||
|
|
00d29b88df | ||
|
|
ab9bc9da74 | ||
|
|
b79f7b7ab8 | ||
|
|
9b34b5ca89 | ||
|
|
b486788993 | ||
|
|
563e9c51e1 | ||
|
|
6ab5e3ed4f | ||
|
|
43a6c81151 | ||
|
|
887a5d50a4 | ||
|
|
be68f8c3f7 | ||
|
|
86a4923157 | ||
|
|
f80ff31412 | ||
|
|
94acc82bf5 | ||
|
|
3c1a1fcca1 | ||
|
|
b3d08e4cb8 | ||
|
|
ab766ce85b | ||
|
|
bcb8245c61 | ||
|
|
c9e60d5c3a | ||
|
|
eb7c74eea7 | ||
|
|
40f5911ceb | ||
|
|
2a8809adbb | ||
|
|
39524c4064 | ||
|
|
c1cc2d6350 | ||
|
|
acb857f433 | ||
|
|
d343d92b17 | ||
|
|
43cb4716a9 | ||
|
|
6222561431 | ||
|
|
07b10e9e23 | ||
|
|
dffe8cef7a | ||
|
|
bb26626fd5 | ||
|
|
2f207de1a0 | ||
|
|
a69419ed04 | ||
|
|
be7c1ba914 | ||
|
|
461f6ad2c1 | ||
|
|
aff85cbfb8 | ||
|
|
c0ce4523fa | ||
|
|
65f8b3978d | ||
|
|
80ca3e114e | ||
|
|
330e803675 | ||
|
|
337e9ac3ef | ||
|
|
dfb78788f9 | ||
|
|
2dc560f583 | ||
|
|
7355400548 | ||
|
|
50b4630436 | ||
|
|
132d43f999 | ||
|
|
0627f20f5e | ||
|
|
40f329512b | ||
|
|
c196c08ada | ||
|
|
8f1e0d57bf | ||
|
|
c30c455a9f | ||
|
|
cd0e8e1c6b | ||
|
|
cbeb91f9a9 | ||
|
|
a3830989ba | ||
|
|
86427e2042 | ||
|
|
8f079de0aa | ||
|
|
651727c697 | ||
|
|
5c55f4d4bb | ||
|
|
c8502d3b7b | ||
|
|
22e3b9b544 | ||
|
|
f16db8298b | ||
|
|
cf4a32b260 | ||
|
|
b8d83c37d9 | ||
|
|
617f6bb8ef | ||
|
|
0c9f2bf5d2 | ||
|
|
eb9afecd66 | ||
|
|
2c1f2ae589 | ||
|
|
9387b09a19 | ||
|
|
f17f04f00a | ||
|
|
07f0192088 | ||
|
|
0fd19f0de8 | ||
|
|
e954fa6478 | ||
|
|
a0fdfc0f39 | ||
|
|
57a4372b65 | ||
|
|
c11cb38269 | ||
|
|
e4fd446946 | ||
|
|
714d8ac3ba | ||
|
|
f09293e077 | ||
|
|
389e8bc325 | ||
|
|
367f763ce5 | ||
|
|
3febed82f1 | ||
|
|
8a6371fe68 | ||
|
|
93937feb13 | ||
|
|
21e62d8597 | ||
|
|
88e8019858 | ||
|
|
cbe562a204 | ||
|
|
4dc40389a3 | ||
|
|
0552f10c38 | ||
|
|
c9ac7401e8 | ||
|
|
60625b9978 | ||
|
|
b4b53cfa4c | ||
|
|
f1e1d67f4e | ||
|
|
982641752f | ||
|
|
ba66cbbc95 | ||
|
|
750d13a300 | ||
|
|
3c69a87fc2 | ||
|
|
dbaddab07b | ||
|
|
1d58811680 | ||
|
|
4d78fe9ca4 | ||
|
|
56d3082696 | ||
|
|
8f573aba2f | ||
|
|
96633360d0 | ||
|
|
8ae7935cee | ||
|
|
68e860baad | ||
|
|
38ead3133f | ||
|
|
553d1f85c4 | ||
|
|
d9a985ff38 | ||
|
|
d3a2d2b248 | ||
|
|
575b8e5f62 | ||
|
|
37ff924c74 | ||
|
|
7ccbc4c77c | ||
|
|
27b7a60a8d | ||
|
|
dca731ffb8 | ||
|
|
0d56de99a7 | ||
|
|
ac5e11d327 | ||
|
|
9d315b0ff9 | ||
|
|
038fe84498 | ||
|
|
4fd59f2a19 | ||
|
|
f77c3bfdf7 | ||
|
|
dc7d941316 | ||
|
|
433cc1e32c | ||
|
|
c066a03683 | ||
|
|
562a8036bc | ||
|
|
53ac703f09 | ||
|
|
a2891d97d0 | ||
|
|
2bd5169f20 | ||
|
|
b3fd6d8c92 | ||
|
|
cea281b1d3 | ||
|
|
e85b2a8961 | ||
|
|
77b879d6bb | ||
|
|
9de3ae5cf2 | ||
|
|
b3a0dc3506 | ||
|
|
383731da4d | ||
|
|
67abb42652 | ||
|
|
edcc24bc12 | ||
|
|
a6836cab15 | ||
|
|
8f985737b0 | ||
|
|
6e2f102177 | ||
|
|
46a768339a | ||
|
|
f1dbbd62e9 | ||
|
|
8bb94889e0 | ||
|
|
da38e4e00c | ||
|
|
d8e8156b1c | ||
|
|
77a1b18673 | ||
|
|
9abd51f318 | ||
|
|
c7d51a29ac | ||
|
|
ac453ef32a | ||
|
|
db25493c04 | ||
|
|
8d4b4d3cd9 | ||
|
|
b05f13d82b | ||
|
|
438622d450 | ||
|
|
4f79efedc9 | ||
|
|
845fa89d0f | ||
|
|
29768576c8 | ||
|
|
4e659d799d | ||
|
|
10596bcb54 | ||
|
|
5ac6f4f7b3 | ||
|
|
957bb46e5c | ||
|
|
1042a537c1 | ||
|
|
2159b4b691 | ||
|
|
ce48e07e18 | ||
|
|
48dded02c6 | ||
|
|
b7d77042bf | ||
|
|
b4ea2569e3 | ||
|
|
42a9f864eb | ||
|
|
22e6de19c4 | ||
|
|
572a65d661 | ||
|
|
108ecb7e12 | ||
|
|
9c87d61528 | ||
|
|
dd903dd7e5 | ||
|
|
ae13cb2513 | ||
|
|
40f47ccd4e | ||
|
|
c344cd2a2b | ||
|
|
7601af24f0 | ||
|
|
0197eb0d08 | ||
|
|
a248967ae8 | ||
|
|
a4beb58b54 | ||
|
|
922cc942a4 | ||
|
|
f11b086381 | ||
|
|
e5eab69f65 | ||
|
|
961884ef12 | ||
|
|
5dbbf643a4 | ||
|
|
f937458c25 | ||
|
|
c617e62a16 | ||
|
|
343c886d54 | ||
|
|
824d85b2a0 | ||
|
|
0289fc5ce2 | ||
|
|
914a886bfe | ||
|
|
f65c30e975 | ||
|
|
48ac0049aa | ||
|
|
fea1117eae | ||
|
|
ace1a060db | ||
|
|
be6ad9c5e3 | ||
|
|
b2d51a2a9b | ||
|
|
74411d8656 | ||
|
|
332392b7ba | ||
|
|
e441414854 | ||
|
|
4b1d79e7f7 | ||
|
|
d7889e27e5 | ||
|
|
e65a68ce78 | ||
|
|
990f6d3730 | ||
|
|
84a62b3707 | ||
|
|
e18789b8d3 | ||
|
|
cb7be0e460 | ||
|
|
df825d0109 | ||
|
|
ce4baecb4b | ||
|
|
48907517e9 | ||
|
|
dde1d96058 | ||
|
|
b2f688a032 | ||
|
|
b4664f85f0 | ||
|
|
2725d32c33 | ||
|
|
c9f80db3c6 | ||
|
|
cb53ddf8a8 | ||
|
|
fdca41a71b | ||
|
|
d59ceee0f7 | ||
|
|
38b08835c2 | ||
|
|
dbbdb1bcbe | ||
|
|
b408e5d0d3 | ||
|
|
30f00508f5 | ||
|
|
75bb6aa966 | ||
|
|
eff206fb2b | ||
|
|
98da419c96 | ||
|
|
efe226045d | ||
|
|
35ba1532f4 | ||
|
|
476d732a3c | ||
|
|
21efc0c4a5 | ||
|
|
c20c6665fd | ||
|
|
cd497bfe9b | ||
|
|
25c42bee6d | ||
|
|
6d639385da | ||
|
|
fd1c0efedf | ||
|
|
5d2010aa73 | ||
|
|
d9333b2e93 | ||
|
|
3034306fcc | ||
|
|
0c7bae6fd7 | ||
|
|
855233f498 | ||
|
|
6b859a0478 | ||
|
|
2f37b658f1 | ||
|
|
3bd952e5c5 | ||
|
|
ae58c1fa99 | ||
|
|
dfb411cb6a | ||
|
|
449e3f5cc6 | ||
|
|
1b1fe17fca | ||
|
|
f3c457745e | ||
|
|
26f2e2b223 | ||
|
|
fcdd399eea | ||
|
|
c1d16782ab | ||
|
|
860434a1d5 | ||
|
|
38b493ee9d | ||
|
|
19dc560d56 | ||
|
|
bb10214db0 | ||
|
|
6a871c51a1 | ||
|
|
d7ff3050c2 | ||
|
|
8e0a0379d5 | ||
|
|
b7ceb90e61 | ||
|
|
c1935c83f6 | ||
|
|
62f08a2105 | ||
|
|
38d7f6e671 | ||
|
|
3c2c99c236 | ||
|
|
7694402ae4 | ||
|
|
7ed1d13221 | ||
|
|
47e89e35b2 | ||
|
|
3633759295 | ||
|
|
98bdb0479b | ||
|
|
1e40df227d | ||
|
|
caf0a709b8 | ||
|
|
daef951e59 | ||
|
|
73eab87dd9 | ||
|
|
1a2720649b | ||
|
|
1083cdb743 | ||
|
|
06eb8f9c10 | ||
|
|
31af15d267 | ||
|
|
12938df375 | ||
|
|
24d8dbcf64 | ||
|
|
2b7585357f | ||
|
|
5b659966c8 | ||
|
|
2834d6cac7 | ||
|
|
65dd4c873f | ||
|
|
8c834e634b | ||
|
|
f92430d092 | ||
|
|
b110e944c3 | ||
|
|
77eb5b5147 | ||
|
|
1fabdb9e2d | ||
|
|
e8682ac058 | ||
|
|
08603ad905 | ||
|
|
224b867737 | ||
|
|
0eb4ac5bcc | ||
|
|
876ca5927d | ||
|
|
98b4509014 | ||
|
|
c0013a0ba5 | ||
|
|
cc915e39c5 | ||
|
|
b569ad4ef5 | ||
|
|
6ab5388075 | ||
|
|
ded3079390 | ||
|
|
44fe358766 | ||
|
|
cee4b089c6 | ||
|
|
ba8bd4f95c | ||
|
|
c602072e5b | ||
|
|
76061c84aa | ||
|
|
cd01d3e923 | ||
|
|
ff23e7aba7 | ||
|
|
e61fb6f206 | ||
|
|
a6cab8fddc | ||
|
|
ec16d9abfc | ||
|
|
b5c67a47d1 | ||
|
|
a4c1e3b0bc | ||
|
|
b160d58d1b | ||
|
|
b6a4dfb424 | ||
|
|
5837718cf4 | ||
|
|
962e579434 | ||
|
|
63a249ecb0 | ||
|
|
3f40ca65f5 | ||
|
|
57668fc618 | ||
|
|
e82d14c973 | ||
|
|
8e9aa23c3c | ||
|
|
4687c7dcda | ||
|
|
5d857c731f | ||
|
|
eaec1205a1 | ||
|
|
e3d03c3d78 | ||
|
|
927fb013ff | ||
|
|
4deb14ccfb | ||
|
|
e04dba610b | ||
|
|
99a5dfee31 | ||
|
|
66842fca8e | ||
|
|
a47280f47b | ||
|
|
2808ca139c | ||
|
|
d87467aa88 | ||
|
|
382aad5119 | ||
|
|
93f94b65f1 | ||
|
|
bc66d4b0e7 | ||
|
|
ff044c831f | ||
|
|
cb85292f99 | ||
|
|
7c7722e8fc | ||
|
|
78cc6764bf | ||
|
|
0b540d6406 | ||
|
|
f1e0b7a94f | ||
|
|
611635a9a2 | ||
|
|
26c30b013b | ||
|
|
899f5231b5 | ||
|
|
0cfeee18c9 | ||
|
|
3e44835687 | ||
|
|
d5ac67071f | ||
|
|
6aee9ce92e | ||
|
|
6a268bfb68 | ||
|
|
63848e815f | ||
|
|
6640df18ac | ||
|
|
b9436c0cab | ||
|
|
c730f7931f | ||
|
|
ef6035b5be | ||
|
|
8502c0f048 | ||
|
|
acc4d5201a | ||
|
|
8248f31b20 | ||
|
|
39c1624d42 | ||
|
|
7eb82f2e84 | ||
|
|
df0d0d820a | ||
|
|
e0c0d8bc04 | ||
|
|
97619d8ba1 | ||
|
|
80df96fd0d | ||
|
|
579e76430d | ||
|
|
36dd7269e2 | ||
|
|
6596cb014f | ||
|
|
62ac63fd77 | ||
|
|
e6e8d96f12 | ||
|
|
f80464ea31 | ||
|
|
75b0c6f7a3 | ||
|
|
f95ce8c7b5 | ||
|
|
c991a3ccfd | ||
|
|
a1d612b1f6 | ||
|
|
d3cbd20c5e | ||
|
|
cff4f29ba4 | ||
|
|
dc08363360 | ||
|
|
a2aa8d9336 | ||
|
|
ab2bfa951c | ||
|
|
e871d37044 | ||
|
|
e32ee71bea | ||
|
|
3bc8823e54 | ||
|
|
a4b9dfaf1c | ||
|
|
c7c85ac676 | ||
|
|
1af445a390 | ||
|
|
4236a2e6f7 | ||
|
|
47e58942f8 | ||
|
|
f854ed50d6 | ||
|
|
2933a173a2 | ||
|
|
39c45cd329 | ||
|
|
93e6473828 | ||
|
|
2cf96bef52 | ||
|
|
3850ef4355 | ||
|
|
d29f989c22 | ||
|
|
0e31d503d0 | ||
|
|
8c2d552238 | ||
|
|
1b6cb61f8a | ||
|
|
b6e0fa9085 | ||
|
|
1f983d502e | ||
|
|
13637be1aa | ||
|
|
8f22740e07 | ||
|
|
03d5cc7521 | ||
|
|
c9f9e2b97d | ||
|
|
8ca4ede403 | ||
|
|
b50be86615 | ||
|
|
fe1a8f4425 | ||
|
|
dd472c1322 | ||
|
|
a636adec10 | ||
|
|
e3960445ae | ||
|
|
c631b7cd8a | ||
|
|
bb2bf12808 | ||
|
|
db95dfe208 | ||
|
|
86d052e51e | ||
|
|
fb55b9db17 | ||
|
|
ad3ad81c1e | ||
|
|
dccb84ded8 | ||
|
|
510c693871 | ||
|
|
8696df12ac | ||
|
|
d56e0b0eba | ||
|
|
29d77b2f2c | ||
|
|
4e131cd059 | ||
|
|
4c1f3948a3 | ||
|
|
c40ff67704 | ||
|
|
af6ac8bd4f | ||
|
|
70211a8407 | ||
|
|
4d6b83425b | ||
|
|
985396aaf9 | ||
|
|
d86c14d3a6 | ||
|
|
3bdb3a6b87 | ||
|
|
8dac57d4cf | ||
|
|
a91e7b9ed0 | ||
|
|
220b2c9a2a | ||
|
|
06bc8ed4a4 | ||
|
|
648863d21b | ||
|
|
3232e60467 | ||
|
|
da81ea4e57 | ||
|
|
42baec7c72 | ||
|
|
1accdfe2e6 | ||
|
|
f625653b30 | ||
|
|
2682187fa3 | ||
|
|
090f3fafa9 | ||
|
|
de81ed0c61 | ||
|
|
49465888b2 | ||
|
|
1555185d60 | ||
|
|
e5235bd714 | ||
|
|
1b4fe6135f | ||
|
|
9481b29d6b | ||
|
|
20115e6557 | ||
|
|
ee47136fb4 | ||
|
|
83dece68fc | ||
|
|
fce7083e28 | ||
|
|
5268375153 | ||
|
|
3598f59123 | ||
|
|
557f491a7e | ||
|
|
5aa876da72 | ||
|
|
7e7a66595b | ||
|
|
c429bdf139 | ||
|
|
22d22f3afa | ||
|
|
f5845908b9 | ||
|
|
138ce1c69a | ||
|
|
8366ec5831 | ||
|
|
383f0a7f43 | ||
|
|
22e5a5cafd | ||
|
|
8d6255aa55 | ||
|
|
8fd6f7add9 | ||
|
|
623c2cb9f1 | ||
|
|
259e87442d | ||
|
|
8655e025a2 | ||
|
|
aba2a9f504 | ||
|
|
9aa76bd088 | ||
|
|
10faef62fa | ||
|
|
6b291a5ce5 | ||
|
|
164f1dcfd4 | ||
|
|
b7d6d027d3 | ||
|
|
c4869f1917 | ||
|
|
79c31b5f54 | ||
|
|
89e99219d7 | ||
|
|
a9b6c68ce3 | ||
|
|
0563077fb9 | ||
|
|
e2f174e92e | ||
|
|
861bdb47ed | ||
|
|
9f9e2d12c4 | ||
|
|
03f504cadc | ||
|
|
182c7e827b | ||
|
|
61e0cfc979 | ||
|
|
3ea3f01394 | ||
|
|
fc5b8ca1e5 | ||
|
|
5d67b2f9dc | ||
|
|
bcf4fd9e93 | ||
|
|
5b5faad553 | ||
|
|
5299261d18 | ||
|
|
f852851886 | ||
|
|
20a4d9adb8 | ||
|
|
13997cd282 | ||
|
|
965429296b | ||
|
|
d9750ce4dc | ||
|
|
d0fb41e582 | ||
|
|
f7a83d5a60 | ||
|
|
fc52462df4 | ||
|
|
119804794f | ||
|
|
f23bd0b268 | ||
|
|
d6f61b4faf | ||
|
|
4e4b7a1c39 | ||
|
|
376bfb6799 | ||
|
|
12bdba9a9c | ||
|
|
33fa1e1350 | ||
|
|
94e1a4f793 | ||
|
|
2603d960b7 | ||
|
|
b8433c4ea7 | ||
|
|
fc30aeea61 | ||
|
|
01d6e1f14d | ||
|
|
3b4a65deaa | ||
|
|
2ec5ec78a9 | ||
|
|
6b416b8494 | ||
|
|
eac470e081 | ||
|
|
34ce50b7b5 | ||
|
|
6d85e7cdf7 | ||
|
|
23a47a6f63 | ||
|
|
d2bfcc6f0e | ||
|
|
7495392aa2 | ||
|
|
c4ddf84ba8 | ||
|
|
aad6c28e4d | ||
|
|
2bd03dada4 | ||
|
|
5fab16ad06 | ||
|
|
6a4d1ed44d | ||
|
|
db22159a89 | ||
|
|
029e0e5044 | ||
|
|
3f1ee0b1b8 | ||
|
|
8009794cca | ||
|
|
12ce96d802 | ||
|
|
53bd62b236 | ||
|
|
cd7362c654 | ||
|
|
788b5633cb | ||
|
|
46d106e6e2 | ||
|
|
8ffb91022e | ||
|
|
57c09d1772 | ||
|
|
0731ed2c7a | ||
|
|
19ecb67f2d | ||
|
|
d16123c276 | ||
|
|
f90b168fdd | ||
|
|
09f416efdf | ||
|
|
05f40f3451 | ||
|
|
d81206fe2e | ||
|
|
f166ef9313 | ||
|
|
14704f9b4d | ||
|
|
8381daeeb7 | ||
|
|
164ed75af2 | ||
|
|
1f7c64e279 | ||
|
|
a76bf03bc9 | ||
|
|
e50d7f7b95 | ||
|
|
45b1327c58 | ||
|
|
fe60421731 | ||
|
|
0404fe9044 | ||
|
|
8cf6c59ec7 | ||
|
|
7b817ff866 | ||
|
|
f087f70a2c | ||
|
|
b05752f430 | ||
|
|
c4cde366e8 | ||
|
|
33249fad21 | ||
|
|
f0dd28d4db | ||
|
|
c0e35aa9fa | ||
|
|
1fd633a23b | ||
|
|
9a65e26e71 | ||
|
|
f22cabc32a | ||
|
|
b97d57f00b | ||
|
|
5db3544683 | ||
|
|
96eee95596 | ||
|
|
ffb3243bb6 | ||
|
|
09f07902ef | ||
|
|
43583bbc2e | ||
|
|
2ebc713cbb | ||
|
|
65ecc0f3bb | ||
|
|
ebabc1117e | ||
|
|
672e59e657 | ||
|
|
882e11f558 | ||
|
|
1cd5acb972 | ||
|
|
464a6efd28 | ||
|
|
18c3c1f475 | ||
|
|
52de46aeb3 | ||
|
|
b80d088254 | ||
|
|
7d0d85aeb7 | ||
|
|
d19ef8322e | ||
|
|
840b4d7619 | ||
|
|
e4a36545d7 | ||
|
|
31fbc7389b | ||
|
|
19ec936d38 | ||
|
|
939c67d41c | ||
|
|
9614e4f115 | ||
|
|
c48150a792 | ||
|
|
60687502d1 | ||
|
|
2fab58759e | ||
|
|
a42c586bb2 | ||
|
|
a6b76b3494 | ||
|
|
a6eaf7fc84 | ||
|
|
97ba9b42eb | ||
|
|
e0a71f0373 | ||
|
|
b8875d7f1c | ||
|
|
67dfd9a942 | ||
|
|
db46b03d0c | ||
|
|
5672c86905 | ||
|
|
d5406270a5 | ||
|
|
0b3f5e408b | ||
|
|
2ce432ac77 | ||
|
|
6cb26b3fbb | ||
|
|
a9b5949191 | ||
|
|
6016370515 | ||
|
|
f3c026f278 | ||
|
|
8f218bd6d6 | ||
|
|
59fd89bf68 | ||
|
|
d27a6235f0 | ||
|
|
c23febbcf0 | ||
|
|
81e85a4d0d | ||
|
|
44ba1bc85b | ||
|
|
6244fe5a93 | ||
|
|
973335db56 | ||
|
|
4b2c4f88d3 | ||
|
|
bbd2ca0d68 | ||
|
|
a82c225841 | ||
|
|
f9a6852aaa | ||
|
|
fad704b692 | ||
|
|
e362632477 | ||
|
|
4558b49c1b | ||
|
|
4357d8788a | ||
|
|
78b7c24c15 | ||
|
|
127e9e9f74 | ||
|
|
1951ae1cce | ||
|
|
79e2fd4b52 | ||
|
|
2265a2c43d | ||
|
|
1e7e543ab0 | ||
|
|
9671a73bd6 | ||
|
|
5bbee94d68 | ||
|
|
9d7122d69c | ||
|
|
6b1270a4f9 | ||
|
|
3c8de2be3f | ||
|
|
5afb5f0e83 | ||
|
|
7f42d0df40 | ||
|
|
0df54c9021 | ||
|
|
41bc33f4ba | ||
|
|
dcc883fa27 | ||
|
|
492c5d01bf | ||
|
|
49eaca1290 | ||
|
|
ce43b586ad | ||
|
|
ae49cd6a26 | ||
|
|
6ad3897af8 | ||
|
|
53ddb067ea | ||
|
|
a9762170bc | ||
|
|
4d91403fd2 | ||
|
|
e1cd4a63d0 | ||
|
|
18f3874dab | ||
|
|
6efcee500d | ||
|
|
8c0532f363 | ||
|
|
fdb0d07ab8 | ||
|
|
58e30649a3 | ||
|
|
85feef3a60 | ||
|
|
fccd913a8a | ||
|
|
dd119edafe | ||
|
|
f6633fb16c | ||
|
|
d243bf4f48 | ||
|
|
92d306f777 | ||
|
|
0ea29b3d7c | ||
|
|
c8e6e8eb32 | ||
|
|
a6aae6292e | ||
|
|
e33100b075 | ||
|
|
84a229d286 | ||
|
|
ab32c42487 | ||
|
|
0dc3744859 | ||
|
|
d22eab4155 | ||
|
|
ea9bfec3c9 | ||
|
|
02b43a5d66 | ||
|
|
e0fc7952f4 | ||
|
|
66ec2c5d27 | ||
|
|
f5a78402a6 | ||
|
|
29bfd7325d | ||
|
|
318962c01f | ||
|
|
8ca49fafa1 | ||
|
|
656e783894 | ||
|
|
18c6d60a85 | ||
|
|
b202121c21 | ||
|
|
ea3672dd08 | ||
|
|
88037af7ef | ||
|
|
4bda5b619d | ||
|
|
a0645ea30f | ||
|
|
a3e4adb0af | ||
|
|
e18aedfabf | ||
|
|
44529a78d2 | ||
|
|
bb9025364b | ||
|
|
7c78283b46 | ||
|
|
f7d6ca5c11 | ||
|
|
172a341b40 | ||
|
|
09aef67808 | ||
|
|
a400312d3a | ||
|
|
1b01b35b03 | ||
|
|
2d0acaa8ae | ||
|
|
a31a73320b | ||
|
|
75da352806 | ||
|
|
61b0c9b1c1 | ||
|
|
2185fe0f4c | ||
|
|
4ee0977aa1 | ||
|
|
1ba44771bb | ||
|
|
9966eec1df | ||
|
|
dd444f5f76 | ||
|
|
a0a6089057 | ||
|
|
4be72fc989 | ||
|
|
033cbf696a | ||
|
|
805bc85ea9 | ||
|
|
0d057d500e | ||
|
|
7462500e20 | ||
|
|
3e06a4a7c5 | ||
|
|
e0684ab086 | ||
|
|
e7be883e2e | ||
|
|
8fe80a4507 | ||
|
|
68084c4567 | ||
|
|
9c27545f5f | ||
|
|
6da8af7680 | ||
|
|
1b7ce93623 | ||
|
|
5f6480527e | ||
|
|
4d7b4ce877 | ||
|
|
fd61f7d363 | ||
|
|
47cc3d7358 | ||
|
|
d180618634 | ||
|
|
b2b96426d7 | ||
|
|
5796d4b969 | ||
|
|
37957613df | ||
|
|
cb82f02eb4 | ||
|
|
3feccefee8 | ||
|
|
910b1dca85 | ||
|
|
d71c6f055b | ||
|
|
536f373b91 | ||
|
|
6987845228 | ||
|
|
2edd2bf763 | ||
|
|
2605761d76 | ||
|
|
391d261ca1 | ||
|
|
6a7531f1e6 | ||
|
|
fb294e8bea | ||
|
|
a1046488c3 | ||
|
|
8cef56265c | ||
|
|
ec30851247 | ||
|
|
7420c12b89 | ||
|
|
895c770c24 | ||
|
|
606070f449 | ||
|
|
ec41493d91 | ||
|
|
d551093199 | ||
|
|
f7f8b2da62 | ||
|
|
1378b630a6 | ||
|
|
9726d86ab0 | ||
|
|
c9364e7b94 | ||
|
|
1e6780a2e3 | ||
|
|
72855d4d7a | ||
|
|
c0359da930 | ||
|
|
b4f39b0bfc | ||
|
|
d7af145f3b | ||
|
|
b078d8477e | ||
|
|
02b64e1a4b | ||
|
|
f444825e42 | ||
|
|
9fa62ef388 | ||
|
|
e73ad07836 | ||
|
|
a680e79686 | ||
|
|
728c05262c | ||
|
|
23e08c1ca1 | ||
|
|
198d73acfa | ||
|
|
71e210b66c | ||
|
|
2f31c53fd4 | ||
|
|
9f661535e0 | ||
|
|
5b0d4bf8e6 | ||
|
|
a639264149 | ||
|
|
91ab257eb6 | ||
|
|
e24a62d621 | ||
|
|
ec9f4b2b61 | ||
|
|
b66c7da4b3 | ||
|
|
6544cc98d5 | ||
|
|
2dbef9e1fa | ||
|
|
a924e81adb | ||
|
|
1ded1b603e | ||
|
|
a3012a29c2 | ||
|
|
8fcd800aff | ||
|
|
4d414ea082 | ||
|
|
d5b2380bc2 | ||
|
|
d2853fafa9 | ||
|
|
0e5a207c44 | ||
|
|
d7744537ae | ||
|
|
9e79e9efb6 | ||
|
|
a04338d184 | ||
|
|
772b0ca2b0 | ||
|
|
13eb2b75d5 | ||
|
|
c800440e44 | ||
|
|
05f822380c | ||
|
|
7896c81e98 | ||
|
|
ea50569b2a | ||
|
|
7bce07aa0e | ||
|
|
5ef02290dd | ||
|
|
34d5ba7d35 | ||
|
|
55004e7832 | ||
|
|
4945446171 | ||
|
|
0e2d2408ca | ||
|
|
8b8707c36e | ||
|
|
3bd9caf113 | ||
|
|
f713a83abf | ||
|
|
b0e0f8c8bf | ||
|
|
c8623fd3a2 | ||
|
|
c6aad2c2d4 | ||
|
|
7ede87753b | ||
|
|
59bed5a0fa | ||
|
|
e59377d9a3 | ||
|
|
6274cfce4b | ||
|
|
9d624702f6 | ||
|
|
f9d8ff3f74 | ||
|
|
6c837f0639 | ||
|
|
03c9ce3589 | ||
|
|
1ac7cdacb0 | ||
|
|
ba93be1814 | ||
|
|
1404bbab9f | ||
|
|
a5f8ed6378 | ||
|
|
1b59212003 | ||
|
|
4142901dc6 | ||
|
|
4ba9431e6f | ||
|
|
5da83517a8 | ||
|
|
a7e95c2a4d | ||
|
|
ae7fbbb04f | ||
|
|
cc18ef9aa8 | ||
|
|
4202e8a7ba | ||
|
|
882ff8a325 | ||
|
|
1b29957731 | ||
|
|
5702543bc5 | ||
|
|
c810f0647a | ||
|
|
d366b67bee | ||
|
|
85286b3cf9 | ||
|
|
ae4b5464c7 | ||
|
|
dec2536e3e | ||
|
|
30ea512dcc | ||
|
|
f6cdf34b25 | ||
|
|
99818d038b | ||
|
|
c35ce8e195 | ||
|
|
2ae856b0dd | ||
|
|
e592598990 | ||
|
|
07af34fbd0 | ||
|
|
0b3e313260 | ||
|
|
21947de4e0 | ||
|
|
3cdd0baabb | ||
|
|
f851e62330 | ||
|
|
bea19ad8ce | ||
|
|
f5b48f5390 | ||
|
|
cc712b86d5 | ||
|
|
0cf6cfc2b0 | ||
|
|
6f19360da5 | ||
|
|
f216b4716f | ||
|
|
3bf638f7c6 | ||
|
|
5ec9a24c99 | ||
|
|
23caa1d0b5 | ||
|
|
36ecf7c7fd | ||
|
|
0027e75a45 | ||
|
|
4cd759bfa6 | ||
|
|
0f2752220a | ||
|
|
ce1ed46851 | ||
|
|
aa795ee7eb | ||
|
|
5c83671739 | ||
|
|
3fb9390040 | ||
|
|
965687186c | ||
|
|
83742437d6 | ||
|
|
a37e53769c | ||
|
|
084a389a02 | ||
|
|
7971c42814 | ||
|
|
c694461abc |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,6 +7,9 @@
|
|||||||
# Eclipse project files
|
# Eclipse project files
|
||||||
.classpath
|
.classpath
|
||||||
.project
|
.project
|
||||||
|
.settings
|
||||||
|
maven-eclipse.xml
|
||||||
|
.externalToolBuilders
|
||||||
# Netbeans configuration
|
# Netbeans configuration
|
||||||
nb-configuration.xml
|
nb-configuration.xml
|
||||||
/target/
|
/target/
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ The plugin can be configured using the following:
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-maven</artifactId>
|
<artifactId>dependency-check-maven</artifactId>
|
||||||
<version>1.0.2</version>
|
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<goals>
|
<goals>
|
||||||
@@ -59,7 +58,7 @@ The plugin can be configured using the following:
|
|||||||
|
|
||||||
### Ant Task
|
### Ant Task
|
||||||
|
|
||||||
For instructions on the use of the Ant Task, please see the [dependency-check-ant github page](http://jeremylong.github.io/DependencyCheck/dependency-check-maven/installation.html).
|
For instructions on the use of the Ant Task, please see the [dependency-check-ant github page](http://jeremylong.github.io/DependencyCheck/dependency-check-ant/installation.html).
|
||||||
|
|
||||||
Development Usage
|
Development Usage
|
||||||
-------------
|
-------------
|
||||||
@@ -106,4 +105,4 @@ Dependency-Check makes use of several other open source libraries. Please see th
|
|||||||
[wiki]: https://github.com/jeremylong/DependencyCheck/wiki
|
[wiki]: https://github.com/jeremylong/DependencyCheck/wiki
|
||||||
[subscribe]: mailto:dependency-check+subscribe@googlegroups.com
|
[subscribe]: mailto:dependency-check+subscribe@googlegroups.com
|
||||||
[post]: mailto:dependency-check@googlegroups.com
|
[post]: mailto:dependency-check@googlegroups.com
|
||||||
[notices]: https://github.com/jeremylong/DependencyCheck/blob/master/NOTICES.txt
|
[notices]: https://github.com/jeremylong/DependencyCheck/blob/master/NOTICES.txt
|
||||||
|
|||||||
@@ -15,20 +15,19 @@ limitations under the License.
|
|||||||
|
|
||||||
Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
|
Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-parent</artifactId>
|
<artifactId>dependency-check-parent</artifactId>
|
||||||
<version>1.2.3</version>
|
<version>1.2.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>dependency-check-ant</artifactId>
|
<artifactId>dependency-check-ant</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>Dependency-Check Ant Task</name>
|
<name>Dependency-Check Ant Task</name>
|
||||||
<description>Dependency-check is a utility that attempts to detect publicly disclosed vulnerabilities contained within project dependencies. It does this by determining if there is a Common Platform Enumeration (CPE) identifier for a given dependency. If found, it will generate a report linking to the associated CVE entries.</description>
|
<description>dependency-check-ant is an Ant Task that uses dependency-check-core to detect publicly disclosed vulnerabilities associated with the project's dependencies. The task will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.</description>
|
||||||
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
<site>
|
<site>
|
||||||
@@ -324,6 +323,9 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>2.9.1</version>
|
<version>2.9.1</version>
|
||||||
|
<configuration>
|
||||||
|
<bottom>Copyright© 2012-14 Jeremy Long. All Rights Reserved.</bottom>
|
||||||
|
</configuration>
|
||||||
<reportSets>
|
<reportSets>
|
||||||
<reportSet>
|
<reportSet>
|
||||||
<id>default</id>
|
<id>default</id>
|
||||||
|
|||||||
@@ -559,6 +559,28 @@ public class DependencyCheckTask extends Task {
|
|||||||
public void setNuspecAnalyzerEnabled(boolean nuspecAnalyzerEnabled) {
|
public void setNuspecAnalyzerEnabled(boolean nuspecAnalyzerEnabled) {
|
||||||
this.nuspecAnalyzerEnabled = nuspecAnalyzerEnabled;
|
this.nuspecAnalyzerEnabled = nuspecAnalyzerEnabled;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Whether or not the central analyzer is enabled.
|
||||||
|
*/
|
||||||
|
private boolean centralAnalyzerEnabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of centralAnalyzerEnabled
|
||||||
|
*
|
||||||
|
* @return the value of centralAnalyzerEnabled
|
||||||
|
*/
|
||||||
|
public boolean isCentralAnalyzerEnabled() {
|
||||||
|
return centralAnalyzerEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of centralAnalyzerEnabled
|
||||||
|
*
|
||||||
|
* @param centralAnalyzerEnabled new value of centralAnalyzerEnabled
|
||||||
|
*/
|
||||||
|
public void setCentralAnalyzerEnabled(boolean centralAnalyzerEnabled) {
|
||||||
|
this.centralAnalyzerEnabled = centralAnalyzerEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the nexus analyzer is enabled.
|
* Whether or not the nexus analyzer is enabled.
|
||||||
@@ -1015,6 +1037,8 @@ public class DependencyCheckTask extends Task {
|
|||||||
Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
|
Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
|
||||||
//NUSPEC ANALYZER
|
//NUSPEC ANALYZER
|
||||||
Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
|
Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
|
||||||
|
//CENTRAL ANALYZER
|
||||||
|
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
|
||||||
//NEXUS ANALYZER
|
//NEXUS ANALYZER
|
||||||
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
|
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
|
||||||
if (nexusUrl != null && !nexusUrl.isEmpty()) {
|
if (nexusUrl != null && !nexusUrl.isEmpty()) {
|
||||||
|
|||||||
@@ -46,17 +46,18 @@ Note, that specific analyzers will automatically disable themselves if no file
|
|||||||
types that they support are detected - so specifically disabling them may not
|
types that they support are detected - so specifically disabling them may not
|
||||||
be needed.
|
be needed.
|
||||||
|
|
||||||
Property | Description | Default Value
|
Property | Description | Default Value
|
||||||
------------------------|------------------------------------|------------------
|
------------------------|---------------------------------------------------------------------------|------------------
|
||||||
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
|
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
|
||||||
zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |
|
zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |
|
||||||
jarAnalyzer | Sets whether Jar Analyzer will be used. | true
|
jarAnalyzer | Sets whether the Jar Analyzer will be used. | true
|
||||||
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. | true
|
centralAnalyzerEnabled | Sets whether the Central Analyzer will be used. If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true
|
||||||
nexusUrl | Defines the Nexus URL. | https://repository.sonatype.org/service/local/
|
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. | true
|
||||||
|
nexusUrl | Defines the Nexus Pro URL. If not set the Nexus Analyzer will be disabled. |
|
||||||
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
|
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
|
||||||
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
|
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
|
||||||
assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true
|
assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true
|
||||||
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems |
|
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. |
|
||||||
|
|
||||||
Advanced Configuration
|
Advanced Configuration
|
||||||
====================
|
====================
|
||||||
|
|||||||
@@ -3,7 +3,20 @@ Installation
|
|||||||
Download dependency-check-ant from [bintray here](http://dl.bintray.com/jeremy-long/owasp/dependency-check-ant-${project.version}.jar).
|
Download dependency-check-ant from [bintray here](http://dl.bintray.com/jeremy-long/owasp/dependency-check-ant-${project.version}.jar).
|
||||||
To install dependency-check-ant place the dependency-check-ant-${project.version}.jar into
|
To install dependency-check-ant place the dependency-check-ant-${project.version}.jar into
|
||||||
the lib directory of your Ant instalation directory. Once installed you can add
|
the lib directory of your Ant instalation directory. Once installed you can add
|
||||||
the taskdef to you build.xml and add the task to a new or existing target.
|
the taskdef to you build.xml and add the task to a new or existing target:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask"/>
|
||||||
|
```
|
||||||
|
|
||||||
|
If you do not want to install dependency-check-ant into your ant's lib directory when you define the task def you
|
||||||
|
must add the classpath to the taskdef:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask">
|
||||||
|
<classpath path="[path]/[to]/dependency-check-ant-${project.version}.jar"/>
|
||||||
|
</taskdef>
|
||||||
|
```
|
||||||
|
|
||||||
It is important to understand that the first time this task is executed it may
|
It is important to understand that the first time this task is executed it may
|
||||||
take 20 minutes or more as it downloads and processes the data from the National
|
take 20 minutes or more as it downloads and processes the data from the National
|
||||||
|
|||||||
@@ -1,11 +1,19 @@
|
|||||||
Usage
|
Usage
|
||||||
====================
|
====================
|
||||||
First, add the dependency-check-ant taskdef to your build.xml:
|
First, add the dependency-check-ant taskdef to your build.xml (see the [installation guide](installation.html):
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask"/>
|
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask"/>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Or
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask">
|
||||||
|
<classpath path="[path]/[to]/dependency-check-ant-${project.version}.jar"/>
|
||||||
|
</taskdef>
|
||||||
|
```
|
||||||
|
|
||||||
Next, add the task to a target of your choosing:
|
Next, add the task to a target of your choosing:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
@@ -15,20 +15,19 @@ limitations under the License.
|
|||||||
|
|
||||||
Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
|
Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-parent</artifactId>
|
<artifactId>dependency-check-parent</artifactId>
|
||||||
<version>1.2.3</version>
|
<version>1.2.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>dependency-check-cli</artifactId>
|
<artifactId>dependency-check-cli</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>Dependency-Check Command Line</name>
|
<name>Dependency-Check Command Line</name>
|
||||||
<description>Dependency-Check-Maven is a Maven Plugin that attempts to detect publicly disclosed vulnerabilities contained within project dependencies. It does this by determining if there is a Common Platform Enumeration (CPE) identifier for a given dependency. If found, it will generate a report linking to the associated CVE entries.</description>
|
<description>dependency-check-cli is an command line tool that uses dependency-check-core to detect publicly disclosed vulnerabilities associated with the scanned project dependencies. The tool will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.</description>
|
||||||
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
<site>
|
<site>
|
||||||
@@ -174,6 +173,9 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>2.9.1</version>
|
<version>2.9.1</version>
|
||||||
|
<configuration>
|
||||||
|
<bottom>Copyright© 2012-14 Jeremy Long. All Rights Reserved.</bottom>
|
||||||
|
</configuration>
|
||||||
<reportSets>
|
<reportSets>
|
||||||
<reportSet>
|
<reportSet>
|
||||||
<id>default</id>
|
<id>default</id>
|
||||||
@@ -284,12 +286,12 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>appassembler-maven-plugin</artifactId>
|
<artifactId>appassembler-maven-plugin</artifactId>
|
||||||
<version>1.7</version>
|
<version>1.8.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<programs>
|
<programs>
|
||||||
<program>
|
<program>
|
||||||
<mainClass>org.owasp.dependencycheck.App</mainClass>
|
<mainClass>org.owasp.dependencycheck.App</mainClass>
|
||||||
<name>dependency-check</name>
|
<id>dependency-check</id>
|
||||||
</program>
|
</program>
|
||||||
</programs>
|
</programs>
|
||||||
<assembleDirectory>${project.build.directory}/release</assembleDirectory>
|
<assembleDirectory>${project.build.directory}/release</assembleDirectory>
|
||||||
|
|||||||
@@ -2,10 +2,8 @@
|
|||||||
<assembly
|
<assembly
|
||||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
|
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="
|
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
|
||||||
http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
|
http://maven.apache.org/xsd/assembly-1.1.2.xsd"
|
||||||
http://maven.apache.org/xsd/assembly-1.1.2.xsd
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<id>release</id>
|
<id>release</id>
|
||||||
<formats>
|
<formats>
|
||||||
|
|||||||
@@ -21,15 +21,19 @@ import java.io.File;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.owasp.dependencycheck.cli.CliParser;
|
|
||||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||||
import org.owasp.dependencycheck.dependency.Dependency;
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
|
import org.owasp.dependencycheck.org.apache.tools.ant.DirectoryScanner;
|
||||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||||
import org.owasp.dependencycheck.utils.LogUtils;
|
import org.owasp.dependencycheck.utils.LogUtils;
|
||||||
import org.owasp.dependencycheck.utils.Settings;
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
@@ -93,7 +97,11 @@ public class App {
|
|||||||
cli.printVersionInfo();
|
cli.printVersionInfo();
|
||||||
} else if (cli.isRunScan()) {
|
} else if (cli.isRunScan()) {
|
||||||
populateSettings(cli);
|
populateSettings(cli);
|
||||||
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles());
|
try {
|
||||||
|
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles(), cli.getExcludeList());
|
||||||
|
} catch (InvalidScanPathException ex) {
|
||||||
|
Logger.getLogger(App.class.getName()).log(Level.SEVERE, "An invalid scan path was detected; unable to scan '//*' paths");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cli.printHelp();
|
cli.printHelp();
|
||||||
}
|
}
|
||||||
@@ -106,18 +114,71 @@ public class App {
|
|||||||
* @param outputFormat the output format of the report
|
* @param outputFormat the output format of the report
|
||||||
* @param applicationName the application name for the report
|
* @param applicationName the application name for the report
|
||||||
* @param files the files/directories to scan
|
* @param files the files/directories to scan
|
||||||
|
* @param excludes the patterns for files/directories to exclude
|
||||||
|
*
|
||||||
|
* @throws InvalidScanPathException thrown if the path to scan starts with "//"
|
||||||
*/
|
*/
|
||||||
private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files) {
|
private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
|
||||||
Engine scanner = null;
|
String[] excludes) throws InvalidScanPathException {
|
||||||
|
Engine engine = null;
|
||||||
try {
|
try {
|
||||||
scanner = new Engine();
|
engine = new Engine();
|
||||||
|
List<String> antStylePaths = new ArrayList<String>();
|
||||||
for (String file : files) {
|
if (excludes == null || excludes.length == 0) {
|
||||||
scanner.scan(file);
|
for (String file : files) {
|
||||||
|
if (file.contains("*") || file.contains("?")) {
|
||||||
|
antStylePaths.add(file);
|
||||||
|
} else {
|
||||||
|
engine.scan(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
antStylePaths = Arrays.asList(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
scanner.analyzeDependencies();
|
final Set<File> paths = new HashSet<File>();
|
||||||
final List<Dependency> dependencies = scanner.getDependencies();
|
for (String file : antStylePaths) {
|
||||||
|
final DirectoryScanner scanner = new DirectoryScanner();
|
||||||
|
String include = file.replace('\\', '/');
|
||||||
|
File baseDir;
|
||||||
|
|
||||||
|
if (include.startsWith("//")) {
|
||||||
|
throw new InvalidScanPathException("Unable to scan paths specified by //");
|
||||||
|
} else if (include.startsWith("./")) {
|
||||||
|
baseDir = new File(".");
|
||||||
|
include = include.substring(2);
|
||||||
|
} else if (include.startsWith("/")) {
|
||||||
|
baseDir = new File("/");
|
||||||
|
include = include.substring(1);
|
||||||
|
} else if (include.contains("/")) {
|
||||||
|
final int pos = include.indexOf('/');
|
||||||
|
final String tmp = include.substring(0, pos);
|
||||||
|
if (tmp.contains("*") || tmp.contains("?")) {
|
||||||
|
baseDir = new File(".");
|
||||||
|
} else {
|
||||||
|
baseDir = new File(tmp);
|
||||||
|
include = include.substring(pos + 1);
|
||||||
|
}
|
||||||
|
} else { //no path info - must just be a file in the working directory
|
||||||
|
baseDir = new File(".");
|
||||||
|
}
|
||||||
|
scanner.setBasedir(baseDir);
|
||||||
|
scanner.setIncludes(include);
|
||||||
|
if (excludes != null && excludes.length > 0) {
|
||||||
|
scanner.addExcludes(excludes);
|
||||||
|
}
|
||||||
|
scanner.scan();
|
||||||
|
if (scanner.getIncludedFilesCount() > 0) {
|
||||||
|
for (String s : scanner.getIncludedFiles()) {
|
||||||
|
final File f = new File(baseDir, s);
|
||||||
|
paths.add(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
engine.scan(paths);
|
||||||
|
|
||||||
|
engine.analyzeDependencies();
|
||||||
|
final List<Dependency> dependencies = engine.getDependencies();
|
||||||
DatabaseProperties prop = null;
|
DatabaseProperties prop = null;
|
||||||
CveDB cve = null;
|
CveDB cve = null;
|
||||||
try {
|
try {
|
||||||
@@ -131,7 +192,7 @@ public class App {
|
|||||||
cve.close();
|
cve.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers(), prop);
|
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
|
||||||
try {
|
try {
|
||||||
report.generateReports(reportDirectory, outputFormat);
|
report.generateReports(reportDirectory, outputFormat);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
@@ -145,8 +206,8 @@ public class App {
|
|||||||
LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
|
LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
|
||||||
LOGGER.log(Level.FINE, "", ex);
|
LOGGER.log(Level.FINE, "", ex);
|
||||||
} finally {
|
} finally {
|
||||||
if (scanner != null) {
|
if (engine != null) {
|
||||||
scanner.cleanup();
|
engine.cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,6 +233,7 @@ public class App {
|
|||||||
final boolean archiveDisabled = cli.isArchiveDisabled();
|
final boolean archiveDisabled = cli.isArchiveDisabled();
|
||||||
final boolean assemblyDisabled = cli.isAssemblyDisabled();
|
final boolean assemblyDisabled = cli.isAssemblyDisabled();
|
||||||
final boolean nuspecDisabled = cli.isNuspecDisabled();
|
final boolean nuspecDisabled = cli.isNuspecDisabled();
|
||||||
|
final boolean centralDisabled = cli.isCentralDisabled();
|
||||||
final boolean nexusDisabled = cli.isNexusDisabled();
|
final boolean nexusDisabled = cli.isNexusDisabled();
|
||||||
final String nexusUrl = cli.getNexusUrl();
|
final String nexusUrl = cli.getNexusUrl();
|
||||||
final String databaseDriverName = cli.getDatabaseDriverName();
|
final String databaseDriverName = cli.getDatabaseDriverName();
|
||||||
@@ -237,6 +299,7 @@ public class App {
|
|||||||
Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !nuspecDisabled);
|
Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !nuspecDisabled);
|
||||||
Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !assemblyDisabled);
|
Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !assemblyDisabled);
|
||||||
|
|
||||||
|
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !centralDisabled);
|
||||||
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !nexusDisabled);
|
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !nexusDisabled);
|
||||||
if (nexusUrl != null && !nexusUrl.isEmpty()) {
|
if (nexusUrl != null && !nexusUrl.isEmpty()) {
|
||||||
Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
|
Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.cli;
|
package org.owasp.dependencycheck;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@@ -134,14 +134,36 @@ public final class CliParser {
|
|||||||
* @throws FileNotFoundException is thrown if the path being validated does not exist.
|
* @throws FileNotFoundException is thrown if the path being validated does not exist.
|
||||||
*/
|
*/
|
||||||
private void validatePathExists(String path, String argumentName) throws FileNotFoundException {
|
private void validatePathExists(String path, String argumentName) throws FileNotFoundException {
|
||||||
if (!path.contains("*.")) {
|
if (path == null) {
|
||||||
final File f = new File(path);
|
isValid = false;
|
||||||
if (!f.exists()) {
|
final String msg = String.format("Invalid '%s' argument: null", argumentName);
|
||||||
isValid = false;
|
throw new FileNotFoundException(msg);
|
||||||
final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
|
} else if (!path.contains("*") && !path.contains("?")) {
|
||||||
throw new FileNotFoundException(msg);
|
File f = new File(path);
|
||||||
|
if ("o".equals(argumentName.substring(0, 1).toLowerCase()) && !"ALL".equals(this.getReportFormat().toUpperCase())) {
|
||||||
|
final String checkPath = path.toLowerCase();
|
||||||
|
if (checkPath.endsWith(".html") || checkPath.endsWith(".xml") || checkPath.endsWith(".htm")) {
|
||||||
|
if (f.getParentFile() == null) {
|
||||||
|
f = new File(".", path);
|
||||||
|
}
|
||||||
|
if (!f.getParentFile().isDirectory()) {
|
||||||
|
isValid = false;
|
||||||
|
final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
|
||||||
|
throw new FileNotFoundException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!f.exists()) {
|
||||||
|
isValid = false;
|
||||||
|
final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
|
||||||
|
throw new FileNotFoundException(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // else { // TODO add a validation for *.zip extensions rather then relying on the engine to validate it.
|
} else if (path.startsWith("//") || path.startsWith("\\\\")) {
|
||||||
|
isValid = false;
|
||||||
|
final String msg = String.format("Invalid '%s' argument: '%s'%nUnable to scan paths that start with '//'.", argumentName, path);
|
||||||
|
throw new FileNotFoundException(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,7 +173,6 @@ public final class CliParser {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("static-access")
|
@SuppressWarnings("static-access")
|
||||||
private Options createCommandLineOptions() {
|
private Options createCommandLineOptions() {
|
||||||
|
|
||||||
final Options options = new Options();
|
final Options options = new Options();
|
||||||
addStandardOptions(options);
|
addStandardOptions(options);
|
||||||
addAdvancedOptions(options);
|
addAdvancedOptions(options);
|
||||||
@@ -184,16 +205,22 @@ public final class CliParser {
|
|||||||
.create(ARGUMENT.APP_NAME_SHORT);
|
.create(ARGUMENT.APP_NAME_SHORT);
|
||||||
|
|
||||||
final Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.SCAN)
|
final Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.SCAN)
|
||||||
.withDescription("The path to scan - this option can be specified multiple times. To limit the scan"
|
.withDescription("The path to scan - this option can be specified multiple times. Ant style"
|
||||||
+ " to specific file types *.[ext] can be added to the end of the path.")
|
+ " paths are supported (e.g. path/**/*.jar).")
|
||||||
.create(ARGUMENT.SCAN_SHORT);
|
.create(ARGUMENT.SCAN_SHORT);
|
||||||
|
|
||||||
|
final Option excludes = OptionBuilder.withArgName("pattern").hasArg().withLongOpt(ARGUMENT.EXCLUDE)
|
||||||
|
.withDescription("Specify and exclusion pattern. This option can be specified multiple times"
|
||||||
|
+ " and it accepts Ant style excludsions.")
|
||||||
|
.create();
|
||||||
|
|
||||||
final Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ARGUMENT.PROP)
|
final Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ARGUMENT.PROP)
|
||||||
.withDescription("A property file to load.")
|
.withDescription("A property file to load.")
|
||||||
.create(ARGUMENT.PROP_SHORT);
|
.create(ARGUMENT.PROP_SHORT);
|
||||||
|
|
||||||
final Option out = OptionBuilder.withArgName("folder").hasArg().withLongOpt(ARGUMENT.OUT)
|
final Option out = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.OUT)
|
||||||
.withDescription("The folder to write reports to. This defaults to the current directory.")
|
.withDescription("The folder to write reports to. This defaults to the current directory. "
|
||||||
|
+ "It is possible to set this to a specific file name if the format argument is not set to ALL.")
|
||||||
.create(ARGUMENT.OUT_SHORT);
|
.create(ARGUMENT.OUT_SHORT);
|
||||||
|
|
||||||
final Option outputFormat = OptionBuilder.withArgName("format").hasArg().withLongOpt(ARGUMENT.OUTPUT_FORMAT)
|
final Option outputFormat = OptionBuilder.withArgName("format").hasArg().withLongOpt(ARGUMENT.OUTPUT_FORMAT)
|
||||||
@@ -212,7 +239,11 @@ public final class CliParser {
|
|||||||
final OptionGroup og = new OptionGroup();
|
final OptionGroup og = new OptionGroup();
|
||||||
og.addOption(path);
|
og.addOption(path);
|
||||||
|
|
||||||
|
final OptionGroup exog = new OptionGroup();
|
||||||
|
exog.addOption(excludes);
|
||||||
|
|
||||||
options.addOptionGroup(og)
|
options.addOptionGroup(og)
|
||||||
|
.addOptionGroup(exog)
|
||||||
.addOption(out)
|
.addOption(out)
|
||||||
.addOption(outputFormat)
|
.addOption(outputFormat)
|
||||||
.addOption(appName)
|
.addOption(appName)
|
||||||
@@ -292,12 +323,16 @@ public final class CliParser {
|
|||||||
.withDescription("Disable the .NET Assembly Analyzer.")
|
.withDescription("Disable the .NET Assembly Analyzer.")
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
|
final Option disableCentralAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_CENTRAL)
|
||||||
|
.withDescription("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable the Nexus Analyzer.")
|
||||||
|
.create();
|
||||||
|
|
||||||
final Option disableNexusAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_NEXUS)
|
final Option disableNexusAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_NEXUS)
|
||||||
.withDescription("Disable the Nexus Analyzer.")
|
.withDescription("Disable the Nexus Analyzer.")
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
final Option nexusUrl = OptionBuilder.withArgName("url").hasArg().withLongOpt(ARGUMENT.NEXUS_URL)
|
final Option nexusUrl = OptionBuilder.withArgName("url").hasArg().withLongOpt(ARGUMENT.NEXUS_URL)
|
||||||
.withDescription("The url to the Nexus Server.")
|
.withDescription("The url to the Nexus Pro Server. If not set the Nexus Analyzer will be disabled.")
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
final Option nexusUsesProxy = OptionBuilder.withArgName("true/false").hasArg().withLongOpt(ARGUMENT.NEXUS_USES_PROXY)
|
final Option nexusUsesProxy = OptionBuilder.withArgName("true/false").hasArg().withLongOpt(ARGUMENT.NEXUS_USES_PROXY)
|
||||||
@@ -329,6 +364,7 @@ public final class CliParser {
|
|||||||
.addOption(disableArchiveAnalyzer)
|
.addOption(disableArchiveAnalyzer)
|
||||||
.addOption(disableAssemblyAnalyzer)
|
.addOption(disableAssemblyAnalyzer)
|
||||||
.addOption(disableNuspecAnalyzer)
|
.addOption(disableNuspecAnalyzer)
|
||||||
|
.addOption(disableCentralAnalyzer)
|
||||||
.addOption(disableNexusAnalyzer)
|
.addOption(disableNexusAnalyzer)
|
||||||
.addOption(nexusUrl)
|
.addOption(nexusUrl)
|
||||||
.addOption(nexusUsesProxy)
|
.addOption(nexusUsesProxy)
|
||||||
@@ -425,6 +461,15 @@ public final class CliParser {
|
|||||||
return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
|
return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the disableCentral command line argument was specified.
|
||||||
|
*
|
||||||
|
* @return true if the disableCentral command line argument was specified; otherwise false
|
||||||
|
*/
|
||||||
|
public boolean isCentralDisabled() {
|
||||||
|
return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the url to the nexus server if one was specified.
|
* Returns the url to the nexus server if one was specified.
|
||||||
*
|
*
|
||||||
@@ -479,7 +524,6 @@ public final class CliParser {
|
|||||||
options,
|
options,
|
||||||
"",
|
"",
|
||||||
true);
|
true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -491,6 +535,15 @@ public final class CliParser {
|
|||||||
return line.getOptionValues(ARGUMENT.SCAN);
|
return line.getOptionValues(ARGUMENT.SCAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the list of excluded file patterns specified by the 'exclude' argument.
|
||||||
|
*
|
||||||
|
* @return the excluded file patterns
|
||||||
|
*/
|
||||||
|
public String[] getExcludeList() {
|
||||||
|
return line.getOptionValues(ARGUMENT.EXCLUDE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the directory to write the reports to specified on the command line.
|
* Returns the directory to write the reports to specified on the command line.
|
||||||
*
|
*
|
||||||
@@ -628,8 +681,8 @@ public final class CliParser {
|
|||||||
*/
|
*/
|
||||||
public void printVersionInfo() {
|
public void printVersionInfo() {
|
||||||
final String version = String.format("%s version %s",
|
final String version = String.format("%s version %s",
|
||||||
Settings.getString("application.name", "DependencyCheck"),
|
Settings.getString(Settings.KEYS.APPLICATION_VAME, "dependency-check"),
|
||||||
Settings.getString("application.version", "Unknown"));
|
Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
|
||||||
System.out.println(version);
|
System.out.println(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,6 +890,10 @@ public final class CliParser {
|
|||||||
* Disables the Nuspec Analyzer.
|
* Disables the Nuspec Analyzer.
|
||||||
*/
|
*/
|
||||||
public static final String DISABLE_NUSPEC = "disableNuspec";
|
public static final String DISABLE_NUSPEC = "disableNuspec";
|
||||||
|
/**
|
||||||
|
* Disables the Central Analyzer.
|
||||||
|
*/
|
||||||
|
public static final String DISABLE_CENTRAL = "disableCentral";
|
||||||
/**
|
/**
|
||||||
* Disables the Nexus Analyzer.
|
* Disables the Nexus Analyzer.
|
||||||
*/
|
*/
|
||||||
@@ -877,5 +934,9 @@ public final class CliParser {
|
|||||||
* The CLI argument name for setting extra extensions.
|
* The CLI argument name for setting extra extensions.
|
||||||
*/
|
*/
|
||||||
public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
|
public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
|
||||||
|
/**
|
||||||
|
* Exclude path argument.
|
||||||
|
*/
|
||||||
|
public static final String EXCLUDE = "exclude";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-cli.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown if an invalid path is encountered.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
class InvalidScanPathException extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new InvalidScanPathException.
|
||||||
|
*/
|
||||||
|
public InvalidScanPathException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new InvalidScanPathException.
|
||||||
|
*
|
||||||
|
* @param msg a message for the exception
|
||||||
|
*/
|
||||||
|
public InvalidScanPathException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new InvalidScanPathException.
|
||||||
|
*
|
||||||
|
* @param ex the cause of the exception
|
||||||
|
*/
|
||||||
|
public InvalidScanPathException(Throwable ex) {
|
||||||
|
super(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new InvalidScanPathException.
|
||||||
|
*
|
||||||
|
* @param msg a message for the exception
|
||||||
|
* @param ex the cause of the exception
|
||||||
|
*/
|
||||||
|
public InvalidScanPathException(String msg, Throwable ex) {
|
||||||
|
super(msg, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
/**
|
|
||||||
* <html>
|
|
||||||
* <head>
|
|
||||||
* <title>org.owasp.dependencycheck.cli</title>
|
|
||||||
* </head>
|
|
||||||
* <body>
|
|
||||||
* Includes utility classes such as the CLI Parser,
|
|
||||||
* </body>
|
|
||||||
* </html>
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.owasp.dependencycheck.cli;
|
|
||||||
@@ -6,8 +6,9 @@ The following table lists the command line arguments:
|
|||||||
Short | Argument Name | Parameter | Description | Requirement
|
Short | Argument Name | Parameter | Description | Requirement
|
||||||
-------|-----------------------|-----------------|-------------|------------
|
-------|-----------------------|-----------------|-------------|------------
|
||||||
\-a | \-\-app | \<name\> | The name of the application being scanned. This is a required argument. | Required
|
\-a | \-\-app | \<name\> | The name of the application being scanned. This is a required argument. | Required
|
||||||
\-s | \-\-scan | \<path\> | The path to scan \- this option can be specified multiple times. It is also possible to specify specific file types that should be scanned by supplying a scan path of '[path]/[to]/[scan]/*.zip'. The wild card can only be used to denote any file-name with a specific extension. | Required
|
\-s | \-\-scan | \<path\> | The path to scan \- this option can be specified multiple times. It is also possible to specify Ant style paths (e.g. directory/**/*.jar). | Required
|
||||||
\-o | \-\-out | \<folder\> | The folder to write reports to. This defaults to the current directory. | Optional
|
| \-\-exclude | \<pattern\> | The path patterns to exclude from the scan \- this option can be specified multiple times. This accepts Ant style path patterns (e.g. **/exclude/**) . | Optional
|
||||||
|
\-o | \-\-out | \<path\> | The folder to write reports to. This defaults to the current directory. If the format is not set to ALL one could specify a specific file name. | Optional
|
||||||
\-f | \-\-format | \<format\> | The output format to write to (XML, HTML, VULN, ALL). The default is HTML. | Required
|
\-f | \-\-format | \<format\> | The output format to write to (XML, HTML, VULN, ALL). The default is HTML. | Required
|
||||||
\-l | \-\-log | \<file\> | The file path to write verbose logging information. | Optional
|
\-l | \-\-log | \<file\> | The file path to write verbose logging information. | Optional
|
||||||
\-n | \-\-noupdate | | Disables the automatic updating of the CPE data. | Optional
|
\-n | \-\-noupdate | | Disables the automatic updating of the CPE data. | Optional
|
||||||
@@ -18,26 +19,26 @@ Short | Argument Name | Parameter | Description | Requir
|
|||||||
|
|
||||||
Advanced Options
|
Advanced Options
|
||||||
================
|
================
|
||||||
Short | Argument Name | Parameter | Description | Default Value
|
Short | Argument Name | Parameter | Description | Default Value
|
||||||
-------|-----------------------|-----------------|-------------|---------------
|
-------|-----------------------|-----------------|-----------------------------------------------------------------------------|---------------
|
||||||
| \-\-disableArchive | | Sets whether the Archive Analyzer will be used. | false
|
| \-\-disableArchive | | Sets whether the Archive Analyzer will be used. | false
|
||||||
| \-\-zipExtensions | \<strings\> | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |
|
| \-\-zipExtensions | \<strings\> | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |
|
||||||
| \-\-disableJar | | Sets whether Jar Analyzer will be used. | false
|
| \-\-disableJar | | Sets whether the Jar Analyzer will be used. | false
|
||||||
| \-\-disableNexus | | Sets whether Nexus Analyzer will be used. | false
|
| \-\-disableCentral | | Sets whether the Central Analyzer will be used. If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer. | false
|
||||||
| \-\-disableNexus | | Disable the Nexus Analyzer. |
|
| \-\-disableNexus | | Sets whether the Nexus Analyzer will be used. Note, this has been superceded by the Central Analyzer. However, you can configure the Nexus URL to utilize an internally hosted Nexus Pro server. | false
|
||||||
| \-\-nexus | \<url\> | The url to the Nexus Server. | https://repository.sonatype.org/service/local/
|
| \-\-nexus | \<url\> | The url to the Nexus Pro Server. If not set the Nexus Analyzer will be disabled. |
|
||||||
| \-\-nexusUsesProxy | \<true\|false\> | Whether or not the defined proxy should be used when connecting to Nexus. | true
|
| \-\-nexusUsesProxy | \<true\|false\> | Whether or not the defined proxy should be used when connecting to Nexus. | true
|
||||||
| \-\-disableNuspec | | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | false
|
| \-\-disableNuspec | | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | false
|
||||||
| \-\-disableAssembly | | Sets whether or not the .NET Assembly Analyzer should be used. | false
|
| \-\-disableAssembly | | Sets whether or not the .NET Assembly Analyzer should be used. | false
|
||||||
| \-\-pathToMono | \<path\> | The path to Mono for .NET Assembly analysis on non-windows systems. |
|
| \-\-pathToMono | \<path\> | The path to Mono for .NET Assembly analysis on non-windows systems. |
|
||||||
| \-\-proxyserver | \<server\> | The proxy server to use when downloading resources. |
|
| \-\-proxyserver | \<server\> | The proxy server to use when downloading resources. |
|
||||||
| \-\-proxyport | \<port\> | The proxy port to use when downloading resources. |
|
| \-\-proxyport | \<port\> | The proxy port to use when downloading resources. |
|
||||||
| \-\-connectiontimeout | \<timeout\> | The connection timeout (in milliseconds) to use when downloading resources. |
|
| \-\-connectiontimeout | \<timeout\> | The connection timeout (in milliseconds) to use when downloading resources. |
|
||||||
| \-\-proxypass | \<pass\> | The proxy password to use when downloading resources. |
|
| \-\-proxypass | \<pass\> | The proxy password to use when downloading resources. |
|
||||||
| \-\-proxyuser | \<user\> | The proxy username to use when downloading resources. |
|
| \-\-proxyuser | \<user\> | The proxy username to use when downloading resources. |
|
||||||
| \-\-connectionString | \<connStr\> | The connection string to the database. |
|
| \-\-connectionString | \<connStr\> | The connection string to the database. |
|
||||||
| \-\-dbDriverName | \<driver\> | The database driver name. |
|
| \-\-dbDriverName | \<driver\> | The database driver name. |
|
||||||
| \-\-dbDriverPath | \<path\> | The path to the database driver; note, this does not need to be set unless the JAR is outside of the class path. |
|
| \-\-dbDriverPath | \<path\> | The path to the database driver; note, this does not need to be set unless the JAR is outside of the class path. |
|
||||||
| \-\-dbPassword | \<password\> | The password for connecting to the database. |
|
| \-\-dbPassword | \<password\> | The password for connecting to the database. |
|
||||||
| \-\-dbUser | \<user\> | The username used to connect to the database. |
|
| \-\-dbUser | \<user\> | The username used to connect to the database. |
|
||||||
\-d | \-\-data | \<path\> | The location of the data directory used to store persistent data. This option should generally not be set. |
|
\-d | \-\-data | \<path\> | The location of the data directory used to store persistent data. This option should generally not be set. |
|
||||||
|
|||||||
@@ -15,8 +15,9 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.cli;
|
package org.owasp.dependencycheck;
|
||||||
|
|
||||||
|
import org.owasp.dependencycheck.CliParser;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@@ -20,13 +20,14 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-parent</artifactId>
|
<artifactId>dependency-check-parent</artifactId>
|
||||||
<version>1.2.3</version>
|
<version>1.2.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>dependency-check-core</artifactId>
|
<artifactId>dependency-check-core</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>Dependency-Check Core</name>
|
<name>Dependency-Check Core</name>
|
||||||
|
<description>dependency-check-core is the engine and reporting tool used to identify and report if there are any known, publicly disclosed vulnerabilities in the scanned project's dependencies. The engine extracts meta-data from the dependencies and uses this to do fuzzy key-word matching against the Common Platfrom Enumeration (CPE), if any CPE identifiers are found the associated Common Vulnerability and Exposure (CVE) entries are added to the generated report.</description>
|
||||||
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
<site>
|
<site>
|
||||||
@@ -271,6 +272,9 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>2.9.1</version>
|
<version>2.9.1</version>
|
||||||
|
<configuration>
|
||||||
|
<bottom>Copyright© 2012-14 Jeremy Long. All Rights Reserved.</bottom>
|
||||||
|
</configuration>
|
||||||
<reportSets>
|
<reportSets>
|
||||||
<reportSet>
|
<reportSet>
|
||||||
<id>default</id>
|
<id>default</id>
|
||||||
@@ -396,6 +400,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
<version>3.1</version>
|
<version>3.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<showDeprecation>false</showDeprecation>
|
<showDeprecation>false</showDeprecation>
|
||||||
|
<compilerArgument>-Xlint:unchecked</compilerArgument>
|
||||||
<source>1.6</source>
|
<source>1.6</source>
|
||||||
<target>1.6</target>
|
<target>1.6</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -414,6 +419,12 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
<version>4.3.1</version>
|
<version>4.3.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jmockit</groupId>
|
||||||
|
<artifactId>jmockit</artifactId>
|
||||||
|
<version>1.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.findbugs</groupId>
|
<groupId>com.google.code.findbugs</groupId>
|
||||||
<artifactId>annotations</artifactId>
|
<artifactId>annotations</artifactId>
|
||||||
@@ -428,7 +439,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-compress</artifactId>
|
<artifactId>commons-compress</artifactId>
|
||||||
<version>1.8</version>
|
<version>1.8.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-io</groupId>
|
<groupId>commons-io</groupId>
|
||||||
@@ -460,50 +471,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
<artifactId>velocity</artifactId>
|
<artifactId>velocity</artifactId>
|
||||||
<version>1.7</version>
|
<version>1.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.velocity</groupId>
|
|
||||||
<artifactId>velocity-tools</artifactId>
|
|
||||||
<version>2.0</version>
|
|
||||||
<!-- very limited use of the velocity-tools, not all of the dependencies are needed-->
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>commons-chain</groupId>
|
|
||||||
<artifactId>commons-chain</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>javax.servlet</groupId>
|
|
||||||
<artifactId>servlet-api</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>commons-validator</groupId>
|
|
||||||
<artifactId>commons-validator</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>dom4j</groupId>
|
|
||||||
<artifactId>dom4j</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>sslext</groupId>
|
|
||||||
<artifactId>sslext</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.apache.struts</groupId>
|
|
||||||
<artifactId>struts-core</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>antlr</groupId>
|
|
||||||
<artifactId>antlr</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.apache.struts</groupId>
|
|
||||||
<artifactId>struts-taglib</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.apache.struts</groupId>
|
|
||||||
<artifactId>struts-tiles</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
@@ -617,6 +584,13 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.retry</groupId>
|
||||||
|
<artifactId>spring-retry</artifactId>
|
||||||
|
<version>1.1.0.RELEASE</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
@@ -733,6 +707,28 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish.jersey.core</groupId>
|
||||||
|
<artifactId>jersey-client</artifactId>
|
||||||
|
<version>2.12</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sun.jersey</groupId>
|
||||||
|
<artifactId>jersey-client</artifactId>
|
||||||
|
<version>1.11.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sun.faces</groupId>
|
||||||
|
<artifactId>jsf-impl</artifactId>
|
||||||
|
<version>2.2.8-02</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</profile>
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ import org.owasp.dependencycheck.analyzer.Analyzer;
|
|||||||
import org.owasp.dependencycheck.analyzer.AnalyzerService;
|
import org.owasp.dependencycheck.analyzer.AnalyzerService;
|
||||||
import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
|
import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
|
||||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex;
|
|
||||||
import org.owasp.dependencycheck.data.cpe.IndexException;
|
|
||||||
import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory;
|
import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
@@ -57,19 +55,21 @@ public class Engine {
|
|||||||
/**
|
/**
|
||||||
* The list of dependencies.
|
* The list of dependencies.
|
||||||
*/
|
*/
|
||||||
private List<Dependency> dependencies;
|
private List<Dependency> dependencies = new ArrayList<Dependency>();
|
||||||
/**
|
/**
|
||||||
* A Map of analyzers grouped by Analysis phase.
|
* A Map of analyzers grouped by Analysis phase.
|
||||||
*/
|
*/
|
||||||
private final EnumMap<AnalysisPhase, List<Analyzer>> analyzers;
|
private EnumMap<AnalysisPhase, List<Analyzer>> analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Map of analyzers grouped by Analysis phase.
|
* A Map of analyzers grouped by Analysis phase.
|
||||||
*/
|
*/
|
||||||
private final Set<FileTypeAnalyzer> fileTypeAnalyzers;
|
private Set<FileTypeAnalyzer> fileTypeAnalyzers = new HashSet<FileTypeAnalyzer>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ClassLoader to use when dynamically loading Analyzer and Update services.
|
* The ClassLoader to use when dynamically loading Analyzer and Update services.
|
||||||
*/
|
*/
|
||||||
private ClassLoader serviceClassLoader;
|
private ClassLoader serviceClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
/**
|
/**
|
||||||
* The Logger for use throughout the class.
|
* The Logger for use throughout the class.
|
||||||
*/
|
*/
|
||||||
@@ -81,32 +81,27 @@ public class Engine {
|
|||||||
* @throws DatabaseException thrown if there is an error connecting to the database
|
* @throws DatabaseException thrown if there is an error connecting to the database
|
||||||
*/
|
*/
|
||||||
public Engine() throws DatabaseException {
|
public Engine() throws DatabaseException {
|
||||||
this(Thread.currentThread().getContextClassLoader());
|
initializeEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Engine.
|
||||||
|
*
|
||||||
|
* @param serviceClassLoader a reference the class loader being used
|
||||||
|
* @throws DatabaseException thrown if there is an error connecting to the database
|
||||||
|
*/
|
||||||
|
public Engine(ClassLoader serviceClassLoader) throws DatabaseException {
|
||||||
|
this.serviceClassLoader = serviceClassLoader;
|
||||||
|
initializeEngine();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Engine using the specified classloader to dynamically load Analyzer and Update services.
|
* Creates a new Engine using the specified classloader to dynamically load Analyzer and Update services.
|
||||||
*
|
*
|
||||||
* @param serviceClassLoader the ClassLoader to use when dynamically loading Analyzer and Update services
|
|
||||||
* @throws DatabaseException thrown if there is an error connecting to the database
|
* @throws DatabaseException thrown if there is an error connecting to the database
|
||||||
*/
|
*/
|
||||||
public Engine(ClassLoader serviceClassLoader) throws DatabaseException {
|
protected final void initializeEngine() throws DatabaseException {
|
||||||
this.dependencies = new ArrayList<Dependency>();
|
|
||||||
this.analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class);
|
|
||||||
this.fileTypeAnalyzers = new HashSet<FileTypeAnalyzer>();
|
|
||||||
this.serviceClassLoader = serviceClassLoader;
|
|
||||||
|
|
||||||
ConnectionFactory.initialize();
|
ConnectionFactory.initialize();
|
||||||
|
|
||||||
boolean autoUpdate = true;
|
|
||||||
try {
|
|
||||||
autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
|
|
||||||
} catch (InvalidSettingException ex) {
|
|
||||||
LOGGER.log(Level.FINE, "Invalid setting for auto-update; using true.");
|
|
||||||
}
|
|
||||||
if (autoUpdate) {
|
|
||||||
doUpdates();
|
|
||||||
}
|
|
||||||
loadAnalyzers();
|
loadAnalyzers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +116,9 @@ public class Engine {
|
|||||||
* Loads the analyzers specified in the configuration file (or system properties).
|
* Loads the analyzers specified in the configuration file (or system properties).
|
||||||
*/
|
*/
|
||||||
private void loadAnalyzers() {
|
private void loadAnalyzers() {
|
||||||
|
if (analyzers.size() > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (AnalysisPhase phase : AnalysisPhase.values()) {
|
for (AnalysisPhase phase : AnalysisPhase.values()) {
|
||||||
analyzers.put(phase, new ArrayList<Analyzer>());
|
analyzers.put(phase, new ArrayList<Analyzer>());
|
||||||
}
|
}
|
||||||
@@ -156,159 +153,200 @@ public class Engine {
|
|||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the dependencies.
|
||||||
|
*
|
||||||
|
* @param dependencies the dependencies
|
||||||
|
*/
|
||||||
public void setDependencies(List<Dependency> dependencies) {
|
public void setDependencies(List<Dependency> dependencies) {
|
||||||
this.dependencies = dependencies;
|
this.dependencies = dependencies;
|
||||||
//for (Dependency dependency: dependencies) {
|
|
||||||
// dependencies.add(dependency);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any
|
* Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any
|
||||||
* dependencies identified are added to the dependency collection.
|
* dependencies identified are added to the dependency collection.
|
||||||
*
|
*
|
||||||
* @since v0.3.2.5
|
* @param paths an array of paths to files or directories to be analyzed
|
||||||
|
* @return the list of dependencies scanned
|
||||||
*
|
*
|
||||||
* @param paths an array of paths to files or directories to be analyzed.
|
* @since v0.3.2.5
|
||||||
*/
|
*/
|
||||||
public void scan(String[] paths) {
|
public List<Dependency> scan(String[] paths) {
|
||||||
|
final List<Dependency> deps = new ArrayList<Dependency>();
|
||||||
for (String path : paths) {
|
for (String path : paths) {
|
||||||
final File file = new File(path);
|
final File file = new File(path);
|
||||||
scan(file);
|
final List<Dependency> d = scan(file);
|
||||||
|
if (d != null) {
|
||||||
|
deps.addAll(d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return deps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies
|
* Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies
|
||||||
* identified are added to the dependency collection.
|
* identified are added to the dependency collection.
|
||||||
*
|
*
|
||||||
* @param path the path to a file or directory to be analyzed.
|
* @param path the path to a file or directory to be analyzed
|
||||||
|
* @return the list of dependencies scanned
|
||||||
*/
|
*/
|
||||||
public void scan(String path) {
|
public List<Dependency> scan(String path) {
|
||||||
if (path.matches("^.*[\\/]\\*\\.[^\\/:*|?<>\"]+$")) {
|
final File file = new File(path);
|
||||||
final String[] parts = path.split("\\*\\.");
|
return scan(file);
|
||||||
final String[] ext = new String[]{parts[parts.length - 1]};
|
|
||||||
final File dir = new File(path.substring(0, path.length() - ext[0].length() - 2));
|
|
||||||
if (dir.isDirectory()) {
|
|
||||||
final List<File> files = (List<File>) org.apache.commons.io.FileUtils.listFiles(dir, ext, true);
|
|
||||||
scan(files);
|
|
||||||
} else {
|
|
||||||
final String msg = String.format("Invalid file path provided to scan '%s'", path);
|
|
||||||
LOGGER.log(Level.SEVERE, msg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final File file = new File(path);
|
|
||||||
scan(file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any
|
* Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any
|
||||||
* dependencies identified are added to the dependency collection.
|
* dependencies identified are added to the dependency collection.
|
||||||
*
|
*
|
||||||
* @since v0.3.2.5
|
|
||||||
*
|
|
||||||
* @param files an array of paths to files or directories to be analyzed.
|
* @param files an array of paths to files or directories to be analyzed.
|
||||||
|
* @return the list of dependencies
|
||||||
|
*
|
||||||
|
* @since v0.3.2.5
|
||||||
*/
|
*/
|
||||||
public void scan(File[] files) {
|
public List<Dependency> scan(File[] files) {
|
||||||
|
final List<Dependency> deps = new ArrayList<Dependency>();
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
scan(file);
|
final List<Dependency> d = scan(file);
|
||||||
|
if (d != null) {
|
||||||
|
deps.addAll(d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return deps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any
|
* Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any
|
||||||
* dependencies identified are added to the dependency collection.
|
* dependencies identified are added to the dependency collection.
|
||||||
*
|
*
|
||||||
* @since v0.3.2.5
|
* @param files a set of paths to files or directories to be analyzed
|
||||||
|
* @return the list of dependencies scanned
|
||||||
*
|
*
|
||||||
* @param files a set of paths to files or directories to be analyzed.
|
* @since v0.3.2.5
|
||||||
*/
|
*/
|
||||||
public void scan(Set<File> files) {
|
public List<Dependency> scan(Set<File> files) {
|
||||||
|
final List<Dependency> deps = new ArrayList<Dependency>();
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
scan(file);
|
final List<Dependency> d = scan(file);
|
||||||
|
if (d != null) {
|
||||||
|
deps.addAll(d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return deps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any
|
* Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any
|
||||||
* dependencies identified are added to the dependency collection.
|
* dependencies identified are added to the dependency collection.
|
||||||
*
|
*
|
||||||
* @since v0.3.2.5
|
* @param files a set of paths to files or directories to be analyzed
|
||||||
|
* @return the list of dependencies scanned
|
||||||
*
|
*
|
||||||
* @param files a set of paths to files or directories to be analyzed.
|
* @since v0.3.2.5
|
||||||
*/
|
*/
|
||||||
public void scan(List<File> files) {
|
public List<Dependency> scan(List<File> files) {
|
||||||
|
final List<Dependency> deps = new ArrayList<Dependency>();
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
scan(file);
|
final List<Dependency> d = scan(file);
|
||||||
|
if (d != null) {
|
||||||
|
deps.addAll(d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return deps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies
|
* Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies
|
||||||
* identified are added to the dependency collection.
|
* identified are added to the dependency collection.
|
||||||
*
|
*
|
||||||
|
* @param file the path to a file or directory to be analyzed
|
||||||
|
* @return the list of dependencies scanned
|
||||||
|
*
|
||||||
* @since v0.3.2.4
|
* @since v0.3.2.4
|
||||||
*
|
*
|
||||||
* @param file the path to a file or directory to be analyzed.
|
|
||||||
*/
|
*/
|
||||||
public void scan(File file) {
|
public List<Dependency> scan(File file) {
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
scanDirectory(file);
|
return scanDirectory(file);
|
||||||
} else {
|
} else {
|
||||||
scanFile(file);
|
final Dependency d = scanFile(file);
|
||||||
|
if (d != null) {
|
||||||
|
final List<Dependency> deps = new ArrayList<Dependency>();
|
||||||
|
deps.add(d);
|
||||||
|
return deps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively scans files and directories. Any dependencies identified are added to the dependency collection.
|
* Recursively scans files and directories. Any dependencies identified are added to the dependency collection.
|
||||||
*
|
*
|
||||||
* @param dir the directory to scan.
|
* @param dir the directory to scan
|
||||||
|
* @return the list of Dependency objects scanned
|
||||||
*/
|
*/
|
||||||
protected void scanDirectory(File dir) {
|
protected List<Dependency> scanDirectory(File dir) {
|
||||||
final File[] files = dir.listFiles();
|
final File[] files = dir.listFiles();
|
||||||
|
final List<Dependency> deps = new ArrayList<Dependency>();
|
||||||
if (files != null) {
|
if (files != null) {
|
||||||
for (File f : files) {
|
for (File f : files) {
|
||||||
if (f.isDirectory()) {
|
if (f.isDirectory()) {
|
||||||
scanDirectory(f);
|
final List<Dependency> d = scanDirectory(f);
|
||||||
|
if (d != null) {
|
||||||
|
deps.addAll(d);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
scanFile(f);
|
final Dependency d = scanFile(f);
|
||||||
|
deps.add(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return deps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans a specified file. If a dependency is identified it is added to the dependency collection.
|
* Scans a specified file. If a dependency is identified it is added to the dependency collection.
|
||||||
*
|
*
|
||||||
* @param file The file to scan.
|
* @param file The file to scan
|
||||||
|
* @return the scanned dependency
|
||||||
*/
|
*/
|
||||||
protected void scanFile(File file) {
|
protected Dependency scanFile(File file) {
|
||||||
if (!file.isFile()) {
|
if (!file.isFile()) {
|
||||||
final String msg = String.format("Path passed to scanFile(File) is not a file: %s. Skipping the file.", file.toString());
|
final String msg = String.format("Path passed to scanFile(File) is not a file: %s. Skipping the file.", file.toString());
|
||||||
LOGGER.log(Level.FINE, msg);
|
LOGGER.log(Level.FINE, msg);
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
final String fileName = file.getName();
|
final String fileName = file.getName();
|
||||||
final String extension = FileUtils.getFileExtension(fileName);
|
final String extension = FileUtils.getFileExtension(fileName);
|
||||||
|
Dependency dependency = null;
|
||||||
if (extension != null) {
|
if (extension != null) {
|
||||||
if (supportsExtension(extension)) {
|
if (supportsExtension(extension)) {
|
||||||
final Dependency dependency = new Dependency(file);
|
dependency = new Dependency(file);
|
||||||
dependencies.add(dependency);
|
dependencies.add(dependency);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final String msg = String.format("No file extension found on file '%s'. The file was not analyzed.",
|
final String msg = String.format("No file extension found on file '%s'. The file was not analyzed.", file.toString());
|
||||||
file.toString());
|
LOGGER.log(Level.FINE, msg);
|
||||||
LOGGER.log(Level.FINEST, msg);
|
|
||||||
}
|
}
|
||||||
|
return dependency;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the analyzers against all of the dependencies.
|
* Runs the analyzers against all of the dependencies.
|
||||||
*/
|
*/
|
||||||
public void analyzeDependencies() {
|
public void analyzeDependencies() {
|
||||||
|
boolean autoUpdate = true;
|
||||||
|
try {
|
||||||
|
autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
|
||||||
|
} catch (InvalidSettingException ex) {
|
||||||
|
LOGGER.log(Level.FINE, "Invalid setting for auto-update; using true.");
|
||||||
|
}
|
||||||
|
if (autoUpdate) {
|
||||||
|
doUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
//need to ensure that data exists
|
//need to ensure that data exists
|
||||||
try {
|
try {
|
||||||
ensureDataExists();
|
ensureDataExists();
|
||||||
@@ -337,7 +375,7 @@ public class Engine {
|
|||||||
final List<Analyzer> analyzerList = analyzers.get(phase);
|
final List<Analyzer> analyzerList = analyzers.get(phase);
|
||||||
|
|
||||||
for (Analyzer a : analyzerList) {
|
for (Analyzer a : analyzerList) {
|
||||||
initializeAnalyzer(a);
|
a = initializeAnalyzer(a);
|
||||||
|
|
||||||
/* need to create a copy of the collection because some of the
|
/* need to create a copy of the collection because some of the
|
||||||
* analyzers may modify it. This prevents ConcurrentModificationExceptions.
|
* analyzers may modify it. This prevents ConcurrentModificationExceptions.
|
||||||
@@ -392,8 +430,9 @@ public class Engine {
|
|||||||
* Initializes the given analyzer.
|
* Initializes the given analyzer.
|
||||||
*
|
*
|
||||||
* @param analyzer the analyzer to initialize
|
* @param analyzer the analyzer to initialize
|
||||||
|
* @return the initialized analyzer
|
||||||
*/
|
*/
|
||||||
private void initializeAnalyzer(Analyzer analyzer) {
|
protected Analyzer initializeAnalyzer(Analyzer analyzer) {
|
||||||
try {
|
try {
|
||||||
final String msg = String.format("Initializing %s", analyzer.getName());
|
final String msg = String.format("Initializing %s", analyzer.getName());
|
||||||
LOGGER.log(Level.FINE, msg);
|
LOGGER.log(Level.FINE, msg);
|
||||||
@@ -408,6 +447,7 @@ public class Engine {
|
|||||||
LOGGER.log(Level.FINEST, null, ex1);
|
LOGGER.log(Level.FINEST, null, ex1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return analyzer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -415,7 +455,7 @@ public class Engine {
|
|||||||
*
|
*
|
||||||
* @param analyzer the analyzer to close
|
* @param analyzer the analyzer to close
|
||||||
*/
|
*/
|
||||||
private void closeAnalyzer(Analyzer analyzer) {
|
protected void closeAnalyzer(Analyzer analyzer) {
|
||||||
final String msg = String.format("Closing Analyzer '%s'", analyzer.getName());
|
final String msg = String.format("Closing Analyzer '%s'", analyzer.getName());
|
||||||
LOGGER.log(Level.FINE, msg);
|
LOGGER.log(Level.FINE, msg);
|
||||||
try {
|
try {
|
||||||
@@ -429,6 +469,7 @@ public class Engine {
|
|||||||
* Cycles through the cached web data sources and calls update on all of them.
|
* Cycles through the cached web data sources and calls update on all of them.
|
||||||
*/
|
*/
|
||||||
private void doUpdates() {
|
private void doUpdates() {
|
||||||
|
LOGGER.info("Checking for updates");
|
||||||
final UpdateService service = new UpdateService(serviceClassLoader);
|
final UpdateService service = new UpdateService(serviceClassLoader);
|
||||||
final Iterator<CachedWebDataSource> iterator = service.getDataSources();
|
final Iterator<CachedWebDataSource> iterator = service.getDataSources();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
@@ -438,10 +479,10 @@ public class Engine {
|
|||||||
} catch (UpdateException ex) {
|
} catch (UpdateException ex) {
|
||||||
LOGGER.log(Level.WARNING,
|
LOGGER.log(Level.WARNING,
|
||||||
"Unable to update Cached Web DataSource, using local data instead. Results may not include recent vulnerabilities.");
|
"Unable to update Cached Web DataSource, using local data instead. Results may not include recent vulnerabilities.");
|
||||||
LOGGER.log(Level.FINE,
|
LOGGER.log(Level.FINE, String.format("Unable to update details for %s", source.getClass().getName()), ex);
|
||||||
String.format("Unable to update details for %s", source.getClass().getName()), ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LOGGER.info("Check for updates complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -477,6 +518,15 @@ public class Engine {
|
|||||||
return scan;
|
return scan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the set of file type analyzers.
|
||||||
|
*
|
||||||
|
* @return the set of file type analyzers
|
||||||
|
*/
|
||||||
|
public Set<FileTypeAnalyzer> getFileTypeAnalyzers() {
|
||||||
|
return this.fileTypeAnalyzers;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the CPE Index to ensure documents exists. If none exist a NoDataException is thrown.
|
* Checks the CPE Index to ensure documents exists. If none exist a NoDataException is thrown.
|
||||||
*
|
*
|
||||||
@@ -484,22 +534,16 @@ public class Engine {
|
|||||||
* @throws DatabaseException thrown if there is an exception opening the database
|
* @throws DatabaseException thrown if there is an exception opening the database
|
||||||
*/
|
*/
|
||||||
private void ensureDataExists() throws NoDataException, DatabaseException {
|
private void ensureDataExists() throws NoDataException, DatabaseException {
|
||||||
final CpeMemoryIndex cpe = CpeMemoryIndex.getInstance();
|
|
||||||
final CveDB cve = new CveDB();
|
final CveDB cve = new CveDB();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cve.open();
|
cve.open();
|
||||||
cpe.open(cve);
|
if (!cve.dataExists()) {
|
||||||
} catch (IndexException ex) {
|
throw new NoDataException("No documents exist");
|
||||||
throw new NoDataException(ex.getMessage(), ex);
|
}
|
||||||
} catch (DatabaseException ex) {
|
} catch (DatabaseException ex) {
|
||||||
throw new NoDataException(ex.getMessage(), ex);
|
throw new NoDataException(ex.getMessage(), ex);
|
||||||
} finally {
|
} finally {
|
||||||
cve.close();
|
cve.close();
|
||||||
}
|
}
|
||||||
if (cpe.numDocs() <= 0) {
|
|
||||||
cpe.close();
|
|
||||||
throw new NoDataException("No documents exist");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -440,6 +440,52 @@ public class DependencyCheckScanAgent {
|
|||||||
this.showSummary = showSummary;
|
this.showSummary = showSummary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the Maven Central analyzer is enabled.
|
||||||
|
*/
|
||||||
|
private boolean centralAnalyzerEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of centralAnalyzerEnabled.
|
||||||
|
*
|
||||||
|
* @return the value of centralAnalyzerEnabled
|
||||||
|
*/
|
||||||
|
public boolean isCentralAnalyzerEnabled() {
|
||||||
|
return centralAnalyzerEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of centralAnalyzerEnabled.
|
||||||
|
*
|
||||||
|
* @param centralAnalyzerEnabled new value of centralAnalyzerEnabled
|
||||||
|
*/
|
||||||
|
public void setCentralAnalyzerEnabled(boolean centralAnalyzerEnabled) {
|
||||||
|
this.centralAnalyzerEnabled = centralAnalyzerEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of Maven Central.
|
||||||
|
*/
|
||||||
|
private String centralUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of centralUrl.
|
||||||
|
*
|
||||||
|
* @return the value of centralUrl
|
||||||
|
*/
|
||||||
|
public String getCentralUrl() {
|
||||||
|
return centralUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of centralUrl.
|
||||||
|
*
|
||||||
|
* @param centralUrl new value of centralUrl
|
||||||
|
*/
|
||||||
|
public void setCentralUrl(String centralUrl) {
|
||||||
|
this.centralUrl = centralUrl;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the nexus analyzer is enabled.
|
* Whether or not the nexus analyzer is enabled.
|
||||||
*/
|
*/
|
||||||
@@ -849,6 +895,10 @@ public class DependencyCheckScanAgent {
|
|||||||
if (suppressionFile != null && !suppressionFile.isEmpty()) {
|
if (suppressionFile != null && !suppressionFile.isEmpty()) {
|
||||||
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
|
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
|
||||||
}
|
}
|
||||||
|
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
|
||||||
|
if (centralUrl != null && !centralUrl.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.ANALYZER_CENTRAL_URL, centralUrl);
|
||||||
|
}
|
||||||
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
|
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
|
||||||
if (nexusUrl != null && !nexusUrl.isEmpty()) {
|
if (nexusUrl != null && !nexusUrl.isEmpty()) {
|
||||||
Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
|
Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
|
||||||
|
|||||||
@@ -41,16 +41,7 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
|
|||||||
* enabled.
|
* enabled.
|
||||||
*/
|
*/
|
||||||
public AbstractFileTypeAnalyzer() {
|
public AbstractFileTypeAnalyzer() {
|
||||||
final String key = getAnalyzerEnabledSettingKey();
|
reset();
|
||||||
try {
|
|
||||||
enabled = Settings.getBoolean(key, true);
|
|
||||||
} catch (InvalidSettingException ex) {
|
|
||||||
String msg = String.format("Invalid setting for property '%s'", key);
|
|
||||||
LOGGER.log(Level.WARNING, msg);
|
|
||||||
LOGGER.log(Level.FINE, "", ex);
|
|
||||||
msg = String.format("%s has been disabled", getName());
|
|
||||||
LOGGER.log(Level.WARNING, msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
@@ -164,6 +155,23 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the enabled flag on the analyzer.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final void reset() {
|
||||||
|
final String key = getAnalyzerEnabledSettingKey();
|
||||||
|
try {
|
||||||
|
enabled = Settings.getBoolean(key, true);
|
||||||
|
} catch (InvalidSettingException ex) {
|
||||||
|
String msg = String.format("Invalid setting for property '%s'", key);
|
||||||
|
LOGGER.log(Level.WARNING, msg);
|
||||||
|
LOGGER.log(Level.FINE, "", ex);
|
||||||
|
msg = String.format("%s has been disabled", getName());
|
||||||
|
LOGGER.log(Level.WARNING, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted,
|
* Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted,
|
||||||
* scanned, and added to the list of dependencies within the engine.
|
* scanned, and added to the list of dependencies within the engine.
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
static {
|
static {
|
||||||
final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
|
final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
|
||||||
if (additionalZipExt != null) {
|
if (additionalZipExt != null) {
|
||||||
final HashSet ext = new HashSet<String>(Arrays.asList(additionalZipExt));
|
final HashSet<String> ext = new HashSet<String>(Arrays.asList(additionalZipExt));
|
||||||
ZIPPABLES.addAll(ext);
|
ZIPPABLES.addAll(ext);
|
||||||
}
|
}
|
||||||
EXTENSIONS.addAll(ZIPPABLES);
|
EXTENSIONS.addAll(ZIPPABLES);
|
||||||
@@ -186,7 +186,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
if (tempFileLocation != null && tempFileLocation.exists()) {
|
if (tempFileLocation != null && tempFileLocation.exists()) {
|
||||||
LOGGER.log(Level.FINE, "Attempting to delete temporary files");
|
LOGGER.log(Level.FINE, "Attempting to delete temporary files");
|
||||||
final boolean success = FileUtils.delete(tempFileLocation);
|
final boolean success = FileUtils.delete(tempFileLocation);
|
||||||
if (!success && tempFileLocation != null & tempFileLocation.exists()) {
|
if (!success && tempFileLocation != null && tempFileLocation.exists() && tempFileLocation.list().length > 0) {
|
||||||
LOGGER.log(Level.WARNING, "Failed to delete some temporary files, see the log for more details");
|
LOGGER.log(Level.WARNING, "Failed to delete some temporary files, see the log for more details");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,9 +221,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
final String displayPath = String.format("%s%s",
|
final String displayPath = String.format("%s%s",
|
||||||
dependency.getFilePath(),
|
dependency.getFilePath(),
|
||||||
d.getActualFilePath().substring(tmpDir.getAbsolutePath().length()));
|
d.getActualFilePath().substring(tmpDir.getAbsolutePath().length()));
|
||||||
final String displayName = String.format("%s%s%s",
|
final String displayName = String.format("%s: %s",
|
||||||
dependency.getFileName(),
|
dependency.getFileName(),
|
||||||
File.separator,
|
|
||||||
d.getFileName());
|
d.getFileName());
|
||||||
d.setFilePath(displayPath);
|
d.setFilePath(displayPath);
|
||||||
d.setFileName(displayName);
|
d.setFileName(displayName);
|
||||||
@@ -242,7 +241,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
final File tdir = getNextTempDirectory();
|
final File tdir = getNextTempDirectory();
|
||||||
final String fileName = dependency.getFileName();
|
final String fileName = dependency.getFileName();
|
||||||
|
|
||||||
LOGGER.info(String.format("The zip file '%s' appears to be a JAR file, making a deep copy and analyzing it as a JAR.", fileName));
|
LOGGER.info(String.format("The zip file '%s' appears to be a JAR file, making a copy and analyzing it as a JAR.", fileName));
|
||||||
|
|
||||||
final File tmpLoc = new File(tdir, fileName.substring(0, fileName.length() - 3) + "jar");
|
final File tmpLoc = new File(tdir, fileName.substring(0, fileName.length() - 3) + "jar");
|
||||||
try {
|
try {
|
||||||
@@ -339,7 +338,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
try {
|
try {
|
||||||
fis.close();
|
fis.close();
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.log(Level.FINEST, null, ex);
|
LOGGER.log(Level.FINE, null, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,8 +367,10 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
final File file = new File(destination, entry.getName());
|
final File file = new File(destination, entry.getName());
|
||||||
final String ext = FileUtils.getFileExtension(file.getName());
|
final String ext = FileUtils.getFileExtension(file.getName());
|
||||||
if (engine.supportsExtension(ext)) {
|
if (engine.supportsExtension(ext)) {
|
||||||
|
final String extracting = String.format("Extracting '%s'", file.getPath());
|
||||||
|
LOGGER.fine(extracting);
|
||||||
BufferedOutputStream bos = null;
|
BufferedOutputStream bos = null;
|
||||||
FileOutputStream fos;
|
FileOutputStream fos = null;
|
||||||
try {
|
try {
|
||||||
final File parent = file.getParentFile();
|
final File parent = file.getParentFile();
|
||||||
if (!parent.isDirectory()) {
|
if (!parent.isDirectory()) {
|
||||||
@@ -402,6 +403,13 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
LOGGER.log(Level.FINEST, null, ex);
|
LOGGER.log(Level.FINEST, null, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (fos != null) {
|
||||||
|
try {
|
||||||
|
fos.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.FINEST, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,6 +437,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
* @throws ArchiveExtractionException thrown if there is an exception decompressing the file
|
* @throws ArchiveExtractionException thrown if there is an exception decompressing the file
|
||||||
*/
|
*/
|
||||||
private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException {
|
private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException {
|
||||||
|
final String msg = String.format("Decompressing '%s'", outputFile.getPath());
|
||||||
|
LOGGER.fine(msg);
|
||||||
FileOutputStream out = null;
|
FileOutputStream out = null;
|
||||||
try {
|
try {
|
||||||
out = new FileOutputStream(outputFile);
|
out = new FileOutputStream(outputFile);
|
||||||
|
|||||||
@@ -120,9 +120,11 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
// Try evacuating the error stream
|
// Try evacuating the error stream
|
||||||
rdr = new BufferedReader(new InputStreamReader(proc.getErrorStream(), "UTF-8"));
|
rdr = new BufferedReader(new InputStreamReader(proc.getErrorStream(), "UTF-8"));
|
||||||
String line = null;
|
String line = null;
|
||||||
|
// CHECKSTYLE:OFF
|
||||||
while (rdr.ready() && (line = rdr.readLine()) != null) {
|
while (rdr.ready() && (line = rdr.readLine()) != null) {
|
||||||
LOGGER.log(Level.WARNING, "analyzer.AssemblyAnalyzer.grokassembly.stderr", line);
|
LOGGER.log(Level.WARNING, "analyzer.AssemblyAnalyzer.grokassembly.stderr", line);
|
||||||
}
|
}
|
||||||
|
// CHECKSTYLE:ON
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
doc = builder.parse(proc.getInputStream());
|
doc = builder.parse(proc.getInputStream());
|
||||||
|
|
||||||
@@ -233,9 +235,11 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
final Process p = pb.start();
|
final Process p = pb.start();
|
||||||
// Try evacuating the error stream
|
// Try evacuating the error stream
|
||||||
rdr = new BufferedReader(new InputStreamReader(p.getErrorStream(), "UTF-8"));
|
rdr = new BufferedReader(new InputStreamReader(p.getErrorStream(), "UTF-8"));
|
||||||
|
// CHECKSTYLE:OFF
|
||||||
while (rdr.ready() && rdr.readLine() != null) {
|
while (rdr.ready() && rdr.readLine() != null) {
|
||||||
// We expect this to complain
|
// We expect this to complain
|
||||||
}
|
}
|
||||||
|
// CHECKSTYLE:ON
|
||||||
final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream());
|
final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream());
|
||||||
final XPath xpath = XPathFactory.newInstance().newXPath();
|
final XPath xpath = XPathFactory.newInstance().newXPath();
|
||||||
final String error = xpath.evaluate("/assembly/error", doc);
|
final String error = xpath.evaluate("/assembly/error", doc);
|
||||||
|
|||||||
@@ -170,29 +170,10 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
* @throws ParseException is thrown when the Lucene query cannot be parsed.
|
* @throws ParseException is thrown when the Lucene query cannot be parsed.
|
||||||
*/
|
*/
|
||||||
protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
|
protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
|
||||||
Confidence confidence = Confidence.HIGHEST;
|
//TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit
|
||||||
|
String vendors = "";
|
||||||
String vendors = addEvidenceWithoutDuplicateTerms("", dependency.getVendorEvidence(), confidence);
|
String products = "";
|
||||||
String products = addEvidenceWithoutDuplicateTerms("", dependency.getProductEvidence(), confidence);
|
for (Confidence confidence : Confidence.values()) {
|
||||||
/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
|
|
||||||
* CPE identified. As such, we are "using" the evidence and ignoring the results. */
|
|
||||||
addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
|
|
||||||
|
|
||||||
int ctr = 0;
|
|
||||||
do {
|
|
||||||
if (!vendors.isEmpty() && !products.isEmpty()) {
|
|
||||||
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
|
|
||||||
dependency.getVendorEvidence().getWeighting());
|
|
||||||
|
|
||||||
for (IndexEntry e : entries) {
|
|
||||||
if (verifyEntry(e, dependency)) {
|
|
||||||
final String vendor = e.getVendor();
|
|
||||||
final String product = e.getProduct();
|
|
||||||
determineIdentifiers(dependency, vendor, product);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
confidence = reduceConfidence(confidence);
|
|
||||||
if (dependency.getVendorEvidence().contains(confidence)) {
|
if (dependency.getVendorEvidence().contains(confidence)) {
|
||||||
vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence);
|
vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence);
|
||||||
}
|
}
|
||||||
@@ -201,10 +182,28 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
}
|
}
|
||||||
/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
|
/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
|
||||||
* CPE identified. As such, we are "using" the evidence and ignoring the results. */
|
* CPE identified. As such, we are "using" the evidence and ignoring the results. */
|
||||||
if (dependency.getVersionEvidence().contains(confidence)) {
|
// if (dependency.getVersionEvidence().contains(confidence)) {
|
||||||
addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
|
// addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
|
||||||
|
// }
|
||||||
|
if (!vendors.isEmpty() && !products.isEmpty()) {
|
||||||
|
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
|
||||||
|
dependency.getVendorEvidence().getWeighting());
|
||||||
|
if (entries == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
boolean identifierAdded = false;
|
||||||
|
for (IndexEntry e : entries) {
|
||||||
|
if (verifyEntry(e, dependency)) {
|
||||||
|
final String vendor = e.getVendor();
|
||||||
|
final String product = e.getProduct();
|
||||||
|
identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (identifierAdded) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while ((++ctr) < 4);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -239,22 +238,6 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
return sb.toString().trim();
|
return sb.toString().trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reduces the given confidence by one level. This returns LOW if the confidence passed in is not HIGH.
|
|
||||||
*
|
|
||||||
* @param c the confidence to reduce.
|
|
||||||
* @return One less then the confidence passed in.
|
|
||||||
*/
|
|
||||||
private Confidence reduceConfidence(final Confidence c) {
|
|
||||||
if (c == Confidence.HIGHEST) {
|
|
||||||
return Confidence.HIGH;
|
|
||||||
} else if (c == Confidence.HIGH) {
|
|
||||||
return Confidence.MEDIUM;
|
|
||||||
} else {
|
|
||||||
return Confidence.LOW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Searches the Lucene CPE index to identify possible CPE entries associated with the supplied vendor, product, and
|
* Searches the Lucene CPE index to identify possible CPE entries associated with the supplied vendor, product, and
|
||||||
@@ -269,27 +252,24 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
* @param vendorWeightings a list of strings to use to add weighting factors to the vendor field
|
* @param vendorWeightings a list of strings to use to add weighting factors to the vendor field
|
||||||
* @param productWeightings Adds a list of strings that will be used to add weighting factors to the product search
|
* @param productWeightings Adds a list of strings that will be used to add weighting factors to the product search
|
||||||
* @return a list of possible CPE values
|
* @return a list of possible CPE values
|
||||||
* @throws CorruptIndexException when the Lucene index is corrupt
|
|
||||||
* @throws IOException when the Lucene index is not found
|
|
||||||
* @throws ParseException when the generated query is not valid
|
|
||||||
*/
|
*/
|
||||||
protected List<IndexEntry> searchCPE(String vendor, String product,
|
protected List<IndexEntry> searchCPE(String vendor, String product,
|
||||||
Set<String> vendorWeightings, Set<String> productWeightings)
|
Set<String> vendorWeightings, Set<String> productWeightings) {
|
||||||
throws CorruptIndexException, IOException, ParseException {
|
|
||||||
final ArrayList<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS);
|
final ArrayList<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS);
|
||||||
|
|
||||||
final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings);
|
final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings);
|
||||||
if (searchString == null) {
|
if (searchString == null) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS);
|
final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS);
|
||||||
for (ScoreDoc d : docs.scoreDocs) {
|
for (ScoreDoc d : docs.scoreDocs) {
|
||||||
if (d.score >= 0.08) {
|
if (d.score >= 0.08) {
|
||||||
final Document doc = cpe.getDocument(d.doc);
|
final Document doc = cpe.getDocument(d.doc);
|
||||||
final IndexEntry entry = new IndexEntry();
|
final IndexEntry entry = new IndexEntry();
|
||||||
entry.setVendor(doc.get(Fields.VENDOR));
|
entry.setVendor(doc.get(Fields.VENDOR));
|
||||||
entry.setProduct(doc.get(Fields.PRODUCT));
|
entry.setProduct(doc.get(Fields.PRODUCT));
|
||||||
// if (d.score < 0.08) {
|
// if (d.score < 0.08) {
|
||||||
// System.out.print(entry.getVendor());
|
// System.out.print(entry.getVendor());
|
||||||
// System.out.print(":");
|
// System.out.print(":");
|
||||||
@@ -297,13 +277,23 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
// System.out.print(":");
|
// System.out.print(":");
|
||||||
// System.out.println(d.score);
|
// System.out.println(d.score);
|
||||||
// }
|
// }
|
||||||
entry.setSearchScore(d.score);
|
entry.setSearchScore(d.score);
|
||||||
if (!ret.contains(entry)) {
|
if (!ret.contains(entry)) {
|
||||||
ret.add(entry);
|
ret.add(entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
} catch (ParseException ex) {
|
||||||
|
final String msg = String.format("Unable to parse: %s", searchString);
|
||||||
|
LOGGER.log(Level.WARNING, "An error occured querying the CPE data. See the log for more details.");
|
||||||
|
LOGGER.log(Level.INFO, msg, ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
final String msg = String.format("IO Error with search string: %s", searchString);
|
||||||
|
LOGGER.log(Level.WARNING, "An error occured reading CPE data. See the log for more details.");
|
||||||
|
LOGGER.log(Level.INFO, msg, ex);
|
||||||
}
|
}
|
||||||
return ret;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -508,14 +498,21 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
* @param dependency the Dependency being analyzed
|
* @param dependency the Dependency being analyzed
|
||||||
* @param vendor the vendor for the CPE being analyzed
|
* @param vendor the vendor for the CPE being analyzed
|
||||||
* @param product the product for the CPE being analyzed
|
* @param product the product for the CPE being analyzed
|
||||||
|
* @param currentConfidence the current confidence being used during analysis
|
||||||
|
* @return <code>true</code> if an identifier was added to the dependency; otherwise <code>false</code>
|
||||||
* @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
|
* @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
|
||||||
*/
|
*/
|
||||||
private void determineIdentifiers(Dependency dependency, String vendor, String product) throws UnsupportedEncodingException {
|
protected boolean determineIdentifiers(Dependency dependency, String vendor, String product,
|
||||||
|
Confidence currentConfidence) throws UnsupportedEncodingException {
|
||||||
final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
|
final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
|
||||||
DependencyVersion bestGuess = new DependencyVersion("-");
|
DependencyVersion bestGuess = new DependencyVersion("-");
|
||||||
Confidence bestGuessConf = null;
|
Confidence bestGuessConf = null;
|
||||||
|
boolean hasBroadMatch = false;
|
||||||
final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
|
final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
|
||||||
for (Confidence conf : Confidence.values()) {
|
for (Confidence conf : Confidence.values()) {
|
||||||
|
// if (conf.compareTo(currentConfidence) > 0) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
|
for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
|
||||||
final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
|
final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
|
||||||
if (evVer == null) {
|
if (evVer == null) {
|
||||||
@@ -528,9 +525,12 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
} else {
|
} else {
|
||||||
dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
|
dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
|
||||||
}
|
}
|
||||||
if (dbVer == null //special case, no version specified - everything is vulnerable
|
if (dbVer == null) { //special case, no version specified - everything is vulnerable
|
||||||
|| evVer.equals(dbVer)) { //yeah! exact match
|
hasBroadMatch = true;
|
||||||
|
final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
|
||||||
|
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf);
|
||||||
|
collected.add(match);
|
||||||
|
} else if (evVer.equals(dbVer)) { //yeah! exact match
|
||||||
final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
|
final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
|
||||||
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
|
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
|
||||||
collected.add(match);
|
collected.add(match);
|
||||||
@@ -556,7 +556,11 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
|
final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
|
||||||
final String url = null;
|
String url = null;
|
||||||
|
if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess.
|
||||||
|
final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product);
|
||||||
|
url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8"));
|
||||||
|
}
|
||||||
if (bestGuessConf == null) {
|
if (bestGuessConf == null) {
|
||||||
bestGuessConf = Confidence.LOW;
|
bestGuessConf = Confidence.LOW;
|
||||||
}
|
}
|
||||||
@@ -566,6 +570,7 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
Collections.sort(collected);
|
Collections.sort(collected);
|
||||||
final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence();
|
final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence();
|
||||||
final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence();
|
final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence();
|
||||||
|
boolean identifierAdded = false;
|
||||||
for (IdentifierMatch m : collected) {
|
for (IdentifierMatch m : collected) {
|
||||||
if (bestIdentifierQuality.equals(m.getConfidence())
|
if (bestIdentifierQuality.equals(m.getConfidence())
|
||||||
&& bestEvidenceQuality.equals(m.getEvidenceConfidence())) {
|
&& bestEvidenceQuality.equals(m.getEvidenceConfidence())) {
|
||||||
@@ -576,8 +581,10 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
i.setConfidence(bestEvidenceQuality);
|
i.setConfidence(bestEvidenceQuality);
|
||||||
}
|
}
|
||||||
dependency.addIdentifier(i);
|
dependency.addIdentifier(i);
|
||||||
|
identifierAdded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return identifierAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -592,7 +599,12 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
/**
|
/**
|
||||||
* A best guess for the CPE.
|
* A best guess for the CPE.
|
||||||
*/
|
*/
|
||||||
BEST_GUESS
|
BEST_GUESS,
|
||||||
|
/**
|
||||||
|
* The entire vendor/product group must be added (without a guess at version) because there is a CVE with a VS
|
||||||
|
* that only specifies vendor/product.
|
||||||
|
*/
|
||||||
|
BROAD_MATCH
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.analyzer;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.owasp.dependencycheck.Engine;
|
||||||
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
|
import org.owasp.dependencycheck.data.central.CentralSearch;
|
||||||
|
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
|
||||||
|
import org.owasp.dependencycheck.dependency.Confidence;
|
||||||
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
|
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyzer which will attempt to locate a dependency, and the GAV information, by querying Central for the dependency's
|
||||||
|
* SHA-1 digest.
|
||||||
|
*
|
||||||
|
* @author colezlaw
|
||||||
|
*/
|
||||||
|
public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CentralAnalyzer.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the analyzer.
|
||||||
|
*/
|
||||||
|
private static final String ANALYZER_NAME = "Central Analyzer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The phase in which this analyzer runs.
|
||||||
|
*/
|
||||||
|
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types of files on which this will work.
|
||||||
|
*/
|
||||||
|
private static final Set<String> SUPPORTED_EXTENSIONS = newHashSet("jar");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The analyzer should be disabled if there are errors, so this is a flag to determine if such an error has
|
||||||
|
* occurred.
|
||||||
|
*/
|
||||||
|
private boolean errorFlag = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The searcher itself.
|
||||||
|
*/
|
||||||
|
private CentralSearch searcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Field indicating if the analyzer is enabled.
|
||||||
|
*/
|
||||||
|
private final boolean enabled = checkEnabled();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether to enable this analyzer or not.
|
||||||
|
*
|
||||||
|
* @return whether the analyzer should be enabled
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if this analyzer is enabled.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the analyzer is enabled; otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
private boolean checkEnabled() {
|
||||||
|
boolean retval = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Settings.getBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED)) {
|
||||||
|
if (!Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)
|
||||||
|
|| NexusAnalyzer.DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL))) {
|
||||||
|
LOGGER.fine("Enabling the Central analyzer");
|
||||||
|
retval = true;
|
||||||
|
} else {
|
||||||
|
LOGGER.info("Nexus analyzer is enabled, disabling the Central Analyzer");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOGGER.info("Central analyzer disabled");
|
||||||
|
}
|
||||||
|
} catch (InvalidSettingException ise) {
|
||||||
|
LOGGER.warning("Invalid setting. Disabling the Central analyzer");
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the analyzer once before any analysis is performed.
|
||||||
|
*
|
||||||
|
* @throws Exception if there's an error during initialization
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void initializeFileTypeAnalyzer() throws Exception {
|
||||||
|
LOGGER.fine("Initializing Central analyzer");
|
||||||
|
LOGGER.fine(String.format("Central analyzer enabled: %s", isEnabled()));
|
||||||
|
if (isEnabled()) {
|
||||||
|
final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_CENTRAL_URL);
|
||||||
|
LOGGER.fine(String.format("Central Analyzer URL: %s", searchUrl));
|
||||||
|
searcher = new CentralSearch(new URL(searchUrl));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the analyzer's name.
|
||||||
|
*
|
||||||
|
* @return the name of the analyzer
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return ANALYZER_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key used in the properties file to to reference the analyzer's enabled property.
|
||||||
|
*
|
||||||
|
* @return the analyzer's enabled property setting key.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getAnalyzerEnabledSettingKey() {
|
||||||
|
return Settings.KEYS.ANALYZER_CENTRAL_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the analysis phase under which the analyzer runs.
|
||||||
|
*
|
||||||
|
* @return the phase under which the analyzer runs
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AnalysisPhase getAnalysisPhase() {
|
||||||
|
return ANALYSIS_PHASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the extensions for which this Analyzer runs.
|
||||||
|
*
|
||||||
|
* @return the extensions for which this Analyzer runs
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Set<String> getSupportedExtensions() {
|
||||||
|
return SUPPORTED_EXTENSIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the analysis.
|
||||||
|
*
|
||||||
|
* @param dependency the dependency to analyze
|
||||||
|
* @param engine the engine
|
||||||
|
* @throws AnalysisException when there's an exception during analysis
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
|
||||||
|
if (errorFlag || !isEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final List<MavenArtifact> mas = searcher.searchSha1(dependency.getSha1sum());
|
||||||
|
final Confidence confidence = mas.size() > 1 ? Confidence.HIGH : Confidence.HIGHEST;
|
||||||
|
for (MavenArtifact ma : mas) {
|
||||||
|
LOGGER.fine(String.format("Central analyzer found artifact (%s) for dependency (%s)", ma.toString(), dependency.getFileName()));
|
||||||
|
dependency.addAsEvidence("central", ma, confidence);
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
LOGGER.info(String.format("invalid sha1-hash on %s", dependency.getFileName()));
|
||||||
|
} catch (FileNotFoundException fnfe) {
|
||||||
|
LOGGER.fine(String.format("Artifact not found in repository: '%s", dependency.getFileName()));
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
LOGGER.log(Level.FINE, "Could not connect to Central search", ioe);
|
||||||
|
errorFlag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,7 +55,7 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
/**
|
/**
|
||||||
* A pattern for obtaining the first part of a filename.
|
* A pattern for obtaining the first part of a filename.
|
||||||
*/
|
*/
|
||||||
private static final Pattern STARTING_TEXT_PATTERN = Pattern.compile("^[a-zA-Z]*");
|
private static final Pattern STARTING_TEXT_PATTERN = Pattern.compile("^[a-zA-Z0-9]*");
|
||||||
/**
|
/**
|
||||||
* a flag indicating if this analyzer has run. This analyzer only runs once.
|
* a flag indicating if this analyzer has run. This analyzer only runs once.
|
||||||
*/
|
*/
|
||||||
@@ -107,21 +107,25 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
//for (Dependency nextDependency : engine.getDependencies()) {
|
//for (Dependency nextDependency : engine.getDependencies()) {
|
||||||
while (mainIterator.hasNext()) {
|
while (mainIterator.hasNext()) {
|
||||||
final Dependency dependency = mainIterator.next();
|
final Dependency dependency = mainIterator.next();
|
||||||
if (mainIterator.hasNext()) {
|
if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) {
|
||||||
final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
|
final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
|
||||||
while (subIterator.hasNext()) {
|
while (subIterator.hasNext()) {
|
||||||
final Dependency nextDependency = subIterator.next();
|
final Dependency nextDependency = subIterator.next();
|
||||||
if (hashesMatch(dependency, nextDependency)) {
|
if (hashesMatch(dependency, nextDependency)) {
|
||||||
if (isCore(dependency, nextDependency)) {
|
if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
|
||||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||||
} else {
|
} else {
|
||||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||||
|
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||||
}
|
}
|
||||||
} else if (isShadedJar(dependency, nextDependency)) {
|
} else if (isShadedJar(dependency, nextDependency)) {
|
||||||
if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
|
if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
|
||||||
dependenciesToRemove.add(dependency);
|
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||||
|
nextDependency.getRelatedDependencies().remove(dependency);
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
dependenciesToRemove.add(nextDependency);
|
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||||
|
nextDependency.getRelatedDependencies().remove(nextDependency);
|
||||||
}
|
}
|
||||||
} else if (cpeIdentifiersMatch(dependency, nextDependency)
|
} else if (cpeIdentifiersMatch(dependency, nextDependency)
|
||||||
&& hasSameBasePath(dependency, nextDependency)
|
&& hasSameBasePath(dependency, nextDependency)
|
||||||
@@ -131,6 +135,7 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||||
} else {
|
} else {
|
||||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||||
|
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,9 +143,7 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
}
|
}
|
||||||
//removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
|
//removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
|
||||||
// was difficult because of the inner iterator.
|
// was difficult because of the inner iterator.
|
||||||
for (Dependency d : dependenciesToRemove) {
|
engine.getDependencies().removeAll(dependenciesToRemove);
|
||||||
engine.getDependencies().remove(d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,26 +204,24 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
|| dependency2 == null || dependency2.getFileName() == null) {
|
|| dependency2 == null || dependency2.getFileName() == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String fileName1 = dependency1.getFileName();
|
final String fileName1 = dependency1.getActualFile().getName();
|
||||||
String fileName2 = dependency2.getFileName();
|
final String fileName2 = dependency2.getActualFile().getName();
|
||||||
|
|
||||||
//update to deal with archive analyzer, the starting name maybe the same
|
|
||||||
// as this is incorrectly looking at the starting path
|
|
||||||
final File one = new File(fileName1);
|
|
||||||
final File two = new File(fileName2);
|
|
||||||
final String oneParent = one.getParent();
|
|
||||||
final String twoParent = two.getParent();
|
|
||||||
if (oneParent != null) {
|
|
||||||
if (oneParent.equals(twoParent)) {
|
|
||||||
fileName1 = one.getName();
|
|
||||||
fileName2 = two.getName();
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (twoParent != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// //REMOVED because this is attempting to duplicate what is in the hasSameBasePath function.
|
||||||
|
// final File one = new File(fileName1);
|
||||||
|
// final File two = new File(fileName2);
|
||||||
|
// final String oneParent = one.getParent();
|
||||||
|
// final String twoParent = two.getParent();
|
||||||
|
// if (oneParent != null) {
|
||||||
|
// if (oneParent.equals(twoParent)) {
|
||||||
|
// fileName1 = one.getName();
|
||||||
|
// fileName2 = two.getName();
|
||||||
|
// } else {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// } else if (twoParent != null) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
//version check
|
//version check
|
||||||
final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1);
|
final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1);
|
||||||
final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2);
|
final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2);
|
||||||
@@ -267,9 +268,11 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
}
|
}
|
||||||
if (cpeCount1 > 0 && cpeCount1 == cpeCount2) {
|
if (cpeCount1 > 0 && cpeCount1 == cpeCount2) {
|
||||||
for (Identifier i : dependency1.getIdentifiers()) {
|
for (Identifier i : dependency1.getIdentifiers()) {
|
||||||
matches |= dependency2.getIdentifiers().contains(i);
|
if ("cpe".equals(i.getType())) {
|
||||||
if (!matches) {
|
matches |= dependency2.getIdentifiers().contains(i);
|
||||||
break;
|
if (!matches) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,6 +341,10 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
|| !rightName.contains("core") && leftName.contains("core")
|
|| !rightName.contains("core") && leftName.contains("core")
|
||||||
|| !rightName.contains("kernel") && leftName.contains("kernel")) {
|
|| !rightName.contains("kernel") && leftName.contains("kernel")) {
|
||||||
returnVal = true;
|
returnVal = true;
|
||||||
|
// } else if (leftName.matches(".*struts2\\-core.*") && rightName.matches(".*xwork\\-core.*")) {
|
||||||
|
// returnVal = true;
|
||||||
|
// } else if (rightName.matches(".*struts2\\-core.*") && leftName.matches(".*xwork\\-core.*")) {
|
||||||
|
// returnVal = false;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* considered splitting the names up and comparing the components,
|
* considered splitting the names up and comparing the components,
|
||||||
@@ -390,4 +397,43 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines which path is shortest; if path lengths are equal then we use compareTo of the string method to
|
||||||
|
* determine if the first path is smaller.
|
||||||
|
*
|
||||||
|
* @param left the first path to compare
|
||||||
|
* @param right the second path to compare
|
||||||
|
* @return <code>true</code> if the leftPath is the shortest; otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
protected boolean firstPathIsShortest(String left, String right) {
|
||||||
|
final String leftPath = left.replace('\\', '/');
|
||||||
|
final String rightPath = right.replace('\\', '/');
|
||||||
|
|
||||||
|
final int leftCount = countChar(leftPath, '/');
|
||||||
|
final int rightCount = countChar(rightPath, '/');
|
||||||
|
if (leftCount == rightCount) {
|
||||||
|
return leftPath.compareTo(rightPath) <= 0;
|
||||||
|
} else {
|
||||||
|
return leftCount < rightCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts the number of times the character is present in the string.
|
||||||
|
*
|
||||||
|
* @param string the string to count the characters in
|
||||||
|
* @param c the character to count
|
||||||
|
* @return the number of times the character is present in the string
|
||||||
|
*/
|
||||||
|
private int countChar(String string, char c) {
|
||||||
|
int count = 0;
|
||||||
|
final int max = string.length();
|
||||||
|
for (int i = 0; i < max; i++) {
|
||||||
|
if (c == string.charAt(i)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,12 +86,46 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
|
|||||||
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
|
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
|
||||||
removeJreEntries(dependency);
|
removeJreEntries(dependency);
|
||||||
removeBadMatches(dependency);
|
removeBadMatches(dependency);
|
||||||
|
removeBadSpringMatches(dependency);
|
||||||
removeWrongVersionMatches(dependency);
|
removeWrongVersionMatches(dependency);
|
||||||
removeSpuriousCPE(dependency);
|
removeSpuriousCPE(dependency);
|
||||||
removeDuplicativeEntriesFromJar(dependency, engine);
|
removeDuplicativeEntriesFromJar(dependency, engine);
|
||||||
addFalseNegativeCPEs(dependency);
|
addFalseNegativeCPEs(dependency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes inaccurate matches on springframework CPEs.
|
||||||
|
*
|
||||||
|
* @param dependency the dependency to test for and remove known inaccurate CPE matches
|
||||||
|
*/
|
||||||
|
private void removeBadSpringMatches(Dependency dependency) {
|
||||||
|
String mustContain = null;
|
||||||
|
for (Identifier i : dependency.getIdentifiers()) {
|
||||||
|
if ("maven".contains(i.getType())) {
|
||||||
|
if (i.getValue() != null && i.getValue().startsWith("org.springframework.")) {
|
||||||
|
final int endPoint = i.getValue().indexOf(":", 19);
|
||||||
|
if (endPoint >= 0) {
|
||||||
|
mustContain = i.getValue().substring(19, endPoint).toLowerCase();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mustContain != null) {
|
||||||
|
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
|
||||||
|
while (itr.hasNext()) {
|
||||||
|
final Identifier i = itr.next();
|
||||||
|
if ("cpe".contains(i.getType())
|
||||||
|
&& i.getValue() != null
|
||||||
|
&& i.getValue().startsWith("cpe:/a:springsource:")
|
||||||
|
&& !i.getValue().toLowerCase().contains(mustContain)) {
|
||||||
|
itr.remove();
|
||||||
|
//dependency.getIdentifiers().remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Intended to remove spurious CPE entries. By spurious we mean duplicate, less specific CPE entries.</p>
|
* Intended to remove spurious CPE entries. By spurious we mean duplicate, less specific CPE entries.</p>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
|
|||||||
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
|
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
|
||||||
|
|
||||||
//strip any path information that may get added by ArchiveAnalyzer, etc.
|
//strip any path information that may get added by ArchiveAnalyzer, etc.
|
||||||
final File f = new File(dependency.getFileName());
|
final File f = dependency.getActualFile();
|
||||||
String fileName = f.getName();
|
String fileName = f.getName();
|
||||||
|
|
||||||
//remove file extension
|
//remove file extension
|
||||||
|
|||||||
@@ -31,4 +31,9 @@ public interface FileTypeAnalyzer extends Analyzer {
|
|||||||
* @return whether or not the specified file extension is supported by this analyzer.
|
* @return whether or not the specified file extension is supported by this analyzer.
|
||||||
*/
|
*/
|
||||||
boolean supportsExtension(String extension);
|
boolean supportsExtension(String extension);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the analyzers state.
|
||||||
|
*/
|
||||||
|
void reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,7 +169,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
*/
|
*/
|
||||||
public JarAnalyzer() {
|
public JarAnalyzer() {
|
||||||
try {
|
try {
|
||||||
final JAXBContext jaxbContext = JAXBContext.newInstance("org.owasp.dependencycheck.jaxb.pom.generated");
|
//final JAXBContext jaxbContext = JAXBContext.newInstance("org.owasp.dependencycheck.jaxb.pom.generated");
|
||||||
|
final JAXBContext jaxbContext = JAXBContext.newInstance(Model.class);
|
||||||
pomUnmarshaller = jaxbContext.createUnmarshaller();
|
pomUnmarshaller = jaxbContext.createUnmarshaller();
|
||||||
} catch (JAXBException ex) { //guess we will just have a null pointer exception later...
|
} catch (JAXBException ex) { //guess we will just have a null pointer exception later...
|
||||||
LOGGER.log(Level.SEVERE, "Unable to load parser. See the log for more details.");
|
LOGGER.log(Level.SEVERE, "Unable to load parser. See the log for more details.");
|
||||||
@@ -292,13 +293,27 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
LOGGER.log(Level.FINE, msg, ex);
|
LOGGER.log(Level.FINE, msg, ex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
File externalPom = null;
|
||||||
if (pomEntries.isEmpty()) {
|
if (pomEntries.isEmpty()) {
|
||||||
return false;
|
if (dependency.getActualFilePath().matches(".*\\.m2.repository\\b.*")) {
|
||||||
|
String pomPath = dependency.getActualFilePath();
|
||||||
|
pomPath = pomPath.substring(0, pomPath.lastIndexOf('.')) + ".pom";
|
||||||
|
externalPom = new File(pomPath);
|
||||||
|
if (externalPom.isFile()) {
|
||||||
|
pomEntries.add(pomPath);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (String path : pomEntries) {
|
for (String path : pomEntries) {
|
||||||
Properties pomProperties = null;
|
Properties pomProperties = null;
|
||||||
try {
|
try {
|
||||||
pomProperties = retrievePomProperties(path, jar);
|
if (externalPom == null) {
|
||||||
|
pomProperties = retrievePomProperties(path, jar);
|
||||||
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.log(Level.FINEST, "ignore this, failed reading a non-existent pom.properties", ex);
|
LOGGER.log(Level.FINEST, "ignore this, failed reading a non-existent pom.properties", ex);
|
||||||
}
|
}
|
||||||
@@ -312,11 +327,11 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
final String displayPath = String.format("%s%s%s",
|
final String displayPath = String.format("%s%s%s",
|
||||||
dependency.getFilePath(),
|
dependency.getFilePath(),
|
||||||
File.separator,
|
File.separator,
|
||||||
path); //.replaceAll("[\\/]", File.separator));
|
path);
|
||||||
final String displayName = String.format("%s%s%s",
|
final String displayName = String.format("%s%s%s",
|
||||||
dependency.getFileName(),
|
dependency.getFileName(),
|
||||||
File.separator,
|
File.separator,
|
||||||
path); //.replaceAll("[\\/]", File.separator));
|
path);
|
||||||
|
|
||||||
newDependency.setFileName(displayName);
|
newDependency.setFileName(displayName);
|
||||||
newDependency.setFilePath(displayPath);
|
newDependency.setFilePath(displayPath);
|
||||||
@@ -324,7 +339,11 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
engine.getDependencies().add(newDependency);
|
engine.getDependencies().add(newDependency);
|
||||||
Collections.sort(engine.getDependencies());
|
Collections.sort(engine.getDependencies());
|
||||||
} else {
|
} else {
|
||||||
pom = retrievePom(path, jar);
|
if (externalPom == null) {
|
||||||
|
pom = retrievePom(path, jar);
|
||||||
|
} else {
|
||||||
|
pom = retrievePom(externalPom);
|
||||||
|
}
|
||||||
foundSomething |= setPomEvidence(dependency, pom, pomProperties, classes);
|
foundSomething |= setPomEvidence(dependency, pom, pomProperties, classes);
|
||||||
}
|
}
|
||||||
} catch (AnalysisException ex) {
|
} catch (AnalysisException ex) {
|
||||||
@@ -344,16 +363,25 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
* @return a Properties object or null if no pom.properties was found
|
* @return a Properties object or null if no pom.properties was found
|
||||||
* @throws IOException thrown if there is an exception reading the pom.properties
|
* @throws IOException thrown if there is an exception reading the pom.properties
|
||||||
*/
|
*/
|
||||||
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "OS_OPEN_STREAM",
|
|
||||||
justification = "The reader is closed by closing the zipEntry")
|
|
||||||
private Properties retrievePomProperties(String path, final JarFile jar) throws IOException {
|
private Properties retrievePomProperties(String path, final JarFile jar) throws IOException {
|
||||||
Properties pomProperties = null;
|
Properties pomProperties = null;
|
||||||
final String propPath = path.substring(0, path.length() - 7) + "pom.properies";
|
final String propPath = path.substring(0, path.length() - 7) + "pom.properies";
|
||||||
final ZipEntry propEntry = jar.getEntry(propPath);
|
final ZipEntry propEntry = jar.getEntry(propPath);
|
||||||
if (propEntry != null) {
|
if (propEntry != null) {
|
||||||
final Reader reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8");
|
Reader reader = null;
|
||||||
pomProperties = new Properties();
|
try {
|
||||||
pomProperties.load(reader);
|
reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8");
|
||||||
|
pomProperties = new Properties();
|
||||||
|
pomProperties.load(reader);
|
||||||
|
} finally {
|
||||||
|
if (reader != null) {
|
||||||
|
try {
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.FINEST, "close error", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return pomProperties;
|
return pomProperties;
|
||||||
}
|
}
|
||||||
@@ -513,6 +541,41 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads in the specified POM and converts it to a Model.
|
||||||
|
*
|
||||||
|
* @param file the pom.xml file
|
||||||
|
* @return returns a
|
||||||
|
* @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
|
||||||
|
* {@link org.owasp.dependencycheck.jaxb.pom.generated.Model} object
|
||||||
|
*/
|
||||||
|
private Model retrievePom(File file) throws AnalysisException {
|
||||||
|
Model model = null;
|
||||||
|
try {
|
||||||
|
final FileInputStream stream = new FileInputStream(file);
|
||||||
|
final InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
|
||||||
|
final InputSource xml = new InputSource(reader);
|
||||||
|
final SAXSource source = new SAXSource(xml);
|
||||||
|
model = readPom(source);
|
||||||
|
} catch (SecurityException ex) {
|
||||||
|
final String msg = String.format("Unable to parse pom '%s'; invalid signature", file.getPath());
|
||||||
|
LOGGER.log(Level.WARNING, msg);
|
||||||
|
LOGGER.log(Level.FINE, null, ex);
|
||||||
|
throw new AnalysisException(ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
final String msg = String.format("Unable to parse pom '%s'(IO Exception)", file.getPath());
|
||||||
|
LOGGER.log(Level.WARNING, msg);
|
||||||
|
LOGGER.log(Level.FINE, "", ex);
|
||||||
|
throw new AnalysisException(ex);
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
final String msg = String.format("Unexpected error during parsing of the pom '%s'", file.getPath());
|
||||||
|
LOGGER.log(Level.WARNING, msg);
|
||||||
|
LOGGER.log(Level.FINE, "", ex);
|
||||||
|
throw new AnalysisException(ex);
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the specified POM from a jar file and converts it to a Model.
|
* Retrieves the specified POM from a jar file and converts it to a Model.
|
||||||
*
|
*
|
||||||
@@ -573,11 +636,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
final String originalGroupID = groupid;
|
final String originalGroupID = groupid;
|
||||||
|
|
||||||
if (groupid != null && !groupid.isEmpty()) {
|
if (groupid != null && !groupid.isEmpty()) {
|
||||||
if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
|
|
||||||
groupid = groupid.substring(4);
|
|
||||||
}
|
|
||||||
foundSomething = true;
|
foundSomething = true;
|
||||||
dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGH);
|
dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST);
|
||||||
dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
|
dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
|
||||||
addMatchingValues(classes, groupid, dependency.getVendorEvidence());
|
addMatchingValues(classes, groupid, dependency.getVendorEvidence());
|
||||||
addMatchingValues(classes, groupid, dependency.getProductEvidence());
|
addMatchingValues(classes, groupid, dependency.getProductEvidence());
|
||||||
@@ -606,7 +666,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
artifactid = artifactid.substring(4);
|
artifactid = artifactid.substring(4);
|
||||||
}
|
}
|
||||||
foundSomething = true;
|
foundSomething = true;
|
||||||
dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGH);
|
dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST);
|
||||||
dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
|
dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
|
||||||
addMatchingValues(classes, artifactid, dependency.getVendorEvidence());
|
addMatchingValues(classes, artifactid, dependency.getVendorEvidence());
|
||||||
addMatchingValues(classes, artifactid, dependency.getProductEvidence());
|
addMatchingValues(classes, artifactid, dependency.getProductEvidence());
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import org.owasp.dependencycheck.data.nexus.MavenArtifact;
|
|||||||
import org.owasp.dependencycheck.data.nexus.NexusSearch;
|
import org.owasp.dependencycheck.data.nexus.NexusSearch;
|
||||||
import org.owasp.dependencycheck.dependency.Confidence;
|
import org.owasp.dependencycheck.dependency.Confidence;
|
||||||
import org.owasp.dependencycheck.dependency.Dependency;
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
import org.owasp.dependencycheck.dependency.Identifier;
|
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||||
import org.owasp.dependencycheck.utils.Settings;
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,6 +49,11 @@ import org.owasp.dependencycheck.utils.Settings;
|
|||||||
*/
|
*/
|
||||||
public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
|
public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default URL - this will be used by the CentralAnalyzer to determine whether to enable this.
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_URL = "https://repository.sonatype.org/service/local/";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logger.
|
* The logger.
|
||||||
*/
|
*/
|
||||||
@@ -74,6 +79,47 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
*/
|
*/
|
||||||
private NexusSearch searcher;
|
private NexusSearch searcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Field indicating if the analyzer is enabled.
|
||||||
|
*/
|
||||||
|
private final boolean enabled = checkEnabled();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if this analyzer is enabled
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the analyzer is enabled; otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
private boolean checkEnabled() {
|
||||||
|
/* Enable this analyzer ONLY if the Nexus URL has been set to something
|
||||||
|
other than the default one (if it's the default one, we'll use the
|
||||||
|
central one) and it's enabled by the user.
|
||||||
|
*/
|
||||||
|
boolean retval = false;
|
||||||
|
try {
|
||||||
|
if ((!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL)))
|
||||||
|
&& Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)) {
|
||||||
|
LOGGER.info("Enabling Nexus analyzer");
|
||||||
|
retval = true;
|
||||||
|
} else {
|
||||||
|
LOGGER.fine("Nexus analyzer disabled, using Central instead");
|
||||||
|
}
|
||||||
|
} catch (InvalidSettingException ise) {
|
||||||
|
LOGGER.warning("Invalid setting. Disabling Nexus analyzer");
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether to enable this analyzer or not.
|
||||||
|
*
|
||||||
|
* @return whether the analyzer should be enabled
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the analyzer once before any analysis is performed.
|
* Initializes the analyzer once before any analysis is performed.
|
||||||
*
|
*
|
||||||
@@ -150,31 +196,12 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
|
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
|
||||||
|
if (!isEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
final MavenArtifact ma = searcher.searchSha1(dependency.getSha1sum());
|
final MavenArtifact ma = searcher.searchSha1(dependency.getSha1sum());
|
||||||
if (ma.getGroupId() != null && !"".equals(ma.getGroupId())) {
|
dependency.addAsEvidence("nexus", ma, Confidence.HIGH);
|
||||||
dependency.getVendorEvidence().addEvidence("nexus", "groupid", ma.getGroupId(), Confidence.HIGH);
|
|
||||||
}
|
|
||||||
if (ma.getArtifactId() != null && !"".equals(ma.getArtifactId())) {
|
|
||||||
dependency.getProductEvidence().addEvidence("nexus", "artifactid", ma.getArtifactId(), Confidence.HIGH);
|
|
||||||
}
|
|
||||||
if (ma.getVersion() != null && !"".equals(ma.getVersion())) {
|
|
||||||
dependency.getVersionEvidence().addEvidence("nexus", "version", ma.getVersion(), Confidence.HIGH);
|
|
||||||
}
|
|
||||||
if (ma.getArtifactUrl() != null && !"".equals(ma.getArtifactUrl())) {
|
|
||||||
boolean found = false;
|
|
||||||
for (Identifier i : dependency.getIdentifiers()) {
|
|
||||||
if ("maven".equals(i.getType()) && i.getValue().equals(ma.toString())) {
|
|
||||||
found = true;
|
|
||||||
i.setConfidence(Confidence.HIGHEST);
|
|
||||||
i.setUrl(ma.getArtifactUrl());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
dependency.addIdentifier("maven", ma.toString(), ma.getArtifactUrl(), Confidence.HIGHEST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
//dependency.addAnalysisException(new AnalysisException("Invalid SHA-1"));
|
//dependency.addAnalysisException(new AnalysisException("Invalid SHA-1"));
|
||||||
LOGGER.info(String.format("invalid sha-1 hash on %s", dependency.getFileName()));
|
LOGGER.info(String.format("invalid sha-1 hash on %s", dependency.getFileName()));
|
||||||
|
|||||||
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.data.central;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.xpath.XPath;
|
||||||
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
import org.owasp.dependencycheck.utils.URLConnectionFactory;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class of methods to search Maven Central via Central.
|
||||||
|
*
|
||||||
|
* @author colezlaw
|
||||||
|
*/
|
||||||
|
public class CentralSearch {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL for the Central service
|
||||||
|
*/
|
||||||
|
private final URL rootURL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to use the Proxy when making requests
|
||||||
|
*/
|
||||||
|
private boolean useProxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for logging.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CentralSearch.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a NexusSearch for the given repository URL.
|
||||||
|
*
|
||||||
|
* @param rootURL the URL of the repository on which searches should execute. Only parameters are added to this (so
|
||||||
|
* it should end in /select)
|
||||||
|
*/
|
||||||
|
public CentralSearch(URL rootURL) {
|
||||||
|
this.rootURL = rootURL;
|
||||||
|
if (null != Settings.getString(Settings.KEYS.PROXY_SERVER)) {
|
||||||
|
useProxy = true;
|
||||||
|
LOGGER.fine("Using proxy");
|
||||||
|
} else {
|
||||||
|
useProxy = false;
|
||||||
|
LOGGER.fine("Not using proxy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches the configured Central URL for the given sha1 hash. If the artifact is found, a
|
||||||
|
* <code>MavenArtifact</code> is populated with the GAV.
|
||||||
|
*
|
||||||
|
* @param sha1 the SHA-1 hash string for which to search
|
||||||
|
* @return the populated Maven GAV.
|
||||||
|
* @throws IOException if it's unable to connect to the specified repository or if the specified artifact is not
|
||||||
|
* found.
|
||||||
|
*/
|
||||||
|
public List<MavenArtifact> searchSha1(String sha1) throws IOException {
|
||||||
|
if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
|
||||||
|
throw new IllegalArgumentException("Invalid SHA1 format");
|
||||||
|
}
|
||||||
|
|
||||||
|
final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1));
|
||||||
|
|
||||||
|
LOGGER.fine(String.format("Searching Central url %s", url.toString()));
|
||||||
|
|
||||||
|
// Determine if we need to use a proxy. The rules:
|
||||||
|
// 1) If the proxy is set, AND the setting is set to true, use the proxy
|
||||||
|
// 2) Otherwise, don't use the proxy (either the proxy isn't configured,
|
||||||
|
// or proxy is specifically set to false)
|
||||||
|
final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(url, useProxy);
|
||||||
|
|
||||||
|
conn.setDoOutput(true);
|
||||||
|
|
||||||
|
// JSON would be more elegant, but there's not currently a dependency
|
||||||
|
// on JSON, so don't want to add one just for this
|
||||||
|
conn.addRequestProperty("Accept", "application/xml");
|
||||||
|
conn.connect();
|
||||||
|
|
||||||
|
if (conn.getResponseCode() == 200) {
|
||||||
|
boolean missing = false;
|
||||||
|
try {
|
||||||
|
final DocumentBuilder builder = DocumentBuilderFactory
|
||||||
|
.newInstance().newDocumentBuilder();
|
||||||
|
final Document doc = builder.parse(conn.getInputStream());
|
||||||
|
final XPath xpath = XPathFactory.newInstance().newXPath();
|
||||||
|
final String numFound = xpath.evaluate("/response/result/@numFound", doc);
|
||||||
|
if ("0".equals(numFound)) {
|
||||||
|
missing = true;
|
||||||
|
} else {
|
||||||
|
final ArrayList<MavenArtifact> result = new ArrayList<MavenArtifact>();
|
||||||
|
final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET);
|
||||||
|
for (int i = 0; i < docs.getLength(); i++) {
|
||||||
|
final String g = xpath.evaluate("./str[@name='g']", docs.item(i));
|
||||||
|
LOGGER.finest(String.format("GroupId: %s", g));
|
||||||
|
final String a = xpath.evaluate("./str[@name='a']", docs.item(i));
|
||||||
|
LOGGER.finest(String.format("ArtifactId: %s", a));
|
||||||
|
final String v = xpath.evaluate("./str[@name='v']", docs.item(i));
|
||||||
|
LOGGER.finest(String.format("Version: %s", v));
|
||||||
|
result.add(new MavenArtifact(g, a, v, url.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
// Anything else is jacked up XML stuff that we really can't recover
|
||||||
|
// from well
|
||||||
|
throw new IOException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missing) {
|
||||||
|
throw new FileNotFoundException("Artifact not found in Central");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final String msg = String.format("Could not connect to Central received response code: %d %s",
|
||||||
|
conn.getResponseCode(), conn.getResponseMessage());
|
||||||
|
LOGGER.fine(msg);
|
||||||
|
throw new IOException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* <html>
|
||||||
|
* <head>
|
||||||
|
* <title>org.owasp.dependencycheck.data.central</title>
|
||||||
|
* </head>
|
||||||
|
* <body>
|
||||||
|
* <p>
|
||||||
|
* Contains classes related to searching Maven Central.</p>
|
||||||
|
* <p>
|
||||||
|
* These are used to abstract Maven Central searching away from OWASP Dependency Check so they can be reused elsewhere.</p>
|
||||||
|
* </body>
|
||||||
|
* </html>
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.data.central;
|
||||||
@@ -54,6 +54,7 @@ import org.owasp.dependencycheck.utils.Pair;
|
|||||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
*/
|
*/
|
||||||
public final class CpeMemoryIndex {
|
public final class CpeMemoryIndex {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logger.
|
* The logger.
|
||||||
*/
|
*/
|
||||||
@@ -61,7 +62,7 @@ public final class CpeMemoryIndex {
|
|||||||
/**
|
/**
|
||||||
* singleton instance.
|
* singleton instance.
|
||||||
*/
|
*/
|
||||||
private static CpeMemoryIndex instance = new CpeMemoryIndex();
|
private static final CpeMemoryIndex INSTANCE = new CpeMemoryIndex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* private constructor for singleton.
|
* private constructor for singleton.
|
||||||
@@ -75,7 +76,7 @@ public final class CpeMemoryIndex {
|
|||||||
* @return the instance of the CpeMemoryIndex
|
* @return the instance of the CpeMemoryIndex
|
||||||
*/
|
*/
|
||||||
public static CpeMemoryIndex getInstance() {
|
public static CpeMemoryIndex getInstance() {
|
||||||
return instance;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* The in memory Lucene index.
|
* The in memory Lucene index.
|
||||||
@@ -113,18 +114,20 @@ public final class CpeMemoryIndex {
|
|||||||
* @throws IndexException thrown if there is an error creating the index
|
* @throws IndexException thrown if there is an error creating the index
|
||||||
*/
|
*/
|
||||||
public void open(CveDB cve) throws IndexException {
|
public void open(CveDB cve) throws IndexException {
|
||||||
if (!openState) {
|
synchronized (INSTANCE) {
|
||||||
index = new RAMDirectory();
|
if (!openState) {
|
||||||
buildIndex(cve);
|
index = new RAMDirectory();
|
||||||
try {
|
buildIndex(cve);
|
||||||
indexReader = DirectoryReader.open(index);
|
try {
|
||||||
} catch (IOException ex) {
|
indexReader = DirectoryReader.open(index);
|
||||||
throw new IndexException(ex);
|
} catch (IOException ex) {
|
||||||
|
throw new IndexException(ex);
|
||||||
|
}
|
||||||
|
indexSearcher = new IndexSearcher(indexReader);
|
||||||
|
searchingAnalyzer = createSearchingAnalyzer();
|
||||||
|
queryParser = new QueryParser(LuceneUtils.CURRENT_VERSION, Fields.DOCUMENT_KEY, searchingAnalyzer);
|
||||||
|
openState = true;
|
||||||
}
|
}
|
||||||
indexSearcher = new IndexSearcher(indexReader);
|
|
||||||
searchingAnalyzer = createSearchingAnalyzer();
|
|
||||||
queryParser = new QueryParser(LuceneUtils.CURRENT_VERSION, Fields.DOCUMENT_KEY, searchingAnalyzer);
|
|
||||||
openState = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -160,7 +163,7 @@ public final class CpeMemoryIndex {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Analyzer createSearchingAnalyzer() {
|
private Analyzer createSearchingAnalyzer() {
|
||||||
final Map fieldAnalyzers = new HashMap();
|
final Map<String, Analyzer> fieldAnalyzers = new HashMap<String, Analyzer>();
|
||||||
fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer());
|
fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer());
|
||||||
productSearchFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
|
productSearchFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
|
||||||
vendorSearchFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
|
vendorSearchFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ package org.owasp.dependencycheck.data.cpe;
|
|||||||
*
|
*
|
||||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
*/
|
*/
|
||||||
public abstract class Fields {
|
public final class Fields {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key for the name document id.
|
* The key for the name document id.
|
||||||
@@ -36,7 +36,10 @@ public abstract class Fields {
|
|||||||
* The key for the product field.
|
* The key for the product field.
|
||||||
*/
|
*/
|
||||||
public static final String PRODUCT = "product";
|
public static final String PRODUCT = "product";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key for the version field.
|
* Private constructor as this is more of an enumeration rather then a full class.
|
||||||
*/
|
*/
|
||||||
|
private Fields() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,12 @@ import java.util.logging.Logger;
|
|||||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
*/
|
*/
|
||||||
public final class CweDB {
|
public final class CweDB {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Logger.
|
* The Logger.
|
||||||
*/
|
*/
|
||||||
private static final Logger LOGGER = Logger.getLogger(CweDB.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(CweDB.class.getName());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty private constructor as this is a utility class.
|
* Empty private constructor as this is a utility class.
|
||||||
*/
|
*/
|
||||||
@@ -55,7 +57,9 @@ public final class CweDB {
|
|||||||
final String filePath = "data/cwe.hashmap.serialized";
|
final String filePath = "data/cwe.hashmap.serialized";
|
||||||
final InputStream input = CweDB.class.getClassLoader().getResourceAsStream(filePath);
|
final InputStream input = CweDB.class.getClassLoader().getResourceAsStream(filePath);
|
||||||
oin = new ObjectInputStream(input);
|
oin = new ObjectInputStream(input);
|
||||||
return (HashMap<String, String>) oin.readObject();
|
@SuppressWarnings("unchecked")
|
||||||
|
final HashMap<String, String> ret = (HashMap<String, String>) oin.readObject();
|
||||||
|
return ret;
|
||||||
} catch (ClassNotFoundException ex) {
|
} catch (ClassNotFoundException ex) {
|
||||||
LOGGER.log(Level.WARNING, "Unable to load CWE data. This should not be an issue.");
|
LOGGER.log(Level.WARNING, "Unable to load CWE data. This should not be an issue.");
|
||||||
LOGGER.log(Level.FINE, null, ex);
|
LOGGER.log(Level.FINE, null, ex);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import org.owasp.dependencycheck.utils.Settings;
|
|||||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
*/
|
*/
|
||||||
public final class ConnectionFactory {
|
public final class ConnectionFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Logger.
|
* The Logger.
|
||||||
*/
|
*/
|
||||||
@@ -49,7 +50,7 @@ public final class ConnectionFactory {
|
|||||||
/**
|
/**
|
||||||
* The version of the current DB Schema.
|
* The version of the current DB Schema.
|
||||||
*/
|
*/
|
||||||
public static final String DB_SCHEMA_VERSION = "2.9";
|
public static final String DB_SCHEMA_VERSION = Settings.getString(Settings.KEYS.DB_VERSION);
|
||||||
/**
|
/**
|
||||||
* Resource location for SQL file used to create the database schema.
|
* Resource location for SQL file used to create the database schema.
|
||||||
*/
|
*/
|
||||||
@@ -111,7 +112,10 @@ public final class ConnectionFactory {
|
|||||||
//yes, yes - hard-coded password - only if there isn't one in the properties file.
|
//yes, yes - hard-coded password - only if there isn't one in the properties file.
|
||||||
password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!");
|
password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!");
|
||||||
try {
|
try {
|
||||||
connectionString = getConnectionString();
|
connectionString = Settings.getConnectionString(
|
||||||
|
Settings.KEYS.DB_CONNECTION_STRING,
|
||||||
|
Settings.KEYS.DB_FILE_NAME,
|
||||||
|
Settings.KEYS.DB_VERSION);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.log(Level.FINE,
|
LOGGER.log(Level.FINE,
|
||||||
"Unable to retrieve the database connection string", ex);
|
"Unable to retrieve the database connection string", ex);
|
||||||
@@ -120,7 +124,7 @@ public final class ConnectionFactory {
|
|||||||
boolean shouldCreateSchema = false;
|
boolean shouldCreateSchema = false;
|
||||||
try {
|
try {
|
||||||
if (connectionString.startsWith("jdbc:h2:file:")) { //H2
|
if (connectionString.startsWith("jdbc:h2:file:")) { //H2
|
||||||
shouldCreateSchema = !dbSchemaExists();
|
shouldCreateSchema = !h2DataFileExists();
|
||||||
LOGGER.log(Level.FINE, "Need to create DB Structure: {0}", shouldCreateSchema);
|
LOGGER.log(Level.FINE, "Need to create DB Structure: {0}", shouldCreateSchema);
|
||||||
}
|
}
|
||||||
} catch (IOException ioex) {
|
} catch (IOException ioex) {
|
||||||
@@ -217,51 +221,17 @@ public final class ConnectionFactory {
|
|||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the configured connection string. If using the embedded H2 database this function will also ensure the
|
|
||||||
* data directory exists and if not create it.
|
|
||||||
*
|
|
||||||
* @return the connection string
|
|
||||||
* @throws IOException thrown the data directory cannot be created
|
|
||||||
*/
|
|
||||||
private static String getConnectionString() throws IOException {
|
|
||||||
final String connStr = Settings.getString(Settings.KEYS.DB_CONNECTION_STRING, "jdbc:h2:file:%s;AUTO_SERVER=TRUE");
|
|
||||||
if (connStr.contains("%s")) {
|
|
||||||
final String directory = getDataDirectory().getCanonicalPath();
|
|
||||||
final File dataFile = new File(directory, "cve." + DB_SCHEMA_VERSION);
|
|
||||||
LOGGER.log(Level.FINE, String.format("File path for H2 file: '%s'", dataFile.toString()));
|
|
||||||
return String.format(connStr, dataFile.getAbsolutePath());
|
|
||||||
}
|
|
||||||
return connStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the directory that the JAR file exists in so that we can ensure we always use a common data directory
|
|
||||||
* for the embedded H2 database. This is public solely for some unit tests; otherwise this should be private.
|
|
||||||
*
|
|
||||||
* @return the data directory to store data files
|
|
||||||
* @throws IOException is thrown if an IOException occurs of course...
|
|
||||||
*/
|
|
||||||
public static File getDataDirectory() throws IOException {
|
|
||||||
final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY);
|
|
||||||
if (!path.exists()) {
|
|
||||||
if (!path.mkdirs()) {
|
|
||||||
throw new IOException("Unable to create NVD CVE Data directory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the H2 database file exists. If it does not exist then the data structure will need to be created.
|
* Determines if the H2 database file exists. If it does not exist then the data structure will need to be created.
|
||||||
*
|
*
|
||||||
* @return true if the H2 database file does not exist; otherwise false
|
* @return true if the H2 database file does not exist; otherwise false
|
||||||
* @throws IOException thrown if the data directory does not exist and cannot be created
|
* @throws IOException thrown if the data directory does not exist and cannot be created
|
||||||
*/
|
*/
|
||||||
private static boolean dbSchemaExists() throws IOException {
|
private static boolean h2DataFileExists() throws IOException {
|
||||||
final File dir = getDataDirectory();
|
final File dir = Settings.getDataDirectory();
|
||||||
final String name = String.format("cve.%s.h2.db", DB_SCHEMA_VERSION);
|
final String name = Settings.getString(Settings.KEYS.DB_FILE_NAME);
|
||||||
final File file = new File(dir, name);
|
final String fileName = String.format(name, DB_SCHEMA_VERSION);
|
||||||
|
final File file = new File(dir, fileName);
|
||||||
return file.exists();
|
return file.exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.data.nvdcve;
|
package org.owasp.dependencycheck.data.nvdcve;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
@@ -39,6 +40,7 @@ import org.owasp.dependencycheck.utils.DBUtils;
|
|||||||
import org.owasp.dependencycheck.utils.DependencyVersion;
|
import org.owasp.dependencycheck.utils.DependencyVersion;
|
||||||
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
|
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
|
||||||
import org.owasp.dependencycheck.utils.Pair;
|
import org.owasp.dependencycheck.utils.Pair;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The database holding information about the NVD CVE data.
|
* The database holding information about the NVD CVE data.
|
||||||
@@ -87,7 +89,9 @@ public class CveDB {
|
|||||||
* @throws DatabaseException thrown if there is an error opening the database connection
|
* @throws DatabaseException thrown if there is an error opening the database connection
|
||||||
*/
|
*/
|
||||||
public final void open() throws DatabaseException {
|
public final void open() throws DatabaseException {
|
||||||
conn = ConnectionFactory.getConnection();
|
if (!isOpen()) {
|
||||||
|
conn = ConnectionFactory.getConnection();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -306,14 +310,14 @@ public class CveDB {
|
|||||||
* @throws DatabaseException thrown when there is an error retrieving the data from the DB
|
* @throws DatabaseException thrown when there is an error retrieving the data from the DB
|
||||||
*/
|
*/
|
||||||
public Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
|
public Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
|
||||||
final HashSet data = new HashSet<Pair<String, String>>();
|
final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>();
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
ps = getConnection().prepareStatement(SELECT_VENDOR_PRODUCT_LIST);
|
ps = getConnection().prepareStatement(SELECT_VENDOR_PRODUCT_LIST);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
data.add(new Pair(rs.getString(1), rs.getString(2)));
|
data.add(new Pair<String, String>(rs.getString(1), rs.getString(2)));
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
|
final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
|
||||||
@@ -700,6 +704,43 @@ public class CveDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see if data exists so that analysis can be performed.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if data exists; otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
public boolean dataExists() {
|
||||||
|
Statement cs = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
cs = conn.createStatement();
|
||||||
|
rs = cs.executeQuery("SELECT COUNT(*) records FROM cpeEntry");
|
||||||
|
if (rs.next()) {
|
||||||
|
if (rs.getInt(1) > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
String dd;
|
||||||
|
try {
|
||||||
|
dd = Settings.getDataDirectory().getAbsolutePath();
|
||||||
|
} catch (IOException ex1) {
|
||||||
|
dd = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
|
||||||
|
}
|
||||||
|
final String msg = String.format("Unable to access the local database.%n%nEnsure that '%s' is a writable directory. "
|
||||||
|
+ "If the problem persist try deleting the files in '%s' and running %s again. If the problem continues, please "
|
||||||
|
+ "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at "
|
||||||
|
+ "https://github.com/jeremylong/DependencyCheck/issues and include the log file.%n%n",
|
||||||
|
dd, dd, Settings.getString(Settings.KEYS.APPLICATION_VAME));
|
||||||
|
LOGGER.log(Level.SEVERE, msg);
|
||||||
|
LOGGER.log(Level.FINE, "", ex);
|
||||||
|
} finally {
|
||||||
|
DBUtils.closeResultSet(rs);
|
||||||
|
DBUtils.closeStatement(cs);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It is possible that orphaned rows may be generated during database updates. This should be called after all
|
* It is possible that orphaned rows may be generated during database updates. This should be called after all
|
||||||
* updates have been completed to ensure orphan entries are removed.
|
* updates have been completed to ensure orphan entries are removed.
|
||||||
@@ -731,7 +772,7 @@ public class CveDB {
|
|||||||
* @param previous a flag indicating if previous versions of the product are vulnerable
|
* @param previous a flag indicating if previous versions of the product are vulnerable
|
||||||
* @return true if the identified version is affected, otherwise false
|
* @return true if the identified version is affected, otherwise false
|
||||||
*/
|
*/
|
||||||
private boolean isAffected(String vendor, String product, DependencyVersion identifiedVersion, String cpeId, String previous) {
|
protected boolean isAffected(String vendor, String product, DependencyVersion identifiedVersion, String cpeId, String previous) {
|
||||||
boolean affected = false;
|
boolean affected = false;
|
||||||
final boolean isStruts = "apache".equals(vendor) && "struts".equals(product);
|
final boolean isStruts = "apache".equals(vendor) && "struts".equals(product);
|
||||||
final DependencyVersion v = parseDependencyVersion(cpeId);
|
final DependencyVersion v = parseDependencyVersion(cpeId);
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ public class DatabaseProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a properties file containing the last updated date to the VULNERABLE_CPE directory.
|
* Saves the last updated information to the properties file.
|
||||||
*
|
*
|
||||||
* @param updatedValue the updated NVD CVE entry
|
* @param updatedValue the updated NVD CVE entry
|
||||||
* @throws UpdateException is thrown if there is an update exception
|
* @throws UpdateException is thrown if there is an update exception
|
||||||
@@ -100,8 +100,19 @@ public class DatabaseProperties {
|
|||||||
if (updatedValue == null) {
|
if (updatedValue == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
properties.put(LAST_UPDATED_BASE + updatedValue.getId(), String.valueOf(updatedValue.getTimestamp()));
|
save(LAST_UPDATED_BASE + updatedValue.getId(), String.valueOf(updatedValue.getTimestamp()));
|
||||||
cveDB.saveProperty(LAST_UPDATED_BASE + updatedValue.getId(), String.valueOf(updatedValue.getTimestamp()));
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the key value pair to the properties store.
|
||||||
|
*
|
||||||
|
* @param key the property key
|
||||||
|
* @param value the property value
|
||||||
|
* @throws UpdateException is thrown if there is an update exception
|
||||||
|
*/
|
||||||
|
public void save(String key, String value) throws UpdateException {
|
||||||
|
properties.put(key, value);
|
||||||
|
cveDB.saveProperty(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,8 +153,8 @@ public class DatabaseProperties {
|
|||||||
*
|
*
|
||||||
* @return a map of the database meta data
|
* @return a map of the database meta data
|
||||||
*/
|
*/
|
||||||
public Map getMetaData() {
|
public Map<String, String> getMetaData() {
|
||||||
final TreeMap map = new TreeMap();
|
final TreeMap<String, String> map = new TreeMap<String, String>();
|
||||||
for (Entry<Object, Object> entry : properties.entrySet()) {
|
for (Entry<Object, Object> entry : properties.entrySet()) {
|
||||||
final String key = (String) entry.getKey();
|
final String key = (String) entry.getKey();
|
||||||
if (!"version".equals(key)) {
|
if (!"version".equals(key)) {
|
||||||
@@ -156,10 +167,10 @@ public class DatabaseProperties {
|
|||||||
map.put(key, formatted);
|
map.put(key, formatted);
|
||||||
} catch (Throwable ex) { //deliberately being broad in this catch clause
|
} catch (Throwable ex) { //deliberately being broad in this catch clause
|
||||||
LOGGER.log(Level.FINE, "Unable to parse timestamp from DB", ex);
|
LOGGER.log(Level.FINE, "Unable to parse timestamp from DB", ex);
|
||||||
map.put(key, entry.getValue());
|
map.put(key, (String) entry.getValue());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
map.put(key, entry.getValue());
|
map.put(key, (String) entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.data.update;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||||
|
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||||
|
import org.owasp.dependencycheck.utils.DateUtil;
|
||||||
|
import org.owasp.dependencycheck.utils.DependencyVersion;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
import org.owasp.dependencycheck.utils.URLConnectionFactory;
|
||||||
|
import org.owasp.dependencycheck.utils.URLConnectionFailureException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
public class EngineVersionCheck implements CachedWebDataSource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static logger.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(EngineVersionCheck.class.getName());
|
||||||
|
/**
|
||||||
|
* The property key indicating when the last version check occurred.
|
||||||
|
*/
|
||||||
|
public static final String ENGINE_VERSION_CHECKED_ON = "VersionCheckOn";
|
||||||
|
/**
|
||||||
|
* The property key indicating when the last version check occurred.
|
||||||
|
*/
|
||||||
|
public static final String CURRENT_ENGINE_RELEASE = "CurrentEngineRelease";
|
||||||
|
/**
|
||||||
|
* Reference to the Cve Database.
|
||||||
|
*/
|
||||||
|
private CveDB cveDB = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The version retrieved from the database properties or web to check against.
|
||||||
|
*/
|
||||||
|
private String updateToVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for updateToVersion - only used for testing. Represents the version retrieved from the database.
|
||||||
|
*
|
||||||
|
* @return the version to test
|
||||||
|
*/
|
||||||
|
protected String getUpdateToVersion() {
|
||||||
|
return updateToVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for updateToVersion - only used for testing. Represents the version retrieved from the database.
|
||||||
|
*
|
||||||
|
* @param version the version to test
|
||||||
|
*/
|
||||||
|
protected void setUpdateToVersion(String version) {
|
||||||
|
updateToVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() throws UpdateException {
|
||||||
|
try {
|
||||||
|
openDatabase();
|
||||||
|
LOGGER.fine("Begin Engine Version Check");
|
||||||
|
final DatabaseProperties properties = cveDB.getDatabaseProperties();
|
||||||
|
final long lastChecked = Long.parseLong(properties.getProperty(ENGINE_VERSION_CHECKED_ON, "0"));
|
||||||
|
final long now = (new Date()).getTime();
|
||||||
|
updateToVersion = properties.getProperty(CURRENT_ENGINE_RELEASE, "");
|
||||||
|
final String currentVersion = Settings.getString(Settings.KEYS.APPLICATION_VERSION, "0.0.0");
|
||||||
|
LOGGER.fine("Last checked: " + lastChecked);
|
||||||
|
LOGGER.fine("Now: " + now);
|
||||||
|
LOGGER.fine("Current version: " + currentVersion);
|
||||||
|
final boolean updateNeeded = shouldUpdate(lastChecked, now, properties, currentVersion);
|
||||||
|
if (updateNeeded) {
|
||||||
|
final String msg = String.format("A new version of dependency-check is available. Consider updating to version %s.",
|
||||||
|
updateToVersion);
|
||||||
|
LOGGER.warning(msg);
|
||||||
|
}
|
||||||
|
} catch (DatabaseException ex) {
|
||||||
|
LOGGER.log(Level.FINE, "Database Exception opening databases to retrieve properties", ex);
|
||||||
|
throw new UpdateException("Error occured updating database properties.");
|
||||||
|
} finally {
|
||||||
|
closeDatabase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a new version of the dependency-check engine has been released.
|
||||||
|
*
|
||||||
|
* @param lastChecked the epoch time of the last version check
|
||||||
|
* @param now the current epoch time
|
||||||
|
* @param properties the database properties object
|
||||||
|
* @param currentVersion the current version of dependency-check
|
||||||
|
* @return <code>true</code> if a newer version of the database has been released; otherwise <code>false</code>
|
||||||
|
* @throws UpdateException thrown if there is an error connecting to the github documentation site or accessing the
|
||||||
|
* local database.
|
||||||
|
*/
|
||||||
|
protected boolean shouldUpdate(final long lastChecked, final long now, final DatabaseProperties properties,
|
||||||
|
String currentVersion) throws UpdateException {
|
||||||
|
//check every 30 days if we know there is an update, otherwise check every 7 days
|
||||||
|
int checkRange = 30;
|
||||||
|
if (updateToVersion.isEmpty()) {
|
||||||
|
checkRange = 7;
|
||||||
|
}
|
||||||
|
if (!DateUtil.withinDateRange(lastChecked, now, checkRange)) {
|
||||||
|
LOGGER.fine("Checking web for new version.");
|
||||||
|
final String currentRelease = getCurrentReleaseVersion();
|
||||||
|
if (currentRelease != null) {
|
||||||
|
final DependencyVersion v = new DependencyVersion(currentRelease);
|
||||||
|
if (v.getVersionParts() != null && v.getVersionParts().size() >= 3) {
|
||||||
|
updateToVersion = v.toString();
|
||||||
|
if (!currentRelease.equals(updateToVersion)) {
|
||||||
|
properties.save(CURRENT_ENGINE_RELEASE, updateToVersion);
|
||||||
|
} else {
|
||||||
|
properties.save(CURRENT_ENGINE_RELEASE, "");
|
||||||
|
}
|
||||||
|
properties.save(ENGINE_VERSION_CHECKED_ON, Long.toString(now));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOGGER.log(Level.FINE, "Current Release: {0}", updateToVersion);
|
||||||
|
}
|
||||||
|
final DependencyVersion running = new DependencyVersion(currentVersion);
|
||||||
|
final DependencyVersion released = new DependencyVersion(updateToVersion);
|
||||||
|
if (running.compareTo(released) < 0) {
|
||||||
|
LOGGER.fine("Upgrade recommended");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOGGER.fine("Upgrade not needed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the CVE and CPE data stores.
|
||||||
|
*
|
||||||
|
* @throws DatabaseException thrown if a data store cannot be opened
|
||||||
|
*/
|
||||||
|
protected final void openDatabase() throws DatabaseException {
|
||||||
|
if (cveDB != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cveDB = new CveDB();
|
||||||
|
cveDB.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the CVE and CPE data stores.
|
||||||
|
*/
|
||||||
|
protected void closeDatabase() {
|
||||||
|
if (cveDB != null) {
|
||||||
|
try {
|
||||||
|
cveDB.close();
|
||||||
|
} catch (Throwable ignore) {
|
||||||
|
LOGGER.log(Level.FINEST, "Error closing the cveDB", ignore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the current released version number from the github documentation site.
|
||||||
|
*
|
||||||
|
* @return the current released version number
|
||||||
|
*/
|
||||||
|
protected String getCurrentReleaseVersion() {
|
||||||
|
HttpURLConnection conn = null;
|
||||||
|
try {
|
||||||
|
final String str = Settings.getString(Settings.KEYS.ENGINE_VERSION_CHECK_URL, "http://jeremylong.github.io/DependencyCheck/current.txt");
|
||||||
|
final URL url = new URL(str);
|
||||||
|
conn = URLConnectionFactory.createHttpURLConnection(url);
|
||||||
|
conn.connect();
|
||||||
|
if (conn.getResponseCode() != 200) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final String releaseVersion = IOUtils.toString(conn.getInputStream(), "UTF-8");
|
||||||
|
if (releaseVersion != null) {
|
||||||
|
return releaseVersion.trim();
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException ex) {
|
||||||
|
LOGGER.log(Level.FINE, "unable to retrieve current release version of dependency-check", ex);
|
||||||
|
} catch (URLConnectionFailureException ex) {
|
||||||
|
LOGGER.log(Level.FINE, "unable to retrieve current release version of dependency-check", ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.FINE, "unable to retrieve current release version of dependency-check", ex);
|
||||||
|
} finally {
|
||||||
|
if (conn != null) {
|
||||||
|
conn.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||||
import org.owasp.dependencycheck.utils.DownloadFailedException;
|
import org.owasp.dependencycheck.utils.DownloadFailedException;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class responsible for updating the NVD CVE and CPE data stores.
|
* Class responsible for updating the NVD CVE and CPE data stores.
|
||||||
@@ -54,7 +55,11 @@ public class NvdCveUpdater implements CachedWebDataSource {
|
|||||||
LOGGER.log(Level.FINE, null, ex);
|
LOGGER.log(Level.FINE, null, ex);
|
||||||
} catch (DownloadFailedException ex) {
|
} catch (DownloadFailedException ex) {
|
||||||
LOGGER.log(Level.WARNING,
|
LOGGER.log(Level.WARNING,
|
||||||
"Unable to download the NVD CVE data, unable to update the data to use the most current data.");
|
"Unable to download the NVD CVE data; the results may not include the most recent CPE/CVEs from the NVD.");
|
||||||
|
if (Settings.getString(Settings.KEYS.PROXY_SERVER) == null) {
|
||||||
|
LOGGER.log(Level.INFO,
|
||||||
|
"If you are behind a proxy you may need to configure dependency-check to use the proxy.");
|
||||||
|
}
|
||||||
LOGGER.log(Level.FINE, null, ex);
|
LOGGER.log(Level.FINE, null, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.owasp.dependencycheck.data.update.exception.InvalidDataException;
|
|||||||
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||||
import org.owasp.dependencycheck.data.update.task.DownloadTask;
|
import org.owasp.dependencycheck.data.update.task.DownloadTask;
|
||||||
import org.owasp.dependencycheck.data.update.task.ProcessTask;
|
import org.owasp.dependencycheck.data.update.task.ProcessTask;
|
||||||
|
import org.owasp.dependencycheck.utils.DateUtil;
|
||||||
import org.owasp.dependencycheck.utils.DownloadFailedException;
|
import org.owasp.dependencycheck.utils.DownloadFailedException;
|
||||||
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||||
import org.owasp.dependencycheck.utils.Settings;
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
@@ -220,7 +221,7 @@ public class StandardUpdate {
|
|||||||
final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 7);
|
final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 7);
|
||||||
if (lastUpdated == updates.getTimeStamp(MODIFIED)) {
|
if (lastUpdated == updates.getTimeStamp(MODIFIED)) {
|
||||||
updates.clear(); //we don't need to update anything.
|
updates.clear(); //we don't need to update anything.
|
||||||
} else if (withinRange(lastUpdated, now.getTime(), days)) {
|
} else if (DateUtil.withinDateRange(lastUpdated, now.getTime(), days)) {
|
||||||
for (NvdCveInfo entry : updates) {
|
for (NvdCveInfo entry : updates) {
|
||||||
if (MODIFIED.equals(entry.getId())) {
|
if (MODIFIED.equals(entry.getId())) {
|
||||||
entry.setNeedsUpdate(true);
|
entry.setNeedsUpdate(true);
|
||||||
@@ -317,19 +318,4 @@ public class StandardUpdate {
|
|||||||
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
|
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if the epoch date is within the range specified of the compareTo epoch time. This takes the
|
|
||||||
* (compareTo-date)/1000/60/60/24 to get the number of days. If the calculated days is less then the range the date
|
|
||||||
* is considered valid.
|
|
||||||
*
|
|
||||||
* @param date the date to be checked.
|
|
||||||
* @param compareTo the date to compare to.
|
|
||||||
* @param range the range in days to be considered valid.
|
|
||||||
* @return whether or not the date is within the range.
|
|
||||||
*/
|
|
||||||
protected boolean withinRange(long date, long compareTo, int range) {
|
|
||||||
final double differenceInDays = (compareTo - date) / 1000.0 / 60.0 / 60.0 / 24.0;
|
|
||||||
return differenceInDays < range;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
package org.owasp.dependencycheck.data.update.task;
|
package org.owasp.dependencycheck.data.update.task;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
@@ -25,6 +28,8 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
import org.owasp.dependencycheck.data.update.NvdCveInfo;
|
import org.owasp.dependencycheck.data.update.NvdCveInfo;
|
||||||
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||||
@@ -188,13 +193,25 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
|||||||
} catch (DownloadFailedException ex) {
|
} catch (DownloadFailedException ex) {
|
||||||
msg = String.format("Download Failed for NVD CVE - %s%nSome CVEs may not be reported.", nvdCveInfo.getId());
|
msg = String.format("Download Failed for NVD CVE - %s%nSome CVEs may not be reported.", nvdCveInfo.getId());
|
||||||
LOGGER.log(Level.WARNING, msg);
|
LOGGER.log(Level.WARNING, msg);
|
||||||
|
if (Settings.getString(Settings.KEYS.PROXY_SERVER) == null) {
|
||||||
|
LOGGER.log(Level.INFO,
|
||||||
|
"If you are behind a proxy you may need to configure dependency-check to use the proxy.");
|
||||||
|
}
|
||||||
LOGGER.log(Level.FINE, null, ex);
|
LOGGER.log(Level.FINE, null, ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (url1.toExternalForm().endsWith(".xml.gz")) {
|
||||||
|
extractGzip(first);
|
||||||
|
}
|
||||||
|
if (url2.toExternalForm().endsWith(".xml.gz")) {
|
||||||
|
extractGzip(second);
|
||||||
|
}
|
||||||
|
|
||||||
msg = String.format("Download Complete for NVD CVE - %s", nvdCveInfo.getId());
|
msg = String.format("Download Complete for NVD CVE - %s", nvdCveInfo.getId());
|
||||||
LOGGER.log(Level.INFO, msg);
|
LOGGER.log(Level.INFO, msg);
|
||||||
|
if (this.processorService == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final ProcessTask task = new ProcessTask(cveDB, this, settings);
|
final ProcessTask task = new ProcessTask(cveDB, this, settings);
|
||||||
return this.processorService.submit(task);
|
return this.processorService.submit(task);
|
||||||
|
|
||||||
@@ -233,4 +250,56 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the file contained in a gzip archive. The extracted file is placed in the exact same path as the file
|
||||||
|
* specified.
|
||||||
|
*
|
||||||
|
* @param file the archive file
|
||||||
|
* @throws FileNotFoundException thrown if the file does not exist
|
||||||
|
* @throws IOException thrown if there is an error extracting the file.
|
||||||
|
*/
|
||||||
|
private void extractGzip(File file) throws FileNotFoundException, IOException {
|
||||||
|
final String originalPath = file.getPath();
|
||||||
|
final File gzip = new File(originalPath + ".gz");
|
||||||
|
if (gzip.isFile() && !gzip.delete()) {
|
||||||
|
gzip.deleteOnExit();
|
||||||
|
}
|
||||||
|
if (!file.renameTo(gzip)) {
|
||||||
|
throw new IOException("Unable to rename '" + file.getPath() + "'");
|
||||||
|
}
|
||||||
|
final File newfile = new File(originalPath);
|
||||||
|
|
||||||
|
final byte[] buffer = new byte[4096];
|
||||||
|
|
||||||
|
GZIPInputStream cin = null;
|
||||||
|
FileOutputStream out = null;
|
||||||
|
try {
|
||||||
|
cin = new GZIPInputStream(new FileInputStream(gzip));
|
||||||
|
out = new FileOutputStream(newfile);
|
||||||
|
|
||||||
|
int len;
|
||||||
|
while ((len = cin.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (cin != null) {
|
||||||
|
try {
|
||||||
|
cin.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.FINEST, "ignore", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (out != null) {
|
||||||
|
try {
|
||||||
|
out.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.FINEST, "ignore", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gzip.isFile()) {
|
||||||
|
FileUtils.deleteQuietly(gzip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,14 @@ package org.owasp.dependencycheck.dependency;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
|
||||||
import org.owasp.dependencycheck.utils.Checksum;
|
import org.owasp.dependencycheck.utils.Checksum;
|
||||||
import org.owasp.dependencycheck.utils.FileUtils;
|
import org.owasp.dependencycheck.utils.FileUtils;
|
||||||
|
|
||||||
@@ -35,7 +37,7 @@ import org.owasp.dependencycheck.utils.FileUtils;
|
|||||||
*
|
*
|
||||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
*/
|
*/
|
||||||
public class Dependency implements Comparable<Dependency> {
|
public class Dependency implements Serializable, Comparable<Dependency> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logger.
|
* The logger.
|
||||||
@@ -315,6 +317,41 @@ public class Dependency implements Comparable<Dependency> {
|
|||||||
this.identifiers.add(i);
|
this.identifiers.add(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the maven artifact as evidence.
|
||||||
|
*
|
||||||
|
* @param source The source of the evidence
|
||||||
|
* @param mavenArtifact The maven artifact
|
||||||
|
* @param confidence The confidence level of this evidence
|
||||||
|
*/
|
||||||
|
public void addAsEvidence(String source, MavenArtifact mavenArtifact, Confidence confidence) {
|
||||||
|
if (mavenArtifact.getGroupId() != null && !mavenArtifact.getGroupId().isEmpty()) {
|
||||||
|
this.getVendorEvidence().addEvidence(source, "groupid", mavenArtifact.getGroupId(), confidence);
|
||||||
|
}
|
||||||
|
if (mavenArtifact.getArtifactId() != null && !mavenArtifact.getArtifactId().isEmpty()) {
|
||||||
|
this.getProductEvidence().addEvidence(source, "artifactid", mavenArtifact.getArtifactId(), confidence);
|
||||||
|
}
|
||||||
|
if (mavenArtifact.getVersion() != null && !mavenArtifact.getVersion().isEmpty()) {
|
||||||
|
this.getVersionEvidence().addEvidence(source, "version", mavenArtifact.getVersion(), confidence);
|
||||||
|
}
|
||||||
|
if (mavenArtifact.getArtifactUrl() != null && !mavenArtifact.getArtifactUrl().isEmpty()) {
|
||||||
|
boolean found = false;
|
||||||
|
for (Identifier i : this.getIdentifiers()) {
|
||||||
|
if ("maven".equals(i.getType()) && i.getValue().equals(mavenArtifact.toString())) {
|
||||||
|
found = true;
|
||||||
|
i.setConfidence(Confidence.HIGHEST);
|
||||||
|
i.setUrl(mavenArtifact.getArtifactUrl());
|
||||||
|
LOGGER.fine(String.format("Already found identifier %s. Confidence set to highest", i.getValue()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
LOGGER.fine(String.format("Adding new maven identifier %s", mavenArtifact.toString()));
|
||||||
|
this.addIdentifier("maven", mavenArtifact.toString(), mavenArtifact.getArtifactUrl(), Confidence.HIGHEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an entry to the list of detected Identifiers for the dependency file.
|
* Adds an entry to the list of detected Identifiers for the dependency file.
|
||||||
*
|
*
|
||||||
@@ -323,6 +360,7 @@ public class Dependency implements Comparable<Dependency> {
|
|||||||
public void addIdentifier(Identifier identifier) {
|
public void addIdentifier(Identifier identifier) {
|
||||||
this.identifiers.add(identifier);
|
this.identifiers.add(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of identifiers that have been suppressed.
|
* A set of identifiers that have been suppressed.
|
||||||
*/
|
*/
|
||||||
@@ -440,6 +478,7 @@ public class Dependency implements Comparable<Dependency> {
|
|||||||
public EvidenceCollection getVersionEvidence() {
|
public EvidenceCollection getVersionEvidence() {
|
||||||
return this.versionEvidence;
|
return this.versionEvidence;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The description of the JAR file.
|
* The description of the JAR file.
|
||||||
*/
|
*/
|
||||||
@@ -462,6 +501,7 @@ public class Dependency implements Comparable<Dependency> {
|
|||||||
public void setDescription(String description) {
|
public void setDescription(String description) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The license that this dependency uses.
|
* The license that this dependency uses.
|
||||||
*/
|
*/
|
||||||
@@ -484,6 +524,7 @@ public class Dependency implements Comparable<Dependency> {
|
|||||||
public void setLicense(String license) {
|
public void setLicense(String license) {
|
||||||
this.license = license;
|
this.license = license;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of vulnerabilities for this dependency.
|
* A list of vulnerabilities for this dependency.
|
||||||
*/
|
*/
|
||||||
@@ -539,6 +580,7 @@ public class Dependency implements Comparable<Dependency> {
|
|||||||
public void addVulnerability(Vulnerability vulnerability) {
|
public void addVulnerability(Vulnerability vulnerability) {
|
||||||
this.vulnerabilities.add(vulnerability);
|
this.vulnerabilities.add(vulnerability);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of related dependencies.
|
* A collection of related dependencies.
|
||||||
*/
|
*/
|
||||||
@@ -568,7 +610,14 @@ public class Dependency implements Comparable<Dependency> {
|
|||||||
* @param dependency a reference to the related dependency
|
* @param dependency a reference to the related dependency
|
||||||
*/
|
*/
|
||||||
public void addRelatedDependency(Dependency dependency) {
|
public void addRelatedDependency(Dependency dependency) {
|
||||||
relatedDependencies.add(dependency);
|
if (this == dependency) {
|
||||||
|
LOGGER.warning("Attempted to add a circular reference - please post the log file to issue #172 here "
|
||||||
|
+ "https://github.com/jeremylong/DependencyCheck/issues/172 ");
|
||||||
|
LOGGER.log(Level.FINE, "this: {0}", this.toString());
|
||||||
|
LOGGER.log(Level.FINE, "dependency: {0}", dependency.toString());
|
||||||
|
} else {
|
||||||
|
relatedDependencies.add(dependency);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -578,7 +627,7 @@ public class Dependency implements Comparable<Dependency> {
|
|||||||
* @return an integer representing the natural ordering
|
* @return an integer representing the natural ordering
|
||||||
*/
|
*/
|
||||||
public int compareTo(Dependency o) {
|
public int compareTo(Dependency o) {
|
||||||
return this.getFileName().compareToIgnoreCase(o.getFileName());
|
return this.getFilePath().compareToIgnoreCase(o.getFilePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,12 +17,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.dependency;
|
package org.owasp.dependencycheck.dependency;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evidence is a piece of information about a Dependency.
|
* Evidence is a piece of information about a Dependency.
|
||||||
*
|
*
|
||||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
*/
|
*/
|
||||||
public class Evidence implements Comparable<Evidence> {
|
public class Evidence implements Serializable, Comparable<Evidence> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Evidence object.
|
* Creates a new Evidence object.
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.dependency;
|
package org.owasp.dependencycheck.dependency;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -36,7 +37,7 @@ import org.owasp.dependencycheck.utils.UrlStringUtils;
|
|||||||
*
|
*
|
||||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
*/
|
*/
|
||||||
public class EvidenceCollection implements Iterable<Evidence> {
|
public class EvidenceCollection implements Serializable, Iterable<Evidence> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logger.
|
* The logger.
|
||||||
|
|||||||
@@ -17,11 +17,22 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.dependency;
|
package org.owasp.dependencycheck.dependency;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
*/
|
*/
|
||||||
public class Identifier implements Comparable<Identifier> {
|
public class Identifier implements Serializable, Comparable<Identifier> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor. Should only be used for automatic class
|
||||||
|
* creation as is the case with many XML parsers (for the parsing
|
||||||
|
* of the Dependency-Check XML report). For all other use-cases,
|
||||||
|
* please use the non-default constructors.
|
||||||
|
*/
|
||||||
|
public Identifier() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new Identifier with the specified data.
|
* Constructs a new Identifier with the specified data.
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class ScanAgentException extends IOException {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new NoDataException.
|
* Creates a new ScanAgentException.
|
||||||
*
|
*
|
||||||
* @param ex the cause of the exception.
|
* @param ex the cause of the exception.
|
||||||
*/
|
*/
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -113,7 +113,7 @@ public class ReportGenerator {
|
|||||||
context.put("scanDate", scanDate);
|
context.put("scanDate", scanDate);
|
||||||
context.put("scanDateXML", scanDateXML);
|
context.put("scanDateXML", scanDateXML);
|
||||||
context.put("enc", enc);
|
context.put("enc", enc);
|
||||||
context.put("version", Settings.getString("application.version", "Unknown"));
|
context.put("version", Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,6 +137,26 @@ public class ReportGenerator {
|
|||||||
return new VelocityContext();
|
return new VelocityContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the Dependency Reports for the identified dependencies.
|
||||||
|
*
|
||||||
|
* @param outputStream the OutputStream to send the generated report to
|
||||||
|
* @param format the format the report should be written in
|
||||||
|
* @throws IOException is thrown when the template file does not exist
|
||||||
|
* @throws Exception is thrown if there is an error writing out the reports.
|
||||||
|
*/
|
||||||
|
public void generateReports(OutputStream outputStream, Format format) throws IOException, Exception {
|
||||||
|
if (format == Format.XML || format == Format.ALL) {
|
||||||
|
generateReport("XmlReport", outputStream);
|
||||||
|
}
|
||||||
|
if (format == Format.HTML || format == Format.ALL) {
|
||||||
|
generateReport("HtmlReport", outputStream);
|
||||||
|
}
|
||||||
|
if (format == Format.VULN || format == Format.ALL) {
|
||||||
|
generateReport("VulnerabilityReport", outputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the Dependency Reports for the identified dependencies.
|
* Generates the Dependency Reports for the identified dependencies.
|
||||||
*
|
*
|
||||||
@@ -167,15 +187,28 @@ public class ReportGenerator {
|
|||||||
*/
|
*/
|
||||||
public void generateReports(String outputDir, String outputFormat) throws IOException, Exception {
|
public void generateReports(String outputDir, String outputFormat) throws IOException, Exception {
|
||||||
final String format = outputFormat.toUpperCase();
|
final String format = outputFormat.toUpperCase();
|
||||||
|
final String pathToCheck = outputDir.toLowerCase();
|
||||||
if (format.matches("^(XML|HTML|VULN|ALL)$")) {
|
if (format.matches("^(XML|HTML|VULN|ALL)$")) {
|
||||||
if ("XML".equalsIgnoreCase(format)) {
|
if ("XML".equalsIgnoreCase(format)) {
|
||||||
generateReports(outputDir, Format.XML);
|
if (pathToCheck.endsWith(".xml")) {
|
||||||
|
generateReport("XmlReport", outputDir);
|
||||||
|
} else {
|
||||||
|
generateReports(outputDir, Format.XML);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ("HTML".equalsIgnoreCase(format)) {
|
if ("HTML".equalsIgnoreCase(format)) {
|
||||||
generateReports(outputDir, Format.HTML);
|
if (pathToCheck.endsWith(".html") || pathToCheck.endsWith(".htm")) {
|
||||||
|
generateReport("HtmlReport", outputDir);
|
||||||
|
} else {
|
||||||
|
generateReports(outputDir, Format.HTML);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ("VULN".equalsIgnoreCase(format)) {
|
if ("VULN".equalsIgnoreCase(format)) {
|
||||||
generateReports(outputDir, Format.VULN);
|
if (pathToCheck.endsWith(".html") || pathToCheck.endsWith(".htm")) {
|
||||||
|
generateReport("VulnReport", outputDir);
|
||||||
|
} else {
|
||||||
|
generateReports(outputDir, Format.VULN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ("ALL".equalsIgnoreCase(format)) {
|
if ("ALL".equalsIgnoreCase(format)) {
|
||||||
generateReports(outputDir, Format.ALL);
|
generateReports(outputDir, Format.ALL);
|
||||||
@@ -189,11 +222,11 @@ public class ReportGenerator {
|
|||||||
* template file.
|
* template file.
|
||||||
*
|
*
|
||||||
* @param templateName the name of the template to load.
|
* @param templateName the name of the template to load.
|
||||||
* @param outFileName the filename and path to write the report to.
|
* @param outputStream the OutputStream to write the report to.
|
||||||
* @throws IOException is thrown when the template file does not exist.
|
* @throws IOException is thrown when the template file does not exist.
|
||||||
* @throws Exception is thrown when an exception occurs.
|
* @throws Exception is thrown when an exception occurs.
|
||||||
*/
|
*/
|
||||||
protected void generateReport(String templateName, String outFileName) throws IOException, Exception {
|
protected void generateReport(String templateName, OutputStream outputStream) throws IOException, Exception {
|
||||||
InputStream input = null;
|
InputStream input = null;
|
||||||
String templatePath = null;
|
String templatePath = null;
|
||||||
final File f = new File(templateName);
|
final File f = new File(templateName);
|
||||||
@@ -216,18 +249,8 @@ public class ReportGenerator {
|
|||||||
|
|
||||||
final InputStreamReader reader = new InputStreamReader(input, "UTF-8");
|
final InputStreamReader reader = new InputStreamReader(input, "UTF-8");
|
||||||
OutputStreamWriter writer = null;
|
OutputStreamWriter writer = null;
|
||||||
OutputStream outputStream = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final File outDir = new File(outFileName).getParentFile();
|
|
||||||
if (!outDir.exists()) {
|
|
||||||
final boolean created = outDir.mkdirs();
|
|
||||||
if (!created) {
|
|
||||||
throw new Exception("Unable to create directory '" + outDir.getAbsolutePath() + "'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
outputStream = new FileOutputStream(outFileName);
|
|
||||||
writer = new OutputStreamWriter(outputStream, "UTF-8");
|
writer = new OutputStreamWriter(outputStream, "UTF-8");
|
||||||
|
|
||||||
if (!engine.evaluate(context, writer, templatePath, reader)) {
|
if (!engine.evaluate(context, writer, templatePath, reader)) {
|
||||||
@@ -256,4 +279,41 @@ public class ReportGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a report from a given Velocity Template. The template name provided can be the name of a template
|
||||||
|
* contained in the jar file, such as 'XmlReport' or 'HtmlReport', or the template name can be the path to a
|
||||||
|
* template file.
|
||||||
|
*
|
||||||
|
* @param templateName the name of the template to load.
|
||||||
|
* @param outFileName the filename and path to write the report to.
|
||||||
|
* @throws IOException is thrown when the template file does not exist.
|
||||||
|
* @throws Exception is thrown when an exception occurs.
|
||||||
|
*/
|
||||||
|
protected void generateReport(String templateName, String outFileName) throws Exception {
|
||||||
|
File outFile = new File(outFileName);
|
||||||
|
if (outFile.getParentFile() == null) {
|
||||||
|
outFile = new File(".", outFileName);
|
||||||
|
}
|
||||||
|
if (!outFile.getParentFile().exists()) {
|
||||||
|
final boolean created = outFile.getParentFile().mkdirs();
|
||||||
|
if (!created) {
|
||||||
|
throw new Exception("Unable to create directory '" + outFile.getParentFile().getAbsolutePath() + "'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputStream outputSteam = null;
|
||||||
|
try {
|
||||||
|
outputSteam = new FileOutputStream(outFile);
|
||||||
|
generateReport(templateName, outputSteam);
|
||||||
|
} finally {
|
||||||
|
if (outputSteam != null) {
|
||||||
|
try {
|
||||||
|
outputSteam.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.FINEST, "ignore", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,6 +103,12 @@ public class SuppressionHandler extends DefaultHandler {
|
|||||||
currentText = new StringBuffer();
|
currentText = new StringBuffer();
|
||||||
if (SUPPRESS.equals(qName)) {
|
if (SUPPRESS.equals(qName)) {
|
||||||
rule = new SuppressionRule();
|
rule = new SuppressionRule();
|
||||||
|
final String base = currentAttributes.getValue("base");
|
||||||
|
if (base != null) {
|
||||||
|
rule.setBase(Boolean.parseBoolean(base));
|
||||||
|
} else {
|
||||||
|
rule.setBase(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,11 +26,6 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public class SuppressionParseException extends IOException {
|
public class SuppressionParseException extends IOException {
|
||||||
|
|
||||||
/**
|
|
||||||
* The serial version UID.
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new SuppressionParseException.
|
* Creates a new SuppressionParseException.
|
||||||
*/
|
*/
|
||||||
@@ -50,7 +45,7 @@ public class SuppressionParseException extends IOException {
|
|||||||
/**
|
/**
|
||||||
* Creates a new SuppressionParseException.
|
* Creates a new SuppressionParseException.
|
||||||
*
|
*
|
||||||
* @param ex the cause of the download failure.
|
* @param ex the cause of the parse exception
|
||||||
*/
|
*/
|
||||||
public SuppressionParseException(Throwable ex) {
|
public SuppressionParseException(Throwable ex) {
|
||||||
super(ex);
|
super(ex);
|
||||||
@@ -60,7 +55,7 @@ public class SuppressionParseException extends IOException {
|
|||||||
* Creates a new SuppressionParseException.
|
* Creates a new SuppressionParseException.
|
||||||
*
|
*
|
||||||
* @param msg a message for the exception.
|
* @param msg a message for the exception.
|
||||||
* @param ex the cause of the download failure.
|
* @param ex the cause of the parse exception
|
||||||
*/
|
*/
|
||||||
public SuppressionParseException(String msg, Throwable ex) {
|
public SuppressionParseException(String msg, Throwable ex) {
|
||||||
super(msg, ex);
|
super(msg, ex);
|
||||||
|
|||||||
@@ -27,11 +27,9 @@ import java.io.Reader;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.parsers.SAXParser;
|
import javax.xml.parsers.SAXParser;
|
||||||
import javax.xml.parsers.SAXParserFactory;
|
import javax.xml.parsers.SAXParserFactory;
|
||||||
|
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import org.xml.sax.XMLReader;
|
import org.xml.sax.XMLReader;
|
||||||
@@ -68,17 +66,27 @@ public class SuppressionParser {
|
|||||||
* @throws SuppressionParseException thrown if the xml file cannot be parsed
|
* @throws SuppressionParseException thrown if the xml file cannot be parsed
|
||||||
*/
|
*/
|
||||||
public List<SuppressionRule> parseSuppressionRules(File file) throws SuppressionParseException {
|
public List<SuppressionRule> parseSuppressionRules(File file) throws SuppressionParseException {
|
||||||
|
FileInputStream fis = null;
|
||||||
try {
|
try {
|
||||||
return parseSuppressionRules(new FileInputStream(file));
|
fis = new FileInputStream(file);
|
||||||
|
return parseSuppressionRules(fis);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.log(Level.FINE, null, ex);
|
LOGGER.log(Level.FINE, null, ex);
|
||||||
throw new SuppressionParseException(ex);
|
throw new SuppressionParseException(ex);
|
||||||
|
} finally {
|
||||||
|
if (fis != null) {
|
||||||
|
try {
|
||||||
|
fis.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.FINE, "Unable to close stream", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the given xml stream and returns a list of the suppression rules contained.
|
* Parses the given xml stream and returns a list of the suppression rules contained.
|
||||||
*
|
*
|
||||||
* @param inputStream an InputStream containing suppression rues
|
* @param inputStream an InputStream containing suppression rues
|
||||||
* @return a list of suppression rules
|
* @return a list of suppression rules
|
||||||
* @throws SuppressionParseException if the xml cannot be parsed
|
* @throws SuppressionParseException if the xml cannot be parsed
|
||||||
|
|||||||
@@ -266,6 +266,30 @@ public class SuppressionRule {
|
|||||||
return gav != null;
|
return gav != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A flag indicating whether or not the suppression rule is a core/base rule that should not be included in the
|
||||||
|
* resulting report in the "suppressed" section.
|
||||||
|
*/
|
||||||
|
private boolean base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of base.
|
||||||
|
*
|
||||||
|
* @return the value of base
|
||||||
|
*/
|
||||||
|
public boolean isBase() {
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of base.
|
||||||
|
*
|
||||||
|
* @param base new value of base
|
||||||
|
*/
|
||||||
|
public void setBase(boolean base) {
|
||||||
|
this.base = base;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a given dependency to determine if any CPE, CVE, CWE, or CVSS scores should be suppressed. If any
|
* Processes a given dependency to determine if any CPE, CVE, CWE, or CVSS scores should be suppressed. If any
|
||||||
* should be, they are removed from the dependency.
|
* should be, they are removed from the dependency.
|
||||||
@@ -300,7 +324,9 @@ public class SuppressionRule {
|
|||||||
final Identifier i = itr.next();
|
final Identifier i = itr.next();
|
||||||
for (PropertyType c : this.cpe) {
|
for (PropertyType c : this.cpe) {
|
||||||
if (identifierMatches("cpe", c, i)) {
|
if (identifierMatches("cpe", c, i)) {
|
||||||
dependency.addSuppressedIdentifier(i);
|
if (!isBase()) {
|
||||||
|
dependency.addSuppressedIdentifier(i);
|
||||||
|
}
|
||||||
itr.remove();
|
itr.remove();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -339,7 +365,9 @@ public class SuppressionRule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (remove) {
|
if (remove) {
|
||||||
dependency.addSuppressedVulnerability(v);
|
if (!isBase()) {
|
||||||
|
dependency.addSuppressedVulnerability(v);
|
||||||
|
}
|
||||||
itr.remove();
|
itr.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,9 @@ public final class DBUtils {
|
|||||||
int id = 0;
|
int id = 0;
|
||||||
try {
|
try {
|
||||||
rs = statement.getGeneratedKeys();
|
rs = statement.getGeneratedKeys();
|
||||||
rs.next();
|
if (!rs.next()) {
|
||||||
|
throw new DatabaseException("Unable to get primary key for inserted row");
|
||||||
|
}
|
||||||
id = rs.getInt(1);
|
id = rs.getInt(1);
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
throw new DatabaseException("Unable to get primary key for inserted row");
|
throw new DatabaseException("Unable to get primary key for inserted row");
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
public final class DateUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor for utility class.
|
||||||
|
*/
|
||||||
|
private DateUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the epoch date is within the range specified of the compareTo epoch time. This takes the
|
||||||
|
* (compareTo-date)/1000/60/60/24 to get the number of days. If the calculated days is less then the range the date
|
||||||
|
* is considered valid.
|
||||||
|
*
|
||||||
|
* @param date the date to be checked.
|
||||||
|
* @param compareTo the date to compare to.
|
||||||
|
* @param range the range in days to be considered valid.
|
||||||
|
* @return whether or not the date is within the range.
|
||||||
|
*/
|
||||||
|
public static boolean withinDateRange(long date, long compareTo, int range) {
|
||||||
|
final double differenceInDays = (compareTo - date) / 1000.0 / 60.0 / 60.0 / 24.0;
|
||||||
|
return differenceInDays < range;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -65,7 +65,7 @@ public class DependencyVersion implements Iterable, Comparable<DependencyVersion
|
|||||||
public final void parseVersion(String version) {
|
public final void parseVersion(String version) {
|
||||||
versionParts = new ArrayList<String>();
|
versionParts = new ArrayList<String>();
|
||||||
if (version != null) {
|
if (version != null) {
|
||||||
final Pattern rx = Pattern.compile("(\\d+|[a-z]+\\d+|(release|beta|alpha)$)");
|
final Pattern rx = Pattern.compile("(\\d+[a-z]{1,3}$|[a-z]+\\d+|\\d+|(release|beta|alpha)$)");
|
||||||
final Matcher matcher = rx.matcher(version.toLowerCase());
|
final Matcher matcher = rx.matcher(version.toLowerCase());
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
versionParts.add(matcher.group());
|
versionParts.add(matcher.group());
|
||||||
@@ -189,17 +189,23 @@ public class DependencyVersion implements Iterable, Comparable<DependencyVersion
|
|||||||
if (version == null) {
|
if (version == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (Math.abs(this.versionParts.size() - version.versionParts.size()) >= 3) {
|
||||||
boolean ret = true;
|
return false;
|
||||||
int max = (this.versionParts.size() < version.versionParts.size())
|
|
||||||
? this.versionParts.size() : version.versionParts.size();
|
|
||||||
|
|
||||||
if (max > 3) {
|
|
||||||
max = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int max = (this.versionParts.size() < version.versionParts.size())
|
||||||
|
? this.versionParts.size() : version.versionParts.size();
|
||||||
|
|
||||||
|
boolean ret = true;
|
||||||
for (int i = 0; i < max; i++) {
|
for (int i = 0; i < max; i++) {
|
||||||
if (this.versionParts.get(i) == null || !this.versionParts.get(i).equals(version.versionParts.get(i))) {
|
final String thisVersion = this.versionParts.get(i);
|
||||||
|
final String otherVersion = version.getVersionParts().get(i);
|
||||||
|
if (i >= 3) {
|
||||||
|
if (thisVersion.compareToIgnoreCase(otherVersion) >= 0) {
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (!thisVersion.equals(otherVersion)) {
|
||||||
ret = false;
|
ret = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public final class DependencyVersionUtil {
|
|||||||
/**
|
/**
|
||||||
* Regular expression to extract version numbers from file names.
|
* Regular expression to extract version numbers from file names.
|
||||||
*/
|
*/
|
||||||
private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?");
|
private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?");
|
||||||
/**
|
/**
|
||||||
* Regular expression to extract a single version number without periods. This is a last ditch effort just to check
|
* Regular expression to extract a single version number without periods. This is a last ditch effort just to check
|
||||||
* in case we are missing a version number using the previous regex.
|
* in case we are missing a version number using the previous regex.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ org.owasp.dependencycheck.analyzer.CpeSuppressionAnalyzer
|
|||||||
org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer
|
org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer
|
||||||
org.owasp.dependencycheck.analyzer.NvdCveAnalyzer
|
org.owasp.dependencycheck.analyzer.NvdCveAnalyzer
|
||||||
org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer
|
org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer
|
||||||
|
org.owasp.dependencycheck.analyzer.CentralAnalyzer
|
||||||
org.owasp.dependencycheck.analyzer.NexusAnalyzer
|
org.owasp.dependencycheck.analyzer.NexusAnalyzer
|
||||||
org.owasp.dependencycheck.analyzer.NuspecAnalyzer
|
org.owasp.dependencycheck.analyzer.NuspecAnalyzer
|
||||||
org.owasp.dependencycheck.analyzer.AssemblyAnalyzer
|
org.owasp.dependencycheck.analyzer.AssemblyAnalyzer
|
||||||
@@ -1 +1,2 @@
|
|||||||
org.owasp.dependencycheck.data.update.NvdCveUpdater
|
org.owasp.dependencycheck.data.update.NvdCveUpdater
|
||||||
|
org.owasp.dependencycheck.data.update.EngineVersionCheck
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression">
|
<suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression">
|
||||||
<suppress>
|
<suppress base="true">
|
||||||
<notes><![CDATA[
|
<notes><![CDATA[
|
||||||
This suppresses false positives identified on spring security.
|
This suppresses false positives identified on spring security.
|
||||||
]]></notes>
|
]]></notes>
|
||||||
@@ -9,4 +9,57 @@
|
|||||||
<cpe>cpe:/a:springsource:spring_framework</cpe>
|
<cpe>cpe:/a:springsource:spring_framework</cpe>
|
||||||
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
|
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
|
||||||
</suppress>
|
</suppress>
|
||||||
|
<suppress base="true">
|
||||||
|
<notes><![CDATA[
|
||||||
|
This suppresses false positives identified on spring security.
|
||||||
|
]]></notes>
|
||||||
|
<filePath regex="true">.*spring-security-[^\\/]*\.jar$</filePath>
|
||||||
|
<cpe>cpe:/a:mod_security:mod_security</cpe>
|
||||||
|
<cpe>cpe:/a:springsource:spring_framework</cpe>
|
||||||
|
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
|
||||||
|
</suppress>
|
||||||
|
<suppress base="true">
|
||||||
|
<notes><![CDATA[
|
||||||
|
This suppreses additional false positives for the xstream library that occur because spring has a copy of this library.
|
||||||
|
com.springsource.com.thoughtworks.xstream-1.3.1.jar
|
||||||
|
]]></notes>
|
||||||
|
<gav regex="true">com\.thoughtworks\.xstream:xstream:.*</gav>
|
||||||
|
<cpe>cpe:/a:springsource:spring_framework</cpe>
|
||||||
|
</suppress>
|
||||||
|
<suppress base="true">
|
||||||
|
<notes><![CDATA[
|
||||||
|
Suppresses false positives on velocity tools.
|
||||||
|
]]></notes>
|
||||||
|
<gav regex="true">org\.apache\.velocity:velocity-tools:.*</gav>
|
||||||
|
<cpe>cpe:/a:apache:struts</cpe>
|
||||||
|
</suppress>
|
||||||
|
<suppress base="true">
|
||||||
|
<notes><![CDATA[
|
||||||
|
Sandbox is a php blog platform and should not be flagged as a CPE for java or .net dependencies.
|
||||||
|
]]></notes>
|
||||||
|
<filePath regex="true">.*\.(jar|dll|exe|ear|war|pom)</filePath>
|
||||||
|
<cpe>cpe:/a:sandbox:sandbox</cpe>
|
||||||
|
</suppress>
|
||||||
|
<suppress base="true">
|
||||||
|
<notes><![CDATA[
|
||||||
|
Suppresses false positives on Jersey core client.
|
||||||
|
]]></notes>
|
||||||
|
<gav regex="true">(com\.sun\.jersey|org\.glassfish\.jersey\.core):jersey-(client|common):.*</gav>
|
||||||
|
<cpe>cpe:/a:oracle:glassfish</cpe>
|
||||||
|
<cpe>cpe:/a:oracle:oracle_client</cpe>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<notes><![CDATA[
|
||||||
|
Suppresses false positives on the grizzly-framework
|
||||||
|
]]></notes>
|
||||||
|
<gav regex="true">org\.glassfish\.grizzly:grizzly-framework:.*</gav>
|
||||||
|
<cpe>cpe:/a:oracle:glassfish</cpe>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<notes><![CDATA[
|
||||||
|
Suppresses false positives on the grizzly-framework
|
||||||
|
]]></notes>
|
||||||
|
<gav regex="true">org\.forgerock\.opendj:opendj-ldap-sdk:.*</gav>
|
||||||
|
<cpe>cpe:/a:ldap_project:ldap</cpe>
|
||||||
|
</suppress>
|
||||||
</suppressions>
|
</suppressions>
|
||||||
@@ -3,6 +3,9 @@ application.version=${pom.version}
|
|||||||
autoupdate=true
|
autoupdate=true
|
||||||
max.download.threads=3
|
max.download.threads=3
|
||||||
|
|
||||||
|
# the url to obtain the current engine version from
|
||||||
|
engine.version.url=http://jeremylong.github.io/DependencyCheck/current.txt
|
||||||
|
|
||||||
#temp.directory defaults to System.getProperty("java.io.tmpdir")
|
#temp.directory defaults to System.getProperty("java.io.tmpdir")
|
||||||
#temp.directory=[path to temp directory]
|
#temp.directory=[path to temp directory]
|
||||||
|
|
||||||
@@ -13,8 +16,10 @@ max.download.threads=3
|
|||||||
# will not be used. The data.directory will be resolved and if the connection string
|
# will not be used. The data.directory will be resolved and if the connection string
|
||||||
# below contains a %s then the data.directory will replace the %s.
|
# below contains a %s then the data.directory will replace the %s.
|
||||||
data.directory=[JAR]/data
|
data.directory=[JAR]/data
|
||||||
|
#if the filename has a %s it will be replaced with the current expected version
|
||||||
|
data.file_name=cve.%s.h2.db
|
||||||
|
data.version=2.9
|
||||||
data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
|
data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
|
||||||
#data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;AUTOCOMMIT=ON;
|
|
||||||
#data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
|
#data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
|
||||||
|
|
||||||
# user name and password for the database connection. The inherent case is to use H2.
|
# user name and password for the database connection. The inherent case is to use H2.
|
||||||
@@ -38,11 +43,16 @@ data.driver_path=
|
|||||||
cve.url.modified.validfordays=7
|
cve.url.modified.validfordays=7
|
||||||
|
|
||||||
# the path to the modified nvd cve xml file.
|
# the path to the modified nvd cve xml file.
|
||||||
cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
|
cve.url-1.2.modified=https://nvd.nist.gov/download/nvdcve-Modified.xml.gz
|
||||||
cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
|
#cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
|
||||||
|
cve.url-2.0.modified=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz
|
||||||
|
#cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
|
||||||
cve.startyear=2002
|
cve.startyear=2002
|
||||||
cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
|
cve.url-1.2.base=https://nvd.nist.gov/download/nvdcve-%d.xml.gz
|
||||||
cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
|
#cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
|
||||||
|
cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz
|
||||||
|
#cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
|
||||||
|
|
||||||
|
|
||||||
# file type analyzer settings:
|
# file type analyzer settings:
|
||||||
analyzer.archive.enabled=true
|
analyzer.archive.enabled=true
|
||||||
@@ -56,3 +66,7 @@ analyzer.nexus.url=https://repository.sonatype.org/service/local/
|
|||||||
# If set to true, the proxy will still ONLY be used if the proxy properties (proxy.url, proxy.port)
|
# If set to true, the proxy will still ONLY be used if the proxy properties (proxy.url, proxy.port)
|
||||||
# are configured
|
# are configured
|
||||||
analyzer.nexus.proxy=true
|
analyzer.nexus.proxy=true
|
||||||
|
|
||||||
|
# the URL for searching search.maven.org for SHA-1 and whether it's enabled
|
||||||
|
analyzer.central.enabled=true
|
||||||
|
analyzer.central.url=http://search.maven.org/solrsearch/select
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
<xs:element name="cvssBelow" type="dc:cvssScoreType"/>
|
<xs:element name="cvssBelow" type="dc:cvssScoreType"/>
|
||||||
</xs:choice>
|
</xs:choice>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
|
<xs:attribute name="base" use="optional" type="xs:boolean" default="false"/>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
</script>
|
</script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$(".expandable").click(function (e) {
|
$(".expandable").click(function (event) {
|
||||||
e = e || window.event;
|
e = event || window.event;
|
||||||
var h = e.target || e.srcElement;
|
var h = e.target || e.srcElement;
|
||||||
var content = "#content" + h.id.substr(6);
|
var content = "#content" + h.id.substr(6);
|
||||||
var header = "#" + h.id;
|
var header = "#" + h.id;
|
||||||
@@ -56,6 +56,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
$(header).addClass("expandablesubsection");
|
$(header).addClass("expandablesubsection");
|
||||||
$(header).removeClass("collaspablesubsection");
|
$(header).removeClass("collaspablesubsection");
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -84,13 +85,14 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
$('#modal-text').focus();
|
$('#modal-text').focus();
|
||||||
$('#modal-text').select();
|
$('#modal-text').select();
|
||||||
}
|
}
|
||||||
function toggleDisplay(el, clzName) {
|
function toggleDisplay(el, clzName, all, some) {
|
||||||
$(clzName).toggle();
|
$(clzName).toggle();
|
||||||
if (el.innerHTML == 'show all') {
|
if (el.innerHTML == all) {
|
||||||
el.innerHTML = 'less';
|
el.innerHTML = some;
|
||||||
} else {
|
} else {
|
||||||
el.innerHTML = 'show all';
|
el.innerHTML = all;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
@@ -427,15 +429,24 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
.indent {
|
.indent {
|
||||||
margin-left:20px;
|
margin-left:20px;
|
||||||
}
|
}
|
||||||
td, th {
|
td{
|
||||||
|
vertical-align:text-top;
|
||||||
padding:6px;
|
padding:6px;
|
||||||
margin:0px;
|
margin:0px;
|
||||||
}
|
}
|
||||||
|
th {
|
||||||
|
text-align:left
|
||||||
|
vertical-align:text-top;
|
||||||
|
padding:6px;
|
||||||
|
margin:0px;
|
||||||
|
border-bottom:1px;
|
||||||
|
border-color: black;
|
||||||
|
}
|
||||||
table {
|
table {
|
||||||
border: 0px;
|
border: 0px;
|
||||||
}
|
}
|
||||||
table.lined tr:nth-child(even) {
|
table.lined tr:nth-child(even) {
|
||||||
background-color: #fbfbfb;
|
background-color: #f3f3f3;
|
||||||
}
|
}
|
||||||
.fullwidth {
|
.fullwidth {
|
||||||
width:100%;
|
width:100%;
|
||||||
@@ -448,10 +459,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
margin-bottom:3px;
|
margin-bottom:3px;
|
||||||
}
|
}
|
||||||
.vulnerable {
|
.vulnerable {
|
||||||
color: #f00;
|
color: #000;
|
||||||
}
|
|
||||||
.vulnerable li {
|
|
||||||
color: #000;
|
|
||||||
}
|
}
|
||||||
.notvulnerable {
|
.notvulnerable {
|
||||||
display:none;
|
display:none;
|
||||||
@@ -481,7 +489,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
|||||||
<div id="modal-content">
|
<div id="modal-content">
|
||||||
<div>Press CTR-C to copy XML <a href="http://jeremylong.github.io/DependencyCheck/suppression.html" class="infolink" target="_blank" title="Help with suppressing false positives">[help]</a></div>
|
<div>Press CTR-C to copy XML <a href="http://jeremylong.github.io/DependencyCheck/suppression.html" class="infolink" target="_blank" title="Help with suppressing false positives">[help]</a></div>
|
||||||
<textarea id="modal-text" cols="50" rows="10"></textarea><br/>
|
<textarea id="modal-text" cols="50" rows="10"></textarea><br/>
|
||||||
<button id="modal-add-header" class="modal-button">Complete XML Doc</button><button id="modal-close" class="modal-button-right">Close</button>
|
<button id="modal-add-header" title="Add the parent XML nodes to create the complete XML file that can be used to suppress this finding" class="modal-button">Complete XML Doc</button><button id="modal-close" class="modal-button-right">Close</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<h1>Dependency-Check Report</h1>
|
<h1>Dependency-Check Report</h1>
|
||||||
@@ -513,7 +521,7 @@ arising out of or in connection with the use of this tool, the analysis performe
|
|||||||
#set($vulnSuppressedCount=$vulnSuppressedCount+$dependency.getSuppressedVulnerabilities().size())
|
#set($vulnSuppressedCount=$vulnSuppressedCount+$dependency.getSuppressedVulnerabilities().size())
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
Scan Information (<a href="#" onclick="toggleDisplay(this, '.scaninfo'); return false;">show all</a>):<br/>
|
Scan Information (<a href="#" title="Click to toggle display" onclick="return toggleDisplay(this, '.scaninfo', 'show all', 'show less'); return false;">show all</a>):<br/>
|
||||||
<ul class="indent">
|
<ul class="indent">
|
||||||
<li><i>dependency-check version</i>: $version</li>
|
<li><i>dependency-check version</i>: $version</li>
|
||||||
<li><i>Report Generated On</i>: $scanDate</li>
|
<li><i>Report Generated On</i>: $scanDate</li>
|
||||||
@@ -526,23 +534,94 @@ arising out of or in connection with the use of this tool, the analysis performe
|
|||||||
<li class="scaninfo hidden"><i>$enc.html($prop.key)</i>: $enc.html($prop.value)</li>
|
<li class="scaninfo hidden"><i>$enc.html($prop.key)</i>: $enc.html($prop.value)</li>
|
||||||
#end
|
#end
|
||||||
</ul><br/>
|
</ul><br/>
|
||||||
Dependency Display: <a href="#" onclick="toggleDisplay(this,'.notvulnerable'); return false;">show all</a><br/><br/>
|
Display: <a href="#" title="Click to toggle display" onclick="return toggleDisplay(this, '.notvulnerable', 'Showing Vulnerable Dependencies', 'Showing All Dependencies'); return false;">Showing Vulnerable Dependencies</a><br/><br/>
|
||||||
<ul class="indent">
|
|
||||||
#set($lnkcnt=0)
|
#set($lnkcnt=0)
|
||||||
#foreach($dependency in $dependencies)
|
<table class="lined">
|
||||||
|
<tr style="text-align:left">
|
||||||
|
<th title="The name of the dependency">Dependency</th>
|
||||||
|
<th title="The Common Platform Enumeration">CPE</th>
|
||||||
|
<th title="The Maven GAV Coordinates">GAV</th>
|
||||||
|
<th title="The highest CVE Severity">Highest Severity</th>
|
||||||
|
<th title="The number of Common Vulnerability and Exposure (CVE) entries">CVE Count</th>
|
||||||
|
<th title="The confidence rating dependency-check has for the identified CPE">CPE Confidence</th>
|
||||||
|
<th title="The count of evidence used to identify the CPE">Evidence Count</th>
|
||||||
|
</tr>
|
||||||
|
#foreach($dependency in $dependencies)
|
||||||
#set($lnkcnt=$lnkcnt+1)
|
#set($lnkcnt=$lnkcnt+1)
|
||||||
<li class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end">
|
<tr class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end">
|
||||||
<a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a>
|
<td><a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a></td>
|
||||||
#if($dependency.getRelatedDependencies().size()>0)
|
#set($mavenlink="")
|
||||||
<ul>
|
#set($cpeIdCount=0)
|
||||||
#foreach($related in $dependency.getRelatedDependencies())
|
#set($cpeIdConf="")
|
||||||
<li>$enc.html($related.DisplayFileName)</li>
|
<td>
|
||||||
|
#foreach($id in $dependency.getIdentifiers())
|
||||||
|
#if ($id.type=="maven")
|
||||||
|
#if ($mavenlink=="" || !$mavenlink.url)
|
||||||
|
#set($mavenlink=$id)
|
||||||
|
#end
|
||||||
|
#else
|
||||||
|
#if ($cpeIdCount>=1)
|
||||||
|
<br/>
|
||||||
|
#end
|
||||||
|
#if( $id.url )
|
||||||
|
<a href="$enc.html($id.url)" target="_blank">$enc.html($id.value)</a>
|
||||||
|
#else
|
||||||
|
$enc.html($id.value)
|
||||||
|
#end
|
||||||
|
#if ($cpeIdConf == "")
|
||||||
|
#set($cpeIdConf=$id.confidence)
|
||||||
|
#elseif ($cpeIdConf.compareTo($id.confidence)>0)
|
||||||
|
#set($cpeIdConf=$id.confidence)
|
||||||
|
#end
|
||||||
|
#set($cpeIdCount=$cpeIdCount+1)
|
||||||
|
#end
|
||||||
#end
|
#end
|
||||||
</ul>
|
</td>
|
||||||
|
<td>#if( $mavenlink.url )
|
||||||
|
##yes, we are HTML Encoding the href. this is okay. We can't URL encode as we have to trust the analyzer here...
|
||||||
|
<a href="$enc.html($mavenlink.url)" target="_blank">$enc.html($mavenlink.value)</a>
|
||||||
|
#elseif ($mavenlink.value)
|
||||||
|
$enc.html($mavenlink.value)
|
||||||
|
#end</td>
|
||||||
|
#set($cveImpact=-1)
|
||||||
|
#foreach($vuln in $dependency.getVulnerabilities())
|
||||||
|
#if ($cveImpact<$vuln.cvssScore)
|
||||||
|
#set($cveImpact=$vuln.cvssScore)
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
<td>
|
||||||
|
#if ($cveImpact<0)
|
||||||
|
|
||||||
|
#elseif ($cveImpact<4.0)
|
||||||
|
Low
|
||||||
|
#elseif ($cveImpact>=7.0)
|
||||||
|
High
|
||||||
|
#else
|
||||||
|
Medium
|
||||||
|
#end
|
||||||
|
</td>
|
||||||
|
<td>$dependency.getVulnerabilities().size()</td>
|
||||||
|
<td>$cpeIdConf</td>
|
||||||
|
<td>$dependency.getEvidenceForDisplay().size()</td>
|
||||||
|
</tr>
|
||||||
#end
|
#end
|
||||||
</li>
|
</table>
|
||||||
#end
|
## <ul class="indent">
|
||||||
</ul>
|
## #set($lnkcnt=0)
|
||||||
|
## #foreach($dependency in $dependencies)
|
||||||
|
## #set($lnkcnt=$lnkcnt+1)
|
||||||
|
## <li class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end">
|
||||||
|
## <a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a>
|
||||||
|
## #if($dependency.getRelatedDependencies().size()>0)
|
||||||
|
## <ul>
|
||||||
|
## #foreach($related in $dependency.getRelatedDependencies())
|
||||||
|
## <li>$enc.html($related.DisplayFileName)</li>
|
||||||
|
## #end
|
||||||
|
## </ul>
|
||||||
|
## #end
|
||||||
|
## </li>
|
||||||
|
## #end
|
||||||
|
## </ul>
|
||||||
<h2>Dependencies</h2>
|
<h2>Dependencies</h2>
|
||||||
#set($lnkcnt=0)
|
#set($lnkcnt=0)
|
||||||
#set($cnt=0)
|
#set($cnt=0)
|
||||||
@@ -630,7 +709,7 @@ arising out of or in connection with the use of this tool, the analysis performe
|
|||||||
#end
|
#end
|
||||||
#if ($id.type=="cpe")
|
#if ($id.type=="cpe")
|
||||||
##yes, we are HTML Encoding into JavaScript... the escape utils don't have a JS Encode and I haven't written one yet
|
##yes, we are HTML Encoding into JavaScript... the escape utils don't have a JS Encode and I haven't written one yet
|
||||||
<button class="copybutton" onclick="copyText('$enc.html($dependency.FileNameForJavaScript)', '$enc.html($dependency.Sha1sum)', 'cpe', '$enc.html($id.value)')">suppress</button>
|
<button class="copybutton" title="Generate Suppression XML for this CPE for this file" onclick="copyText('$enc.html($dependency.FileNameForJavaScript)', '$enc.html($dependency.Sha1sum)', 'cpe', '$enc.html($id.value)')">suppress</button>
|
||||||
#end
|
#end
|
||||||
#if ($id.description)
|
#if ($id.description)
|
||||||
<br/>$enc.html($id.description)
|
<br/>$enc.html($id.description)
|
||||||
@@ -646,7 +725,7 @@ arising out of or in connection with the use of this tool, the analysis performe
|
|||||||
<div id="content$cnt" class="subsectioncontent standardsubsection">
|
<div id="content$cnt" class="subsectioncontent standardsubsection">
|
||||||
#foreach($vuln in $dependency.getVulnerabilities())
|
#foreach($vuln in $dependency.getVulnerabilities())
|
||||||
#set($vsctr=$vsctr+1)
|
#set($vsctr=$vsctr+1)
|
||||||
<p><b><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=$enc.url($vuln.name)">$enc.html($vuln.name)</a></b> <button class="copybutton" onclick="copyText('$enc.html($dependency.FileNameForJavaScript)', '$enc.html($dependency.Sha1sum)', 'cve', '$enc.html($vuln.name)')">suppress</button></p>
|
<p><b><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=$enc.url($vuln.name)">$enc.html($vuln.name)</a></b> <button class="copybutton" title="Generate Suppression XML for this CCE for this file" onclick="copyText('$enc.html($dependency.FileNameForJavaScript)', '$enc.html($dependency.Sha1sum)', 'cve', '$enc.html($vuln.name)')">suppress</button></p>
|
||||||
<p>Severity:
|
<p>Severity:
|
||||||
#if ($vuln.cvssScore<4.0)
|
#if ($vuln.cvssScore<4.0)
|
||||||
Low
|
Low
|
||||||
@@ -674,7 +753,7 @@ arising out of or in connection with the use of this tool, the analysis performe
|
|||||||
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
|
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
|
||||||
</ul></p>
|
</ul></p>
|
||||||
#else
|
#else
|
||||||
<p>Vulnerable Software & Versions: (<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul>
|
<p>Vulnerable Software & Versions: (<a href="#" onclick="return toggleDisplay(this,'.vs$vsctr', 'show all', 'show less');">show all</a>)<ul>
|
||||||
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
|
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
|
||||||
<li class="vs$vsctr">...</li>
|
<li class="vs$vsctr">...</li>
|
||||||
#foreach($vs in $vuln.getVulnerableSoftware())
|
#foreach($vs in $vuln.getVulnerableSoftware())
|
||||||
@@ -808,7 +887,7 @@ arising out of or in connection with the use of this tool, the analysis performe
|
|||||||
git st<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
|
git st<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
|
||||||
</ul></p>
|
</ul></p>
|
||||||
#else
|
#else
|
||||||
<p>Vulnerable Software & Versions: (<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul>
|
<p>Vulnerable Software & Versions: (<a href="#" onclick="return toggleDisplay(this,'.vs$vsctr', 'show all', 'show less');">show all</a>)<ul>
|
||||||
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
|
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
|
||||||
<li class="vs$vsctr">...</li>
|
<li class="vs$vsctr">...</li>
|
||||||
#foreach($vs in $vuln.getVulnerableSoftware())
|
#foreach($vs in $vuln.getVulnerableSoftware())
|
||||||
@@ -827,6 +906,6 @@ arising out of or in connection with the use of this tool, the analysis performe
|
|||||||
## END SUPPRESSED VULNERABILITIES
|
## END SUPPRESSED VULNERABILITIES
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div><br/><br/>This report contains data retrieved from the <a href="nvd.nist.gov">National Vulnerability Database</a>.</div>
|
<div><br/><br/>This report contains data retrieved from the <a href="http://nvd.nist.gov">National Vulnerability Database</a>.</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -236,6 +236,6 @@ arising out of or in connection with the use of this tool, the analysis performe
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<p><br/><br/>This report contains data retrieved from the <a href="nvd.nist.gov">National Vulnerability Database</a>.</p>
|
<p><br/><br/>This report contains data retrieved from the <a href="http://nvd.nist.gov">National Vulnerability Database</a>.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||||
import org.owasp.dependencycheck.dependency.Dependency;
|
|
||||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||||
import org.owasp.dependencycheck.utils.Settings;
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
@@ -42,26 +41,6 @@ public class EngineIntegrationTest extends BaseTest {
|
|||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Test of scan method, of class Engine.
|
|
||||||
*
|
|
||||||
* @throws Exception is thrown when an exception occurs.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testScan() throws Exception {
|
|
||||||
String testClasses = "target/test-classes/*.zip";
|
|
||||||
boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
|
|
||||||
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
|
|
||||||
Engine instance = new Engine();
|
|
||||||
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
|
|
||||||
instance.scan(testClasses);
|
|
||||||
assertTrue(instance.getDependencies().size() > 0);
|
|
||||||
for (Dependency d : instance.getDependencies()) {
|
|
||||||
assertTrue("non-zip file collected " + d.getFileName(), d.getFileName().toLowerCase().endsWith(".zip"));
|
|
||||||
}
|
|
||||||
instance.cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test running the entire engine.
|
* Test running the entire engine.
|
||||||
*
|
*
|
||||||
@@ -70,10 +49,10 @@ public class EngineIntegrationTest extends BaseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testEngine() throws Exception {
|
public void testEngine() throws Exception {
|
||||||
String testClasses = "target/test-classes";
|
String testClasses = "target/test-classes";
|
||||||
// boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
|
boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
|
||||||
// Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
|
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
|
||||||
Engine instance = new Engine();
|
Engine instance = new Engine();
|
||||||
// Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
|
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
|
||||||
instance.scan(testClasses);
|
instance.scan(testClasses);
|
||||||
assertTrue(instance.getDependencies().size() > 0);
|
assertTrue(instance.getDependencies().size() > 0);
|
||||||
instance.analyzeDependencies();
|
instance.analyzeDependencies();
|
||||||
@@ -81,8 +60,7 @@ public class EngineIntegrationTest extends BaseTest {
|
|||||||
cveDB.open();
|
cveDB.open();
|
||||||
DatabaseProperties dbProp = cveDB.getDatabaseProperties();
|
DatabaseProperties dbProp = cveDB.getDatabaseProperties();
|
||||||
cveDB.close();
|
cveDB.close();
|
||||||
ReportGenerator rg = new ReportGenerator("DependencyCheck",
|
ReportGenerator rg = new ReportGenerator("DependencyCheck", instance.getDependencies(), instance.getAnalyzers(), dbProp);
|
||||||
instance.getDependencies(), instance.getAnalyzers(), dbProp);
|
|
||||||
rg.generateReports("./target/", "ALL");
|
rg.generateReports("./target/", "ALL");
|
||||||
instance.cleanup();
|
instance.cleanup();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class ArchiveAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testGetSupportedExtensions() {
|
public void testGetSupportedExtensions() {
|
||||||
ArchiveAnalyzer instance = new ArchiveAnalyzer();
|
ArchiveAnalyzer instance = new ArchiveAnalyzer();
|
||||||
Set expResult = new HashSet<String>();
|
Set<String> expResult = new HashSet<String>();
|
||||||
expResult.add("zip");
|
expResult.add("zip");
|
||||||
expResult.add("war");
|
expResult.add("war");
|
||||||
expResult.add("ear");
|
expResult.add("ear");
|
||||||
|
|||||||
@@ -25,9 +25,11 @@ import java.util.Set;
|
|||||||
import org.apache.lucene.index.CorruptIndexException;
|
import org.apache.lucene.index.CorruptIndexException;
|
||||||
import org.apache.lucene.queryparser.classic.ParseException;
|
import org.apache.lucene.queryparser.classic.ParseException;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.owasp.dependencycheck.data.cpe.AbstractDatabaseTestCase;
|
import org.owasp.dependencycheck.data.cpe.AbstractDatabaseTestCase;
|
||||||
import org.owasp.dependencycheck.data.cpe.IndexEntry;
|
import org.owasp.dependencycheck.data.cpe.IndexEntry;
|
||||||
|
import org.owasp.dependencycheck.dependency.Confidence;
|
||||||
import org.owasp.dependencycheck.dependency.Dependency;
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
import org.owasp.dependencycheck.dependency.Identifier;
|
import org.owasp.dependencycheck.dependency.Identifier;
|
||||||
|
|
||||||
@@ -81,12 +83,24 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDetermineCPE_full() throws Exception {
|
public void testDetermineCPE_full() throws Exception {
|
||||||
callDetermineCPE_full("hazelcast-2.5.jar", null);
|
CPEAnalyzer instance = new CPEAnalyzer();
|
||||||
callDetermineCPE_full("spring-context-support-2.5.5.jar", "cpe:/a:vmware:springsource_spring_framework:2.5.5");
|
instance.open();
|
||||||
callDetermineCPE_full("spring-core-3.0.0.RELEASE.jar", "cpe:/a:vmware:springsource_spring_framework:3.0.0");
|
FileNameAnalyzer fnAnalyzer = new FileNameAnalyzer();
|
||||||
callDetermineCPE_full("org.mortbay.jetty.jar", "cpe:/a:mortbay_jetty:jetty:4.2");
|
JarAnalyzer jarAnalyzer = new JarAnalyzer();
|
||||||
callDetermineCPE_full("jaxb-xercesImpl-1.5.jar", null);
|
HintAnalyzer hAnalyzer = new HintAnalyzer();
|
||||||
callDetermineCPE_full("ehcache-core-2.2.0.jar", null);
|
FalsePositiveAnalyzer fp = new FalsePositiveAnalyzer();
|
||||||
|
|
||||||
|
try {
|
||||||
|
//callDetermineCPE_full("struts2-core-2.3.16.3.jar", "cpe:/a:apache:struts:2.3.16.3", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
||||||
|
callDetermineCPE_full("hazelcast-2.5.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
||||||
|
callDetermineCPE_full("spring-context-support-2.5.5.jar", "cpe:/a:vmware:springsource_spring_framework:2.5.5", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
||||||
|
callDetermineCPE_full("spring-core-3.0.0.RELEASE.jar", "cpe:/a:vmware:springsource_spring_framework:3.0.0", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
||||||
|
callDetermineCPE_full("org.mortbay.jetty.jar", "cpe:/a:mortbay_jetty:jetty:4.2", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
||||||
|
callDetermineCPE_full("jaxb-xercesImpl-1.5.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
||||||
|
callDetermineCPE_full("ehcache-core-2.2.0.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
||||||
|
} finally {
|
||||||
|
instance.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,25 +108,16 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
|
|||||||
*
|
*
|
||||||
* @throws Exception is thrown when an exception occurs
|
* @throws Exception is thrown when an exception occurs
|
||||||
*/
|
*/
|
||||||
public void callDetermineCPE_full(String depName, String expResult) throws Exception {
|
public void callDetermineCPE_full(String depName, String expResult, CPEAnalyzer instance, FileNameAnalyzer fnAnalyzer, JarAnalyzer jarAnalyzer, HintAnalyzer hAnalyzer, FalsePositiveAnalyzer fp) throws Exception {
|
||||||
|
|
||||||
File file = new File(this.getClass().getClassLoader().getResource(depName).getPath());
|
File file = new File(this.getClass().getClassLoader().getResource(depName).getPath());
|
||||||
|
|
||||||
Dependency dep = new Dependency(file);
|
Dependency dep = new Dependency(file);
|
||||||
|
|
||||||
FileNameAnalyzer fnAnalyzer = new FileNameAnalyzer();
|
|
||||||
fnAnalyzer.analyze(dep, null);
|
fnAnalyzer.analyze(dep, null);
|
||||||
|
|
||||||
JarAnalyzer jarAnalyzer = new JarAnalyzer();
|
|
||||||
jarAnalyzer.analyze(dep, null);
|
jarAnalyzer.analyze(dep, null);
|
||||||
HintAnalyzer hAnalyzer = new HintAnalyzer();
|
|
||||||
hAnalyzer.analyze(dep, null);
|
hAnalyzer.analyze(dep, null);
|
||||||
|
|
||||||
CPEAnalyzer instance = new CPEAnalyzer();
|
|
||||||
instance.open();
|
|
||||||
instance.analyze(dep, null);
|
instance.analyze(dep, null);
|
||||||
instance.close();
|
|
||||||
FalsePositiveAnalyzer fp = new FalsePositiveAnalyzer();
|
|
||||||
fp.analyze(dep, null);
|
fp.analyze(dep, null);
|
||||||
|
|
||||||
if (expResult != null) {
|
if (expResult != null) {
|
||||||
@@ -180,6 +185,30 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
|
|||||||
//Assert.assertTrue("Incorrect match - spring", spring.getIdentifiers().get(0).getValue().equals(expResultSpring));
|
//Assert.assertTrue("Incorrect match - spring", spring.getIdentifiers().get(0).getValue().equals(expResultSpring));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of determineIdentifiers method, of class CPEAnalyzer.
|
||||||
|
*
|
||||||
|
* @throws Exception is thrown when an exception occurs
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDetermineIdentifiers() throws Exception {
|
||||||
|
Dependency openssl = new Dependency();
|
||||||
|
openssl.getVendorEvidence().addEvidence("test", "vendor", "openssl", Confidence.HIGHEST);
|
||||||
|
openssl.getProductEvidence().addEvidence("test", "product", "openssl", Confidence.HIGHEST);
|
||||||
|
openssl.getVersionEvidence().addEvidence("test", "version", "1.0.1c", Confidence.HIGHEST);
|
||||||
|
|
||||||
|
CPEAnalyzer instance = new CPEAnalyzer();
|
||||||
|
instance.open();
|
||||||
|
instance.determineIdentifiers(openssl, "openssl", "openssl", Confidence.HIGHEST);
|
||||||
|
instance.close();
|
||||||
|
|
||||||
|
String expResult = "cpe:/a:openssl:openssl:1.0.1c";
|
||||||
|
Identifier expIdentifier = new Identifier("cpe", expResult, expResult);
|
||||||
|
|
||||||
|
assertTrue(openssl.getIdentifiers().contains(expIdentifier));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of searchCPE method, of class CPEAnalyzer.
|
* Test of searchCPE method, of class CPEAnalyzer.
|
||||||
*
|
*
|
||||||
@@ -190,12 +219,12 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
|
|||||||
String vendor = "apache software foundation";
|
String vendor = "apache software foundation";
|
||||||
String product = "struts 2 core";
|
String product = "struts 2 core";
|
||||||
String version = "2.1.2";
|
String version = "2.1.2";
|
||||||
String expResult = "cpe:/a:apache:struts:2.1.2";
|
String expVendor = "apache";
|
||||||
|
String expProduct = "struts";
|
||||||
|
|
||||||
CPEAnalyzer instance = new CPEAnalyzer();
|
CPEAnalyzer instance = new CPEAnalyzer();
|
||||||
instance.open();
|
instance.open();
|
||||||
|
|
||||||
//TODO - yeah, not a very good test as the results are the same with or without weighting...
|
|
||||||
Set<String> productWeightings = new HashSet<String>(1);
|
Set<String> productWeightings = new HashSet<String>(1);
|
||||||
productWeightings.add("struts2");
|
productWeightings.add("struts2");
|
||||||
|
|
||||||
@@ -203,9 +232,16 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
|
|||||||
vendorWeightings.add("apache");
|
vendorWeightings.add("apache");
|
||||||
|
|
||||||
List<IndexEntry> result = instance.searchCPE(vendor, product, productWeightings, vendorWeightings);
|
List<IndexEntry> result = instance.searchCPE(vendor, product, productWeightings, vendorWeightings);
|
||||||
//TODO fix this assert
|
|
||||||
//Assert.assertEquals(expResult, result.get(0).getName());
|
|
||||||
|
|
||||||
instance.close();
|
instance.close();
|
||||||
|
|
||||||
|
boolean found = false;
|
||||||
|
for (IndexEntry entry : result) {
|
||||||
|
if (expVendor.equals(entry.getVendor()) && expProduct.equals(entry.getProduct())) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue("apache:struts was not identified", found);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,4 +86,40 @@ public class DependencyBundlingAnalyzerTest extends BaseTest {
|
|||||||
assertEquals(expResult, result);
|
assertEquals(expResult, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFirstPathIsShortest() {
|
||||||
|
DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
|
||||||
|
|
||||||
|
String left = "./a/c.jar";
|
||||||
|
String right = "./d/e/f.jar";
|
||||||
|
boolean expResult = true;
|
||||||
|
boolean result = instance.firstPathIsShortest(left, right);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
|
||||||
|
left = "./a/b/c.jar";
|
||||||
|
right = "./d/e/f.jar";
|
||||||
|
expResult = true;
|
||||||
|
result = instance.firstPathIsShortest(left, right);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
|
||||||
|
left = "./d/b/c.jar";
|
||||||
|
right = "./a/e/f.jar";
|
||||||
|
expResult = false;
|
||||||
|
result = instance.firstPathIsShortest(left, right);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
|
||||||
|
left = "./a/b/c.jar";
|
||||||
|
right = "./d/f.jar";
|
||||||
|
expResult = false;
|
||||||
|
result = instance.firstPathIsShortest(left, right);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
|
||||||
|
left = "./a/b/c.jar";
|
||||||
|
right = "./a/b/c.jar";
|
||||||
|
expResult = true;
|
||||||
|
result = instance.firstPathIsShortest(left, right);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class HintAnalyzerTest extends BaseTest {
|
|||||||
for (Dependency d : engine.getDependencies()) {
|
for (Dependency d : engine.getDependencies()) {
|
||||||
if (d.getActualFile().equals(guice)) {
|
if (d.getActualFile().equals(guice)) {
|
||||||
gdep = d;
|
gdep = d;
|
||||||
} else {
|
} else if (d.getActualFile().equals(spring)) {
|
||||||
sdep = d;
|
sdep = d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public class JarAnalyzerTest extends BaseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testGetSupportedExtensions() {
|
public void testGetSupportedExtensions() {
|
||||||
JarAnalyzer instance = new JarAnalyzer();
|
JarAnalyzer instance = new JarAnalyzer();
|
||||||
Set expResult = new HashSet();
|
Set<String> expResult = new HashSet<String>();
|
||||||
expResult.add("jar");
|
expResult.add("jar");
|
||||||
expResult.add("war");
|
expResult.add("war");
|
||||||
Set result = instance.getSupportedExtensions();
|
Set result = instance.getSupportedExtensions();
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class JavaScriptAnalyzerTest extends BaseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testGetSupportedExtensions() {
|
public void testGetSupportedExtensions() {
|
||||||
JavaScriptAnalyzer instance = new JavaScriptAnalyzer();
|
JavaScriptAnalyzer instance = new JavaScriptAnalyzer();
|
||||||
Set expResult = new HashSet<String>();
|
Set<String> expResult = new HashSet<String>();
|
||||||
expResult.add("js");
|
expResult.add("js");
|
||||||
Set result = instance.getSupportedExtensions();
|
Set result = instance.getSupportedExtensions();
|
||||||
assertEquals(expResult, result);
|
assertEquals(expResult, result);
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package org.owasp.dependencycheck.data.central;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.owasp.dependencycheck.BaseTest;
|
||||||
|
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by colezlaw on 10/13/14.
|
||||||
|
*/
|
||||||
|
public class CentralSearchTest extends BaseTest {
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CentralSearchTest.class.getName());
|
||||||
|
private CentralSearch searcher;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
String centralUrl = Settings.getString(Settings.KEYS.ANALYZER_CENTRAL_URL);
|
||||||
|
LOGGER.fine(centralUrl);
|
||||||
|
searcher = new CentralSearch(new URL(centralUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testNullSha1() throws Exception { searcher.searchSha1(null); }
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testMalformedSha1() throws Exception {
|
||||||
|
searcher.searchSha1("invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test does generate network traffic and communicates with a host
|
||||||
|
// you may not be able to reach. Remove the @Ignore annotation if you want to
|
||||||
|
// test it anyway
|
||||||
|
@Test
|
||||||
|
public void testValidSha1() throws Exception {
|
||||||
|
List<MavenArtifact> ma = searcher.searchSha1("9977a8d04e75609cf01badc4eb6a9c7198c4c5ea");
|
||||||
|
assertEquals("Incorrect group", "org.apache.maven.plugins", ma.get(0).getGroupId());
|
||||||
|
assertEquals("Incorrect artifact", "maven-compiler-plugin", ma.get(0).getArtifactId());
|
||||||
|
assertEquals("Incorrect version", "3.1", ma.get(0).getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test does generate network traffic and communicates with a host
|
||||||
|
// you may not be able to reach. Remove the @Ignore annotation if you want to
|
||||||
|
// test it anyway
|
||||||
|
@Test(expected = FileNotFoundException.class)
|
||||||
|
public void testMissingSha1() throws Exception {
|
||||||
|
searcher.searchSha1("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test should give us multiple results back from Central
|
||||||
|
@Test
|
||||||
|
public void testMultipleReturns() throws Exception {
|
||||||
|
List<MavenArtifact> ma = searcher.searchSha1("94A9CE681A42D0352B3AD22659F67835E560D107");
|
||||||
|
assertTrue(ma.size() > 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,8 +45,10 @@ public abstract class BaseDBTestCase extends BaseTest {
|
|||||||
|
|
||||||
public static void ensureDBExists() throws Exception {
|
public static void ensureDBExists() throws Exception {
|
||||||
|
|
||||||
java.io.File dataPath = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY);
|
java.io.File dataPath = Settings.getDataDirectory();
|
||||||
if (!dataPath.exists() || (dataPath.isDirectory() && dataPath.listFiles().length < 3)) {
|
String fileName = String.format(Settings.getString(Settings.KEYS.DB_FILE_NAME), Settings.getString(Settings.KEYS.DB_VERSION));
|
||||||
|
java.io.File dataFile = new File(dataPath, fileName);
|
||||||
|
if (!dataPath.exists() || !dataFile.exists()) {
|
||||||
dataPath.mkdirs();
|
dataPath.mkdirs();
|
||||||
FileInputStream fis = null;
|
FileInputStream fis = null;
|
||||||
ZipInputStream zin = null;
|
ZipInputStream zin = null;
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ package org.owasp.dependencycheck.data.nvdcve;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
|
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
|
||||||
|
import org.owasp.dependencycheck.utils.DependencyVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -72,4 +74,21 @@ public class CveDBIntegrationTest extends BaseDBTestCase {
|
|||||||
instance.close();
|
instance.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of isAffected method, of class CveDB.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testIsAffected() throws Exception {
|
||||||
|
String vendor = "openssl";
|
||||||
|
String product = "openssl";
|
||||||
|
DependencyVersion identifiedVersion = new DependencyVersion("1.0.1o");
|
||||||
|
String cpeId = "cpe:/a:openssl:openssl:1.0.1e";
|
||||||
|
String previous = "y";
|
||||||
|
|
||||||
|
CveDB instance = new CveDB();
|
||||||
|
assertFalse(instance.isAffected(vendor, product, identifiedVersion, cpeId, previous));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 OWASP.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.data.update;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Properties;
|
||||||
|
import mockit.Mock;
|
||||||
|
import mockit.MockUp;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.owasp.dependencycheck.BaseTest;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||||
|
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||||
|
import org.owasp.dependencycheck.utils.DependencyVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
public class EngineVersionCheckTest extends BaseTest {
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Test of update method, of class EngineVersionCheck.
|
||||||
|
// */
|
||||||
|
// @Test
|
||||||
|
// public void testUpdate() throws Exception {
|
||||||
|
// EngineVersionCheck instance = new EngineVersionCheck();
|
||||||
|
// instance.update();
|
||||||
|
// }
|
||||||
|
/**
|
||||||
|
* Test of shouldUpdate method, of class EngineVersionCheck.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testShouldUpdate() throws Exception {
|
||||||
|
DatabaseProperties properties = new MockUp<DatabaseProperties>() {
|
||||||
|
final private Properties properties = new Properties();
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
public void save(String key, String value) throws UpdateException {
|
||||||
|
properties.setProperty(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
public String getProperty(String key) {
|
||||||
|
return properties.getProperty(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}.getMockInstance();
|
||||||
|
|
||||||
|
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
|
||||||
|
String updateToVersion = "1.2.6";
|
||||||
|
String currentVersion = "1.2.6";
|
||||||
|
long lastChecked = df.parse("2014-12-01").getTime();
|
||||||
|
long now = df.parse("2014-12-01").getTime();
|
||||||
|
|
||||||
|
EngineVersionCheck instance = new EngineVersionCheck();
|
||||||
|
boolean expResult = false;
|
||||||
|
instance.setUpdateToVersion(updateToVersion);
|
||||||
|
boolean result = instance.shouldUpdate(lastChecked, now, properties, currentVersion);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
|
||||||
|
updateToVersion = "1.2.5";
|
||||||
|
currentVersion = "1.2.5";
|
||||||
|
lastChecked = df.parse("2014-10-01").getTime();
|
||||||
|
now = df.parse("2014-12-01").getTime();
|
||||||
|
expResult = true;
|
||||||
|
instance.setUpdateToVersion(updateToVersion);
|
||||||
|
result = instance.shouldUpdate(lastChecked, now, properties, currentVersion);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
//System.out.println(properties.getProperty(CURRENT_ENGINE_RELEASE));
|
||||||
|
|
||||||
|
updateToVersion = "1.2.5";
|
||||||
|
currentVersion = "1.2.5";
|
||||||
|
lastChecked = df.parse("2014-12-01").getTime();
|
||||||
|
now = df.parse("2014-12-03").getTime();
|
||||||
|
expResult = false;
|
||||||
|
instance.setUpdateToVersion(updateToVersion);
|
||||||
|
result = instance.shouldUpdate(lastChecked, now, properties, currentVersion);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
|
||||||
|
updateToVersion = "1.2.6";
|
||||||
|
currentVersion = "1.2.5";
|
||||||
|
lastChecked = df.parse("2014-12-01").getTime();
|
||||||
|
now = df.parse("2014-12-03").getTime();
|
||||||
|
expResult = true;
|
||||||
|
instance.setUpdateToVersion(updateToVersion);
|
||||||
|
result = instance.shouldUpdate(lastChecked, now, properties, currentVersion);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
|
||||||
|
updateToVersion = "1.2.5";
|
||||||
|
currentVersion = "1.2.6";
|
||||||
|
lastChecked = df.parse("2014-12-01").getTime();
|
||||||
|
now = df.parse("2014-12-08").getTime();
|
||||||
|
expResult = false;
|
||||||
|
instance.setUpdateToVersion(updateToVersion);
|
||||||
|
result = instance.shouldUpdate(lastChecked, now, properties, currentVersion);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
|
||||||
|
updateToVersion = "";
|
||||||
|
currentVersion = "1.2.5";
|
||||||
|
lastChecked = df.parse("2014-12-01").getTime();
|
||||||
|
now = df.parse("2014-12-03").getTime();
|
||||||
|
expResult = false;
|
||||||
|
instance.setUpdateToVersion(updateToVersion);
|
||||||
|
result = instance.shouldUpdate(lastChecked, now, properties, currentVersion);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
|
||||||
|
updateToVersion = "";
|
||||||
|
currentVersion = "1.2.5";
|
||||||
|
lastChecked = df.parse("2014-12-01").getTime();
|
||||||
|
now = df.parse("2014-12-08").getTime();
|
||||||
|
expResult = true;
|
||||||
|
instance.setUpdateToVersion(updateToVersion);
|
||||||
|
result = instance.shouldUpdate(lastChecked, now, properties, currentVersion);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getCurrentReleaseVersion method, of class EngineVersionCheck.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetCurrentReleaseVersion() {
|
||||||
|
EngineVersionCheck instance = new EngineVersionCheck();
|
||||||
|
DependencyVersion minExpResult = new DependencyVersion("1.2.6");
|
||||||
|
String release = instance.getCurrentReleaseVersion();
|
||||||
|
DependencyVersion result = new DependencyVersion(release);
|
||||||
|
assertTrue(minExpResult.compareTo(result) <= 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,8 +18,6 @@
|
|||||||
package org.owasp.dependencycheck.data.update;
|
package org.owasp.dependencycheck.data.update;
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.util.Calendar;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.owasp.dependencycheck.BaseTest;
|
import org.owasp.dependencycheck.BaseTest;
|
||||||
@@ -47,26 +45,6 @@ public class StandardUpdateIntegrationTest extends BaseTest {
|
|||||||
instance.closeDataStores();
|
instance.closeDataStores();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Test of withinRange method, of class StandardUpdate.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testWithinRange() throws Exception {
|
|
||||||
Calendar c = Calendar.getInstance();
|
|
||||||
|
|
||||||
long current = c.getTimeInMillis();
|
|
||||||
long lastRun = c.getTimeInMillis() - (3 * (1000 * 60 * 60 * 24));
|
|
||||||
int range = 7; // 7 days
|
|
||||||
StandardUpdate instance = getStandardUpdateTask();
|
|
||||||
boolean expResult = true;
|
|
||||||
boolean result = instance.withinRange(lastRun, current, range);
|
|
||||||
assertEquals(expResult, result);
|
|
||||||
|
|
||||||
lastRun = c.getTimeInMillis() - (8 * (1000 * 60 * 60 * 24));
|
|
||||||
expResult = false;
|
|
||||||
result = instance.withinRange(lastRun, current, range);
|
|
||||||
assertEquals(expResult, result);
|
|
||||||
}
|
|
||||||
// test removed as it is duplicative of the EngineIntegrationTest and the NvdCveUpdaterIntergraionTest
|
// test removed as it is duplicative of the EngineIntegrationTest and the NvdCveUpdaterIntergraionTest
|
||||||
// /**
|
// /**
|
||||||
// * Test of update method, of class StandardUpdate.
|
// * Test of update method, of class StandardUpdate.
|
||||||
@@ -77,7 +55,6 @@ public class StandardUpdateIntegrationTest extends BaseTest {
|
|||||||
// instance.update();
|
// instance.update();
|
||||||
// //TODO make this an actual test
|
// //TODO make this an actual test
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of updatesNeeded method, of class StandardUpdate.
|
* Test of updatesNeeded method, of class StandardUpdate.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.data.update.task;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
|
import org.owasp.dependencycheck.data.update.NvdCveInfo;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
public class DownloadTaskTest {
|
||||||
|
|
||||||
|
public DownloadTaskTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpClass() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDownClass() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
Settings.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
Settings.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of call method, of class DownloadTask.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCall() throws Exception {
|
||||||
|
NvdCveInfo cve = new NvdCveInfo();
|
||||||
|
cve.setId("modified");
|
||||||
|
cve.setNeedsUpdate(true);
|
||||||
|
cve.setUrl(Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL));
|
||||||
|
cve.setOldSchemaVersionUrl(Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL));
|
||||||
|
ExecutorService processExecutor = null;
|
||||||
|
CveDB cveDB = null;
|
||||||
|
DownloadTask instance = new DownloadTask(cve, processExecutor, cveDB, Settings.getInstance());;
|
||||||
|
Future<ProcessTask> result = instance.call();
|
||||||
|
assertNull(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,10 +23,12 @@ import java.util.Set;
|
|||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -152,7 +154,7 @@ public class DependencyTest {
|
|||||||
public void testGetMd5sum() {
|
public void testGetMd5sum() {
|
||||||
File file = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
|
File file = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
|
||||||
Dependency instance = new Dependency(file);
|
Dependency instance = new Dependency(file);
|
||||||
// assertEquals("89CE9E36AA9A9E03F1450936D2F4F8DD0F961F8B", result.getSha1sum());
|
//assertEquals("89CE9E36AA9A9E03F1450936D2F4F8DD0F961F8B", result.getSha1sum());
|
||||||
String expResult = "C30B57142E1CCBC1EFD5CD15F307358F";
|
String expResult = "C30B57142E1CCBC1EFD5CD15F307358F";
|
||||||
String result = instance.getMd5sum();
|
String result = instance.getMd5sum();
|
||||||
assertEquals(expResult, result);
|
assertEquals(expResult, result);
|
||||||
@@ -294,4 +296,34 @@ public class DependencyTest {
|
|||||||
EvidenceCollection result = instance.getVersionEvidence();
|
EvidenceCollection result = instance.getVersionEvidence();
|
||||||
assertTrue(true); //this is just a getter setter pair.
|
assertTrue(true); //this is just a getter setter pair.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of addAsEvidence method, of class Dependency.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testAddAsEvidence() {
|
||||||
|
Dependency instance = new Dependency();
|
||||||
|
MavenArtifact mavenArtifact = new MavenArtifact("group", "artifact", "version", "url");
|
||||||
|
instance.addAsEvidence("pom", mavenArtifact, Confidence.HIGH);
|
||||||
|
assertTrue(instance.getEvidence().contains(Confidence.HIGH));
|
||||||
|
assertFalse(instance.getEvidence().getEvidence("pom", "groupid").isEmpty());
|
||||||
|
assertFalse(instance.getEvidence().getEvidence("pom", "artifactid").isEmpty());
|
||||||
|
assertFalse(instance.getEvidence().getEvidence("pom", "version").isEmpty());
|
||||||
|
assertFalse(instance.getIdentifiers().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of addAsEvidence method, of class Dependency.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testAddAsEvidenceWithEmptyArtefact() {
|
||||||
|
Dependency instance = new Dependency();
|
||||||
|
MavenArtifact mavenArtifact = new MavenArtifact(null, null, null, null);
|
||||||
|
instance.addAsEvidence("pom", mavenArtifact, Confidence.HIGH);
|
||||||
|
assertFalse(instance.getEvidence().contains(Confidence.HIGH));
|
||||||
|
assertTrue(instance.getEvidence().getEvidence("pom", "groupid").isEmpty());
|
||||||
|
assertTrue(instance.getEvidence().getEvidence("pom", "artifactid").isEmpty());
|
||||||
|
assertTrue(instance.getEvidence().getEvidence("pom", "version").isEmpty());
|
||||||
|
assertTrue(instance.getIdentifiers().isEmpty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,15 @@ public class SuppressionHandlerTest {
|
|||||||
|
|
||||||
xmlReader.parse(in);
|
xmlReader.parse(in);
|
||||||
|
|
||||||
List result = handler.getSuppressionRules();
|
List<SuppressionRule> result = handler.getSuppressionRules();
|
||||||
assertTrue(result.size() > 3);
|
assertTrue(result.size() > 3);
|
||||||
|
int baseCount = 0;
|
||||||
|
for (SuppressionRule r : result) {
|
||||||
|
if (r.isBase()) {
|
||||||
|
baseCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(baseCount > 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,6 +146,17 @@ public class SuppressionRuleTest {
|
|||||||
List<String> result = instance.getCve();
|
List<String> result = instance.getCve();
|
||||||
assertEquals(cve, result);
|
assertEquals(cve, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of base property, of class SuppressionRule.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBase() {
|
||||||
|
SuppressionRule instance = new SuppressionRule();
|
||||||
|
assertFalse(instance.isBase());
|
||||||
|
instance.setBase(true);
|
||||||
|
assertTrue(instance.isBase());
|
||||||
|
}
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
//<editor-fold defaultstate="collapsed" desc="Ignored duplicate tests, left in, as empty tests, so IDE doesn't re-generate them">
|
//<editor-fold defaultstate="collapsed" desc="Ignored duplicate tests, left in, as empty tests, so IDE doesn't re-generate them">
|
||||||
@@ -424,33 +435,33 @@ public class SuppressionRuleTest {
|
|||||||
instance.setSha1(sha1);
|
instance.setSha1(sha1);
|
||||||
instance.addCwe("287");
|
instance.addCwe("287");
|
||||||
instance.process(dependency);
|
instance.process(dependency);
|
||||||
assertTrue(dependency.getVulnerabilities().size() == 1);
|
assertEquals(1, dependency.getVulnerabilities().size());
|
||||||
dependency.setSha1sum(sha1);
|
dependency.setSha1sum(sha1);
|
||||||
instance.process(dependency);
|
instance.process(dependency);
|
||||||
assertTrue(dependency.getVulnerabilities().isEmpty());
|
assertTrue(dependency.getVulnerabilities().isEmpty());
|
||||||
assertTrue(dependency.getSuppressedVulnerabilities().size() == 1);
|
assertEquals(1, dependency.getSuppressedVulnerabilities().size());
|
||||||
|
|
||||||
//cvss
|
//cvss
|
||||||
dependency.addVulnerability(v);
|
dependency.addVulnerability(v);
|
||||||
instance = new SuppressionRule();
|
instance = new SuppressionRule();
|
||||||
instance.addCvssBelow(5f);
|
instance.addCvssBelow(5f);
|
||||||
instance.process(dependency);
|
instance.process(dependency);
|
||||||
assertTrue(dependency.getVulnerabilities().size() == 1);
|
assertEquals(1, dependency.getVulnerabilities().size());
|
||||||
instance.addCvssBelow(8f);
|
instance.addCvssBelow(8f);
|
||||||
instance.process(dependency);
|
instance.process(dependency);
|
||||||
assertTrue(dependency.getVulnerabilities().isEmpty());
|
assertTrue(dependency.getVulnerabilities().isEmpty());
|
||||||
assertTrue(dependency.getSuppressedVulnerabilities().size() == 1);
|
assertEquals(1, dependency.getSuppressedVulnerabilities().size());
|
||||||
|
|
||||||
//cve
|
//cve
|
||||||
dependency.addVulnerability(v);
|
dependency.addVulnerability(v);
|
||||||
instance = new SuppressionRule();
|
instance = new SuppressionRule();
|
||||||
instance.addCve("CVE-2012-1337");
|
instance.addCve("CVE-2012-1337");
|
||||||
instance.process(dependency);
|
instance.process(dependency);
|
||||||
assertTrue(dependency.getVulnerabilities().size() == 1);
|
assertEquals(1, dependency.getVulnerabilities().size());
|
||||||
instance.addCve("CVE-2013-1337");
|
instance.addCve("CVE-2013-1337");
|
||||||
instance.process(dependency);
|
instance.process(dependency);
|
||||||
assertTrue(dependency.getVulnerabilities().isEmpty());
|
assertTrue(dependency.getVulnerabilities().isEmpty());
|
||||||
assertTrue(dependency.getSuppressedVulnerabilities().size() == 1);
|
assertEquals(1, dependency.getSuppressedVulnerabilities().size());
|
||||||
|
|
||||||
//cpe
|
//cpe
|
||||||
instance = new SuppressionRule();
|
instance = new SuppressionRule();
|
||||||
@@ -468,18 +479,21 @@ public class SuppressionRuleTest {
|
|||||||
instance.setFilePath(pt);
|
instance.setFilePath(pt);
|
||||||
instance.process(dependency);
|
instance.process(dependency);
|
||||||
assertTrue(dependency.getIdentifiers().isEmpty());
|
assertTrue(dependency.getIdentifiers().isEmpty());
|
||||||
assertTrue(dependency.getSuppressedIdentifiers().size() == 1);
|
assertEquals(1, dependency.getSuppressedIdentifiers().size());
|
||||||
|
|
||||||
|
instance = new SuppressionRule();
|
||||||
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.0", "some url not needed for this test");
|
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.0", "some url not needed for this test");
|
||||||
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
|
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
|
||||||
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:5.0", "some url not needed for this test");
|
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:5.0", "some url not needed for this test");
|
||||||
pt = new PropertyType();
|
pt = new PropertyType();
|
||||||
pt.setValue("cpe:/a:microsoft:.net_framework");
|
pt.setValue("cpe:/a:microsoft:.net_framework");
|
||||||
instance.addCpe(pt);
|
instance.addCpe(pt);
|
||||||
assertTrue(dependency.getIdentifiers().size() == 3);
|
instance.setBase(true);
|
||||||
|
assertEquals(3, dependency.getIdentifiers().size());
|
||||||
|
assertEquals(1, dependency.getSuppressedIdentifiers().size());
|
||||||
instance.process(dependency);
|
instance.process(dependency);
|
||||||
assertTrue(dependency.getIdentifiers().isEmpty());
|
assertTrue(dependency.getIdentifiers().isEmpty());
|
||||||
assertTrue(dependency.getSuppressedIdentifiers().size() == 3);
|
assertEquals(1, dependency.getSuppressedIdentifiers().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 OWASP.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.utils;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
public class DateUtilTest {
|
||||||
|
|
||||||
|
public DateUtilTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpClass() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDownClass() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of withinDateRange method, of class DateUtil.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testWithinDateRange() {
|
||||||
|
Calendar c = Calendar.getInstance();
|
||||||
|
|
||||||
|
long current = c.getTimeInMillis();
|
||||||
|
long lastRun = c.getTimeInMillis() - (3 * (1000 * 60 * 60 * 24));
|
||||||
|
int range = 7; // 7 days
|
||||||
|
boolean expResult = true;
|
||||||
|
boolean result = DateUtil.withinDateRange(lastRun, current, range);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
|
||||||
|
lastRun = c.getTimeInMillis() - (8 * (1000 * 60 * 60 * 24));
|
||||||
|
expResult = false;
|
||||||
|
result = DateUtil.withinDateRange(lastRun, current, range);
|
||||||
|
assertEquals(expResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -134,14 +134,14 @@ public class DependencyVersionTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testMatchesAtLeastThreeLevels() {
|
public void testMatchesAtLeastThreeLevels() {
|
||||||
|
|
||||||
DependencyVersion instance = new DependencyVersion("1.2.3.4");
|
DependencyVersion instance = new DependencyVersion("2.3.16.3");
|
||||||
DependencyVersion version = new DependencyVersion("1.2.3.5");
|
DependencyVersion version = new DependencyVersion("2.3.16.4");
|
||||||
//true tests
|
//true tests
|
||||||
assertEquals(true, instance.matchesAtLeastThreeLevels(version));
|
assertEquals(true, instance.matchesAtLeastThreeLevels(version));
|
||||||
version = new DependencyVersion("1.2");
|
version = new DependencyVersion("2.3");
|
||||||
assertEquals(true, instance.matchesAtLeastThreeLevels(version));
|
assertEquals(true, instance.matchesAtLeastThreeLevels(version));
|
||||||
//false tests
|
//false tests
|
||||||
version = new DependencyVersion("1.2.2.5");
|
version = new DependencyVersion("2.3.16.1");
|
||||||
assertEquals(false, instance.matchesAtLeastThreeLevels(version));
|
assertEquals(false, instance.matchesAtLeastThreeLevels(version));
|
||||||
version = new DependencyVersion("2");
|
version = new DependencyVersion("2");
|
||||||
assertEquals(false, instance.matchesAtLeastThreeLevels(version));
|
assertEquals(false, instance.matchesAtLeastThreeLevels(version));
|
||||||
@@ -165,6 +165,14 @@ public class DependencyVersionTest {
|
|||||||
version = new DependencyVersion("1.2.3.1");
|
version = new DependencyVersion("1.2.3.1");
|
||||||
assertEquals(-1, instance.compareTo(version));
|
assertEquals(-1, instance.compareTo(version));
|
||||||
|
|
||||||
|
instance = new DependencyVersion("1.0.1n");
|
||||||
|
version = new DependencyVersion("1.0.1m");
|
||||||
|
assertEquals(1, instance.compareTo(version));
|
||||||
|
version = new DependencyVersion("1.0.1n");
|
||||||
|
assertEquals(0, instance.compareTo(version));
|
||||||
|
version = new DependencyVersion("1.0.1o");
|
||||||
|
assertEquals(-1, instance.compareTo(version));
|
||||||
|
|
||||||
DependencyVersion[] dv = new DependencyVersion[7];
|
DependencyVersion[] dv = new DependencyVersion[7];
|
||||||
dv[0] = new DependencyVersion("2.1.3");
|
dv[0] = new DependencyVersion("2.1.3");
|
||||||
dv[1] = new DependencyVersion("2.1.3.r2");
|
dv[1] = new DependencyVersion("2.1.3.r2");
|
||||||
|
|||||||
@@ -54,13 +54,13 @@ public class DependencyVersionUtilTest {
|
|||||||
* Test of parseVersion method, of class DependencyVersionUtil.
|
* Test of parseVersion method, of class DependencyVersionUtil.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testParseVersionFromFileName() {
|
public void testParseVersion() {
|
||||||
final String[] fileName = {"something-0.9.5.jar", "lib2-1.1.jar", "lib1.5r4-someflag-R26.jar",
|
final String[] fileName = {"something-0.9.5.jar", "lib2-1.1.jar", "lib1.5r4-someflag-R26.jar",
|
||||||
"lib-1.2.5-dev-20050313.jar", "testlib_V4.4.0.jar", "lib-core-2.0.0-RC1-SNAPSHOT.jar",
|
"lib-1.2.5-dev-20050313.jar", "testlib_V4.4.0.jar", "lib-core-2.0.0-RC1-SNAPSHOT.jar",
|
||||||
"lib-jsp-2.0.1_R114940.jar", "dev-api-2.3.11_R121413.jar", "lib-api-3.7-SNAPSHOT.jar",
|
"lib-jsp-2.0.1_R114940.jar", "dev-api-2.3.11_R121413.jar", "lib-api-3.7-SNAPSHOT.jar",
|
||||||
"-", "", "1.3-beta", "6"};
|
"-", "", "1.3-beta", "6", "openssl1.0.1c", "jsf-impl-2.2.8-02.jar"};
|
||||||
final String[] expResult = {"0.9.5", "1.1", "1.5.r4", "1.2.5", "4.4.0", "2.0.0.rc1",
|
final String[] expResult = {"0.9.5", "1.1", "1.5.r4", "1.2.5", "4.4.0", "2.0.0.rc1",
|
||||||
"2.0.1.r114940", "2.3.11.r121413", "3.7", "-", null, "1.3.beta", "6"};
|
"2.0.1.r114940", "2.3.11.r121413", "3.7", "-", null, "1.3.beta", "6", "1.0.1c", "2.2.8.02"};
|
||||||
|
|
||||||
for (int i = 0; i < fileName.length; i++) {
|
for (int i = 0; i < fileName.length; i++) {
|
||||||
final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName[i]);
|
final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName[i]);
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ application.version=${pom.version}
|
|||||||
autoupdate=true
|
autoupdate=true
|
||||||
max.download.threads=3
|
max.download.threads=3
|
||||||
|
|
||||||
|
# the url to obtain the current engine version from
|
||||||
|
engine.version.url=http://jeremylong.github.io/DependencyCheck/current.txt
|
||||||
|
|
||||||
#temp.directory defaults to System.getProperty("java.io.tmpdir")
|
#temp.directory defaults to System.getProperty("java.io.tmpdir")
|
||||||
#temp.directory=[path to temp directory]
|
#temp.directory=[path to temp directory]
|
||||||
|
|
||||||
@@ -13,8 +16,12 @@ max.download.threads=3
|
|||||||
# will not be used. The data.directory will be resolved and if the connection string
|
# will not be used. The data.directory will be resolved and if the connection string
|
||||||
# below contains a %s then the data.directory will replace the %s.
|
# below contains a %s then the data.directory will replace the %s.
|
||||||
data.directory=[JAR]/data
|
data.directory=[JAR]/data
|
||||||
|
# if the filename has a %s it will be replaced with the current expected version. For file
|
||||||
|
# based databases the below filename will be added to the data directory above and then
|
||||||
|
# if the connection string has a %s it will be replaced by the directory/filename path.
|
||||||
|
data.file_name=cve.%s.h2.db
|
||||||
|
data.version=2.9
|
||||||
data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
|
data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
|
||||||
#data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;AUTOCOMMIT=ON;
|
|
||||||
#data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
|
#data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
|
||||||
|
|
||||||
# user name and password for the database connection. The inherent case is to use H2.
|
# user name and password for the database connection. The inherent case is to use H2.
|
||||||
@@ -43,11 +50,16 @@ cpe.meta.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-di
|
|||||||
cve.url.modified.validfordays=7
|
cve.url.modified.validfordays=7
|
||||||
|
|
||||||
# the path to the modified nvd cve xml file.
|
# the path to the modified nvd cve xml file.
|
||||||
cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
|
|
||||||
cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
|
|
||||||
cve.startyear=2014
|
cve.startyear=2014
|
||||||
cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
|
cve.url-1.2.modified=https://nvd.nist.gov/download/nvdcve-Modified.xml.gz
|
||||||
cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
|
#cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
|
||||||
|
cve.url-2.0.modified=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz
|
||||||
|
#cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
|
||||||
|
cve.url-1.2.base=https://nvd.nist.gov/download/nvdcve-%d.xml.gz
|
||||||
|
#cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
|
||||||
|
cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz
|
||||||
|
#cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
|
||||||
|
|
||||||
|
|
||||||
# the URL for searching Nexus for SHA-1 hashes and whether it's enabled
|
# the URL for searching Nexus for SHA-1 hashes and whether it's enabled
|
||||||
analyzer.nexus.enabled=true
|
analyzer.nexus.enabled=true
|
||||||
@@ -55,3 +67,7 @@ analyzer.nexus.url=https://repository.sonatype.org/service/local/
|
|||||||
# If set to true, the proxy will still ONLY be used if the proxy properties (proxy.url, proxy.port)
|
# If set to true, the proxy will still ONLY be used if the proxy properties (proxy.url, proxy.port)
|
||||||
# are configured
|
# are configured
|
||||||
analyzer.nexus.proxy=true
|
analyzer.nexus.proxy=true
|
||||||
|
|
||||||
|
# the URL for searching search.maven.org for SHA-1 and whether it's enabled
|
||||||
|
analyzer.central.enabled=true
|
||||||
|
analyzer.central.url=http://search.maven.org/solrsearch/select
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<filePath>c:\path\to\some.jar</filePath>
|
<filePath>c:\path\to\some.jar</filePath>
|
||||||
<cpe>cpe:/a:csv:csv:1.0</cpe>
|
<cpe>cpe:/a:csv:csv:1.0</cpe>
|
||||||
</suppress>
|
</suppress>
|
||||||
<suppress>
|
<suppress base="true">
|
||||||
<notes><![CDATA[
|
<notes><![CDATA[
|
||||||
This suppresses any jboss:jboss cpe for any test.jar in any directory.
|
This suppresses any jboss:jboss cpe for any test.jar in any directory.
|
||||||
]]></notes>
|
]]></notes>
|
||||||
|
|||||||
@@ -1,17 +1,25 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<description>This plug-in can independently execute a Dependency-Check analysis and visualize the results.</description>
|
|
||||||
<url>http://wiki.jenkins-ci.org/display/JENKINS/OWASP+Dependency-Check+Plugin</url>
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-parent</artifactId>
|
<artifactId>dependency-check-parent</artifactId>
|
||||||
<version>1.2.3</version>
|
<version>1.2.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-jenkins</artifactId>
|
<artifactId>dependency-check-jenkins</artifactId>
|
||||||
<name>Dependency-Check Jenkins Plugin</name>
|
<name>Dependency-Check Jenkins Plugin</name>
|
||||||
|
<url>http://wiki.jenkins-ci.org/display/JENKINS/OWASP+Dependency-Check+Plugin</url>
|
||||||
|
<description>dependency-check-jenkins is a Jenkins plugin that runs dependency-check-core on a project to detect publicly disclosed vulnerabilities associated with the project's dependencies. The plugin will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries. This module is simply a placeholder and does not contain the actual plugin source code. The source code and distribution of the plugin is handled via https://github.com/jenkinsci/dependency-check-jenkins and Jenkin's plugin management.</description>
|
||||||
|
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
||||||
|
<distributionManagement>
|
||||||
|
<site>
|
||||||
|
<id>github-pages-site</id>
|
||||||
|
<name>Deployment through GitHub's site deployment plugin</name>
|
||||||
|
<url>${basedir}/../target/site/${project.version}/dependency-check-jenkins</url>
|
||||||
|
</site>
|
||||||
|
</distributionManagement>
|
||||||
|
<!-- end copy -->
|
||||||
|
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<inceptionYear>2012</inceptionYear>
|
<inceptionYear>2012</inceptionYear>
|
||||||
<organization>
|
<organization>
|
||||||
@@ -31,15 +39,6 @@
|
|||||||
</roles>
|
</roles>
|
||||||
</developer>
|
</developer>
|
||||||
</developers>
|
</developers>
|
||||||
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
|
||||||
<distributionManagement>
|
|
||||||
<site>
|
|
||||||
<id>github-pages-site</id>
|
|
||||||
<name>Deployment through GitHub's site deployment plugin</name>
|
|
||||||
<url>${basedir}/../target/site/${project.version}/dependency-check-maven</url>
|
|
||||||
</site>
|
|
||||||
</distributionManagement>
|
|
||||||
<!-- end copy -->
|
|
||||||
<scm>
|
<scm>
|
||||||
<connection>scm:git:git@github.com:jenkinsci/dependency-check-jenkins.git</connection>
|
<connection>scm:git:git@github.com:jenkinsci/dependency-check-jenkins.git</connection>
|
||||||
<url>https://github.com/jenkinsci/dependency-check-jenkins</url>
|
<url>https://github.com/jenkinsci/dependency-check-jenkins</url>
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-parent</artifactId>
|
<artifactId>dependency-check-parent</artifactId>
|
||||||
<version>1.2.3</version>
|
<version>1.2.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>dependency-check-maven</artifactId>
|
<artifactId>dependency-check-maven</artifactId>
|
||||||
<packaging>maven-plugin</packaging>
|
<packaging>maven-plugin</packaging>
|
||||||
|
|
||||||
<name>Dependency-Check Maven Plugin</name>
|
<name>Dependency-Check Maven Plugin</name>
|
||||||
<description>Dependency-Check-Maven is a Maven Plugin that attempts to detect publicly disclosed vulnerabilities contained within project dependencies. It does this by determining if there is a Common Platform Enumeration (CPE) identifier for a given dependency. If found, it will generate a report linking to the associated CVE entries.</description>
|
<description>dependency-check-maven is a Maven Plugin that uses dependency-check-core to detect publicly disclosed vulnerabilities associated with the project's dependencies. The plugin will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.</description>
|
||||||
<inceptionYear>2013</inceptionYear>
|
<inceptionYear>2013</inceptionYear>
|
||||||
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
@@ -86,6 +86,23 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.16</version>
|
||||||
|
<configuration>
|
||||||
|
<systemProperties>
|
||||||
|
<property>
|
||||||
|
<name>data.directory</name>
|
||||||
|
<value>${project.build.directory}/dependency-check-data</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>temp.directory</name>
|
||||||
|
<value>${project.build.directory}/temp</value>
|
||||||
|
</property>
|
||||||
|
</systemProperties>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<inherited>true</inherited>
|
<inherited>true</inherited>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
@@ -149,6 +166,9 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>2.9.1</version>
|
<version>2.9.1</version>
|
||||||
|
<configuration>
|
||||||
|
<bottom>Copyright© 2012-14 Jeremy Long. All Rights Reserved.</bottom>
|
||||||
|
</configuration>
|
||||||
<reportSets>
|
<reportSets>
|
||||||
<reportSet>
|
<reportSet>
|
||||||
<id>default</id>
|
<id>default</id>
|
||||||
@@ -238,7 +258,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
|||||||
<linkXref>true</linkXref>
|
<linkXref>true</linkXref>
|
||||||
<sourceEncoding>utf-8</sourceEncoding>
|
<sourceEncoding>utf-8</sourceEncoding>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/generated/*.java</exclude>
|
<exclude>**/generated/**/*.java</exclude>
|
||||||
<exclude>**/HelpMojo.java</exclude>
|
<exclude>**/HelpMojo.java</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
<rulesets>
|
<rulesets>
|
||||||
@@ -312,6 +332,12 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
|||||||
<artifactId>maven-reporting-api</artifactId>
|
<artifactId>maven-reporting-api</artifactId>
|
||||||
<version>3.0</version>
|
<version>3.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jmockit</groupId>
|
||||||
|
<artifactId>jmockit</artifactId>
|
||||||
|
<version>1.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-maven.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.maven;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
|
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||||
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
|
import org.apache.maven.project.MavenProject;
|
||||||
|
import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer;
|
||||||
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maven Plugin that checks project dependencies and the dependencies of all child modules to see if they have any known
|
||||||
|
* published vulnerabilities.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
@Mojo(
|
||||||
|
name = "aggregate",
|
||||||
|
defaultPhase = LifecyclePhase.SITE,
|
||||||
|
aggregator = true,
|
||||||
|
threadSafe = true,
|
||||||
|
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
|
||||||
|
requiresOnline = true
|
||||||
|
)
|
||||||
|
public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger field reference.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(AggregateMojo.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the aggregate dependency-check goal. This runs dependency-check and generates the subsequent reports.
|
||||||
|
*
|
||||||
|
* @throws MojoExecutionException thrown if there is ane exception running the mojo
|
||||||
|
* @throws MojoFailureException thrown if dependency-check is configured to fail the build
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||||
|
final Engine engine = generateDataFile();
|
||||||
|
|
||||||
|
if (getProject() == getReactorProjects().get(getReactorProjects().size() - 1)) {
|
||||||
|
final Map<MavenProject, Set<MavenProject>> children = buildAggregateInfo();
|
||||||
|
boolean hasOrchestration = false;
|
||||||
|
for (MavenProject current : getReactorProjects()) {
|
||||||
|
final List<Dependency> dependencies = readDataFile(current);
|
||||||
|
final List<MavenProject> childProjects = getAllChildren(current, children);
|
||||||
|
//check for orchestration build - execution root with no children or dependencies
|
||||||
|
if ((dependencies == null || dependencies.isEmpty()) && childProjects.isEmpty() && current.isExecutionRoot()) {
|
||||||
|
hasOrchestration = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MavenProject current : getReactorProjects()) {
|
||||||
|
List<Dependency> dependencies = readDataFile(current);
|
||||||
|
final List<MavenProject> childProjects = getAllChildren(current, children);
|
||||||
|
//check for orchestration build - execution root with no children or dependencies
|
||||||
|
if ((dependencies == null || dependencies.isEmpty()) && childProjects.isEmpty() && current.isExecutionRoot()) {
|
||||||
|
engine.resetFileTypeAnalyzers();
|
||||||
|
for (MavenProject mod : getReactorProjects()) {
|
||||||
|
scanArtifacts(mod, engine);
|
||||||
|
}
|
||||||
|
engine.analyzeDependencies();
|
||||||
|
} else {
|
||||||
|
if (dependencies == null) {
|
||||||
|
dependencies = new ArrayList<Dependency>();
|
||||||
|
}
|
||||||
|
for (MavenProject reportOn : childProjects) {
|
||||||
|
final List<Dependency> childDeps = readDataFile(reportOn);
|
||||||
|
if (childDeps != null && !childDeps.isEmpty()) {
|
||||||
|
dependencies.addAll(childDeps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
engine.getDependencies().clear();
|
||||||
|
engine.getDependencies().addAll(dependencies);
|
||||||
|
final DependencyBundlingAnalyzer bundler = new DependencyBundlingAnalyzer();
|
||||||
|
try {
|
||||||
|
bundler.analyze(null, engine);
|
||||||
|
} catch (AnalysisException ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "An error occured grouping the dependencies; duplicate entries may exist in the report", ex);
|
||||||
|
LOGGER.log(Level.FINE, "Bundling Exception", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final File outputDir = getCorrectOutputDirectory(current);
|
||||||
|
writeReports(engine, current, outputDir);
|
||||||
|
} catch (MojoExecutionException ex) {
|
||||||
|
if (!hasOrchestration) {
|
||||||
|
throw ex;
|
||||||
|
} // else ignore this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
engine.cleanup();
|
||||||
|
Settings.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list containing all the recursive, non-pom children of the given project, never <code>null</code>.
|
||||||
|
*
|
||||||
|
* @param project the parent project to collect the child project references
|
||||||
|
* @param childMap a map of the parent-child relationships
|
||||||
|
* @return a list of child projects
|
||||||
|
*/
|
||||||
|
protected List<MavenProject> getAllChildren(MavenProject project, Map<MavenProject, Set<MavenProject>> childMap) {
|
||||||
|
final Set<MavenProject> children = childMap.get(project);
|
||||||
|
if (children == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
final List<MavenProject> result = new ArrayList<MavenProject>();
|
||||||
|
for (MavenProject child : children) {
|
||||||
|
if (isMultiModule(child)) {
|
||||||
|
result.addAll(getAllChildren(child, childMap));
|
||||||
|
} else {
|
||||||
|
result.add(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the project has pom packaging
|
||||||
|
*
|
||||||
|
* @param mavenProject Project to test
|
||||||
|
* @return <code>true</code> if it has a pom packaging; otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
protected boolean isMultiModule(MavenProject mavenProject) {
|
||||||
|
return "pom".equals(mavenProject.getPackaging());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the parent-child map.
|
||||||
|
*
|
||||||
|
* @return a map of the parent/child relationships
|
||||||
|
*/
|
||||||
|
private Map<MavenProject, Set<MavenProject>> buildAggregateInfo() {
|
||||||
|
final Map<MavenProject, Set<MavenProject>> parentChildMap = new HashMap<MavenProject, Set<MavenProject>>();
|
||||||
|
for (MavenProject proj : getReactorProjects()) {
|
||||||
|
Set<MavenProject> depList = parentChildMap.get(proj.getParent());
|
||||||
|
if (depList == null) {
|
||||||
|
depList = new HashSet<MavenProject>();
|
||||||
|
parentChildMap.put(proj.getParent(), depList);
|
||||||
|
}
|
||||||
|
depList.add(proj);
|
||||||
|
}
|
||||||
|
return parentChildMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs dependency-check's Engine and writes the serialized dependencies to disk.
|
||||||
|
*
|
||||||
|
* @return the Engine used to execute dependency-check
|
||||||
|
* @throws MojoExecutionException thrown if there is an exception running the mojo
|
||||||
|
* @throws MojoFailureException thrown if dependency-check is configured to fail the build if severe CVEs are
|
||||||
|
* identified.
|
||||||
|
*/
|
||||||
|
protected Engine generateDataFile() throws MojoExecutionException, MojoFailureException {
|
||||||
|
final Engine engine;
|
||||||
|
try {
|
||||||
|
engine = initializeEngine();
|
||||||
|
} catch (DatabaseException ex) {
|
||||||
|
LOGGER.log(Level.FINE, "Database connection error", ex);
|
||||||
|
throw new MojoExecutionException("An exception occured connecting to the local database. Please see the log file for more details.", ex);
|
||||||
|
}
|
||||||
|
scanArtifacts(getProject(), engine);
|
||||||
|
engine.analyzeDependencies();
|
||||||
|
writeDataFile(engine.getDependencies());
|
||||||
|
showSummary(engine.getDependencies());
|
||||||
|
checkForFailure(engine.getDependencies());
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canGenerateReport() {
|
||||||
|
return true; //aggregate always returns true for now - we can look at a more complicated/acurate solution later
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the report name.
|
||||||
|
*
|
||||||
|
* @param locale the location
|
||||||
|
* @return the report name
|
||||||
|
*/
|
||||||
|
public String getName(Locale locale) {
|
||||||
|
return "dependency-check:aggregate";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
|
||||||
|
*
|
||||||
|
* @param locale The Locale to get the description for
|
||||||
|
* @return the description
|
||||||
|
*/
|
||||||
|
public String getDescription(Locale locale) {
|
||||||
|
return "Generates an aggregate report of all child Maven projects providing details on any "
|
||||||
|
+ "published vulnerabilities within project dependencies. This report is a best "
|
||||||
|
+ "effort and may contain false positives and false negatives.";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,954 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-maven.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.maven;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.apache.maven.artifact.Artifact;
|
||||||
|
import org.apache.maven.doxia.sink.Sink;
|
||||||
|
import org.apache.maven.plugin.AbstractMojo;
|
||||||
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
|
import org.apache.maven.plugins.annotations.Component;
|
||||||
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
import org.apache.maven.project.MavenProject;
|
||||||
|
import org.apache.maven.reporting.MavenReport;
|
||||||
|
import org.apache.maven.reporting.MavenReportException;
|
||||||
|
import org.apache.maven.settings.Proxy;
|
||||||
|
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||||
|
import org.owasp.dependencycheck.dependency.Confidence;
|
||||||
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
|
import org.owasp.dependencycheck.dependency.Identifier;
|
||||||
|
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||||
|
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||||
|
import org.owasp.dependencycheck.utils.LogUtils;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
public abstract class BaseDependencyCheckMojo extends AbstractMojo implements MavenReport {
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc="Private fields">
|
||||||
|
/**
|
||||||
|
* Logger field reference.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(BaseDependencyCheckMojo.class.getName());
|
||||||
|
/**
|
||||||
|
* The properties file location.
|
||||||
|
*/
|
||||||
|
private static final String PROPERTIES_FILE = "mojo.properties";
|
||||||
|
/**
|
||||||
|
* Name of the logging properties file.
|
||||||
|
*/
|
||||||
|
private static final String LOG_PROPERTIES_FILE = "log.properties";
|
||||||
|
/**
|
||||||
|
* System specific new line character.
|
||||||
|
*/
|
||||||
|
private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
|
||||||
|
/**
|
||||||
|
* Sets whether or not the external report format should be used.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true)
|
||||||
|
private String dataFileName;
|
||||||
|
|
||||||
|
//</editor-fold>
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Maven bound parameters and components">
|
||||||
|
/**
|
||||||
|
* The Maven Project Object.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
private MavenProject project;
|
||||||
|
/**
|
||||||
|
* List of Maven project of the current build
|
||||||
|
*/
|
||||||
|
@Parameter(readonly = true, required = true, property = "reactorProjects")
|
||||||
|
private List<MavenProject> reactorProjects;
|
||||||
|
/**
|
||||||
|
* The path to the verbose log.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "logFile", defaultValue = "")
|
||||||
|
private String logFile = null;
|
||||||
|
/**
|
||||||
|
* The output directory. This generally maps to "target".
|
||||||
|
*/
|
||||||
|
@Parameter(defaultValue = "${project.build.directory}", required = true)
|
||||||
|
private File outputDirectory;
|
||||||
|
/**
|
||||||
|
* Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11
|
||||||
|
* which means since the CVSS scores are 0-10, by default the build will never fail.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true)
|
||||||
|
private float failBuildOnCVSS = 11;
|
||||||
|
/**
|
||||||
|
* Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to
|
||||||
|
* false. Default is true.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "autoupdate", defaultValue = "true", required = true)
|
||||||
|
private boolean autoUpdate = true;
|
||||||
|
/**
|
||||||
|
* Generate aggregate reports in multi-module projects.
|
||||||
|
*
|
||||||
|
* @deprecated use the aggregate goal instead
|
||||||
|
*/
|
||||||
|
@Parameter(property = "aggregate", defaultValue = "false")
|
||||||
|
@Deprecated
|
||||||
|
private boolean aggregate;
|
||||||
|
/**
|
||||||
|
* The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this
|
||||||
|
* within the Site plug-in unless the externalReport is set to true. Default is HTML.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "format", defaultValue = "HTML", required = true)
|
||||||
|
private String format = "HTML";
|
||||||
|
/**
|
||||||
|
* The Maven settings.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "mavenSettings", defaultValue = "${settings}", required = false)
|
||||||
|
private org.apache.maven.settings.Settings mavenSettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maven settings proxy id.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "mavenSettingsProxyId", required = false)
|
||||||
|
private String mavenSettingsProxyId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Connection Timeout.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "connectionTimeout", defaultValue = "", required = false)
|
||||||
|
private String connectionTimeout = null;
|
||||||
|
/**
|
||||||
|
* The path to the suppression file.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "suppressionFile", defaultValue = "", required = false)
|
||||||
|
private String suppressionFile = null;
|
||||||
|
/**
|
||||||
|
* Flag indicating whether or not to show a summary in the output.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "showSummary", defaultValue = "true", required = false)
|
||||||
|
private boolean showSummary = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the Jar Analyzer is enabled.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "jarAnalyzerEnabled", defaultValue = "true", required = false)
|
||||||
|
private boolean jarAnalyzerEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the Archive Analyzer is enabled.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "archiveAnalyzerEnabled", defaultValue = "true", required = false)
|
||||||
|
private boolean archiveAnalyzerEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the .NET Assembly Analyzer is enabled.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "assemblyAnalyzerEnabled", defaultValue = "true", required = false)
|
||||||
|
private boolean assemblyAnalyzerEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the .NET Nuspec Analyzer is enabled.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "nuspecAnalyzerEnabled", defaultValue = "true", required = false)
|
||||||
|
private boolean nuspecAnalyzerEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the Central Analyzer is enabled.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "centralAnalyzerEnabled", defaultValue = "true", required = false)
|
||||||
|
private boolean centralAnalyzerEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the Nexus Analyzer is enabled.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "nexusAnalyzerEnabled", defaultValue = "true", required = false)
|
||||||
|
private boolean nexusAnalyzerEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of a Nexus Pro server.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "nexusUrl", defaultValue = "", required = false)
|
||||||
|
private String nexusUrl;
|
||||||
|
/**
|
||||||
|
* Whether or not the configured proxy is used to connect to Nexus.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "nexusUsesProxy", defaultValue = "true", required = false)
|
||||||
|
private boolean nexusUsesProxy = true;
|
||||||
|
/**
|
||||||
|
* The database connection string.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "connectionString", defaultValue = "", required = false)
|
||||||
|
private String connectionString;
|
||||||
|
/**
|
||||||
|
* The database driver name. An example would be org.h2.Driver.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "databaseDriverName", defaultValue = "", required = false)
|
||||||
|
private String databaseDriverName;
|
||||||
|
/**
|
||||||
|
* The path to the database driver if it is not on the class path.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "databaseDriverPath", defaultValue = "", required = false)
|
||||||
|
private String databaseDriverPath;
|
||||||
|
/**
|
||||||
|
* The database user name.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "databaseUser", defaultValue = "", required = false)
|
||||||
|
private String databaseUser;
|
||||||
|
/**
|
||||||
|
* The password to use when connecting to the database.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "databasePassword", defaultValue = "", required = false)
|
||||||
|
private String databasePassword;
|
||||||
|
/**
|
||||||
|
* A comma-separated list of file extensions to add to analysis next to jar, zip, ....
|
||||||
|
*/
|
||||||
|
@Parameter(property = "zipExtensions", required = false)
|
||||||
|
private String zipExtensions;
|
||||||
|
/**
|
||||||
|
* Skip Analysis for Test Scope Dependencies.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "skipTestScope", defaultValue = "true", required = false)
|
||||||
|
private boolean skipTestScope = true;
|
||||||
|
/**
|
||||||
|
* Skip Analysis for Runtime Scope Dependencies.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false)
|
||||||
|
private boolean skipRuntimeScope = false;
|
||||||
|
/**
|
||||||
|
* Skip Analysis for Provided Scope Dependencies.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "skipProvidedScope", defaultValue = "false", required = false)
|
||||||
|
private boolean skipProvidedScope = false;
|
||||||
|
/**
|
||||||
|
* The data directory, hold DC SQL DB.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "dataDirectory", defaultValue = "", required = false)
|
||||||
|
private String dataDirectory;
|
||||||
|
/**
|
||||||
|
* Data Mirror URL for CVE 1.2.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "cveUrl12Modified", defaultValue = "", required = false)
|
||||||
|
private String cveUrl12Modified;
|
||||||
|
/**
|
||||||
|
* Data Mirror URL for CVE 2.0.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "cveUrl20Modified", defaultValue = "", required = false)
|
||||||
|
private String cveUrl20Modified;
|
||||||
|
/**
|
||||||
|
* Base Data Mirror URL for CVE 1.2.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "cveUrl12Base", defaultValue = "", required = false)
|
||||||
|
private String cveUrl12Base;
|
||||||
|
/**
|
||||||
|
* Data Mirror URL for CVE 2.0.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "cveUrl20Base", defaultValue = "", required = false)
|
||||||
|
private String cveUrl20Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to mono for .NET Assembly analysis on non-windows systems.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "pathToMono", defaultValue = "", required = false)
|
||||||
|
private String pathToMono;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Proxy URL.
|
||||||
|
*
|
||||||
|
* @deprecated Please use mavenSettings instead
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "proxyUrl", defaultValue = "", required = false)
|
||||||
|
@Deprecated
|
||||||
|
private String proxyUrl = null;
|
||||||
|
/**
|
||||||
|
* Sets whether or not the external report format should be used.
|
||||||
|
*
|
||||||
|
* @deprecated the internal report is no longer supported
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("CanBeFinal")
|
||||||
|
@Parameter(property = "externalReport")
|
||||||
|
@Deprecated
|
||||||
|
private String externalReport = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the destination directory for the generated Dependency-Check report. This generally maps to
|
||||||
|
* "target/site".
|
||||||
|
*/
|
||||||
|
@Parameter(property = "reportOutputDirectory", defaultValue = "${project.reporting.outputDirectory}", required = true)
|
||||||
|
private File reportOutputDirectory;
|
||||||
|
// </editor-fold>
|
||||||
|
//<editor-fold defaultstate="collapsed" desc="Base Maven implementation">
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes dependency-check.
|
||||||
|
*
|
||||||
|
* @throws MojoExecutionException thrown if there is an exception executing the mojo
|
||||||
|
* @throws MojoFailureException thrown if dependency-check failed the build
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||||
|
validateAggregate();
|
||||||
|
project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory);
|
||||||
|
runCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the aggregate configuration parameter has been set to true. If it has a MojoExecutionException is
|
||||||
|
* thrown because the aggregate configuration parameter is no longer supported.
|
||||||
|
*
|
||||||
|
* @throws MojoExecutionException thrown if aggregate is set to true
|
||||||
|
*/
|
||||||
|
private void validateAggregate() throws MojoExecutionException {
|
||||||
|
if (aggregate) {
|
||||||
|
final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. "
|
||||||
|
+ "Please use the aggregate goal instead.";
|
||||||
|
throw new MojoExecutionException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the Dependency-Check Site Report.
|
||||||
|
*
|
||||||
|
* @param sink the sink to write the report to
|
||||||
|
* @param locale the locale to use when generating the report
|
||||||
|
* @throws MavenReportException if a maven report exception occurs
|
||||||
|
* @deprecated use {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale) instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
|
||||||
|
generate((Sink) sink, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the Dependency-Check Site Report.
|
||||||
|
*
|
||||||
|
* @param sink the sink to write the report to
|
||||||
|
* @param locale the locale to use when generating the report
|
||||||
|
* @throws MavenReportException if a maven report exception occurs
|
||||||
|
*/
|
||||||
|
public void generate(Sink sink, Locale locale) throws MavenReportException {
|
||||||
|
try {
|
||||||
|
validateAggregate();
|
||||||
|
} catch (MojoExecutionException ex) {
|
||||||
|
throw new MavenReportException(ex.getMessage());
|
||||||
|
}
|
||||||
|
project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory());
|
||||||
|
try {
|
||||||
|
runCheck();
|
||||||
|
} catch (MojoExecutionException ex) {
|
||||||
|
throw new MavenReportException(ex.getMessage(), ex);
|
||||||
|
} catch (MojoFailureException ex) {
|
||||||
|
LOGGER.warning("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the correct output directory depending on if a site is being executed or not.
|
||||||
|
*
|
||||||
|
* @return the directory to write the report(s)
|
||||||
|
* @throws MojoExecutionException thrown if there is an error loading the file path
|
||||||
|
*/
|
||||||
|
protected File getCorrectOutputDirectory() throws MojoExecutionException {
|
||||||
|
return getCorrectOutputDirectory(this.project);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the correct output directory depending on if a site is being executed or not.
|
||||||
|
*
|
||||||
|
* @param current the Maven project to get the output directory from
|
||||||
|
* @return the directory to write the report(s)
|
||||||
|
* @throws MojoExecutionException thrown if there is an error loading the file path
|
||||||
|
*/
|
||||||
|
protected File getCorrectOutputDirectory(MavenProject current) throws MojoExecutionException {
|
||||||
|
final Object obj = current.getContextValue(getOutputDirectoryContextKey());
|
||||||
|
if (obj != null && obj instanceof File) {
|
||||||
|
return (File) obj;
|
||||||
|
} else {
|
||||||
|
throw new MojoExecutionException(String.format("Unable to determine output directory for '%s'", current.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans the project's artifacts and adds them to the engine's dependency list.
|
||||||
|
*
|
||||||
|
* @param project the project to scan the dependencies of
|
||||||
|
* @param engine the engine to use to scan the dependencies
|
||||||
|
*/
|
||||||
|
protected void scanArtifacts(MavenProject project, Engine engine) {
|
||||||
|
for (Artifact a : project.getArtifacts()) {
|
||||||
|
if (excludeFromScan(a)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile());
|
||||||
|
if (deps != null) {
|
||||||
|
if (deps.size() == 1) {
|
||||||
|
final Dependency d = deps.get(0);
|
||||||
|
if (d != null) {
|
||||||
|
final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
|
||||||
|
d.addAsEvidence("pom", ma, Confidence.HIGHEST);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'",
|
||||||
|
a.getGroupId(), a.getArtifactId(), a.getVersion());
|
||||||
|
LOGGER.info(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the dependency-check scan and generates the necassary report.
|
||||||
|
*
|
||||||
|
* @throws MojoExecutionException thrown if there is an exception running the scan
|
||||||
|
* @throws MojoFailureException thrown if dependency-check is configured to fail the build
|
||||||
|
*/
|
||||||
|
public abstract void runCheck() throws MojoExecutionException, MojoFailureException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the Reporting output directory.
|
||||||
|
*
|
||||||
|
* @param directory the output directory
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setReportOutputDirectory(File directory) {
|
||||||
|
reportOutputDirectory = directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the report output directory.
|
||||||
|
*
|
||||||
|
* @return the report output directory
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public File getReportOutputDirectory() {
|
||||||
|
return reportOutputDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the output directory.
|
||||||
|
*
|
||||||
|
* @return the output directory
|
||||||
|
*/
|
||||||
|
public File getOutputDirectory() {
|
||||||
|
return outputDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this is an external report. This method always returns true.
|
||||||
|
*
|
||||||
|
* @return <code>true</code>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final boolean isExternalReport() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the output name.
|
||||||
|
*
|
||||||
|
* @return the output name
|
||||||
|
*/
|
||||||
|
public String getOutputName() {
|
||||||
|
if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) {
|
||||||
|
return "dependency-check-report";
|
||||||
|
} else if ("XML".equalsIgnoreCase(this.format)) {
|
||||||
|
return "dependency-check-report.xml#";
|
||||||
|
} else if ("VULN".equalsIgnoreCase(this.format)) {
|
||||||
|
return "dependency-check-vulnerability";
|
||||||
|
} else {
|
||||||
|
LOGGER.log(Level.WARNING, "Unknown report format used during site generation.");
|
||||||
|
return "dependency-check-report";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the category name.
|
||||||
|
*
|
||||||
|
* @return the category name
|
||||||
|
*/
|
||||||
|
public String getCategoryName() {
|
||||||
|
return MavenReport.CATEGORY_PROJECT_REPORTS;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new <code>Engine</code> that can be used for scanning.
|
||||||
|
*
|
||||||
|
* @return a newly instantiated <code>Engine</code>
|
||||||
|
* @throws DatabaseException thrown if there is a database exception
|
||||||
|
*/
|
||||||
|
protected Engine initializeEngine() throws DatabaseException {
|
||||||
|
final InputStream in = BaseDependencyCheckMojo.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
|
||||||
|
LogUtils.prepareLogger(in, logFile);
|
||||||
|
populateSettings();
|
||||||
|
return new Engine(this.project, this.reactorProjects);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system
|
||||||
|
* properties required to change the proxy url, port, and connection timeout.
|
||||||
|
*/
|
||||||
|
private void populateSettings() {
|
||||||
|
Settings.initialize();
|
||||||
|
InputStream mojoProperties = null;
|
||||||
|
try {
|
||||||
|
mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
|
||||||
|
Settings.mergeProperties(mojoProperties);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "Unable to load the dependency-check ant task.properties file.");
|
||||||
|
LOGGER.log(Level.FINE, null, ex);
|
||||||
|
} finally {
|
||||||
|
if (mojoProperties != null) {
|
||||||
|
try {
|
||||||
|
mojoProperties.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.FINEST, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
|
||||||
|
if (externalReport != null) {
|
||||||
|
LOGGER.warning("The 'externalReport' option was set; this configuration option has been removed. "
|
||||||
|
+ "Please update the dependency-check-maven plugin's configuration");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proxyUrl != null && !proxyUrl.isEmpty()) {
|
||||||
|
LOGGER.warning("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead");
|
||||||
|
}
|
||||||
|
final Proxy proxy = getMavenProxy();
|
||||||
|
if (proxy != null) {
|
||||||
|
Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost());
|
||||||
|
Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort()));
|
||||||
|
final String userName = proxy.getUsername();
|
||||||
|
final String password = proxy.getPassword();
|
||||||
|
if (userName != null) {
|
||||||
|
Settings.setString(Settings.KEYS.PROXY_USERNAME, userName);
|
||||||
|
}
|
||||||
|
if (password != null) {
|
||||||
|
Settings.setString(Settings.KEYS.PROXY_PASSWORD, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
|
||||||
|
}
|
||||||
|
if (suppressionFile != null && !suppressionFile.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
//File Type Analyzer Settings
|
||||||
|
//JAR ANALYZER
|
||||||
|
Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
|
||||||
|
//NUSPEC ANALYZER
|
||||||
|
Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
|
||||||
|
//NEXUS ANALYZER
|
||||||
|
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
|
||||||
|
//NEXUS ANALYZER
|
||||||
|
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
|
||||||
|
if (nexusUrl != null && !nexusUrl.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
|
||||||
|
}
|
||||||
|
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
|
||||||
|
//ARCHIVE ANALYZER
|
||||||
|
Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled);
|
||||||
|
if (zipExtensions != null && !zipExtensions.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
|
||||||
|
}
|
||||||
|
//ASSEMBLY ANALYZER
|
||||||
|
Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled);
|
||||||
|
if (pathToMono != null && !pathToMono.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Database configuration
|
||||||
|
if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
|
||||||
|
}
|
||||||
|
if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
|
||||||
|
}
|
||||||
|
if (connectionString != null && !connectionString.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
|
||||||
|
}
|
||||||
|
if (databaseUser != null && !databaseUser.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.DB_USER, databaseUser);
|
||||||
|
}
|
||||||
|
if (databasePassword != null && !databasePassword.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
|
||||||
|
}
|
||||||
|
// Data Directory
|
||||||
|
if (dataDirectory != null && !dataDirectory.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scope Exclusion
|
||||||
|
Settings.setBoolean(Settings.KEYS.SKIP_TEST_SCOPE, skipTestScope);
|
||||||
|
Settings.setBoolean(Settings.KEYS.SKIP_RUNTIME_SCOPE, skipRuntimeScope);
|
||||||
|
Settings.setBoolean(Settings.KEYS.SKIP_PROVIDED_SCOPE, skipProvidedScope);
|
||||||
|
|
||||||
|
// CVE Data Mirroring
|
||||||
|
if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
|
||||||
|
}
|
||||||
|
if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
|
||||||
|
}
|
||||||
|
if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
|
||||||
|
}
|
||||||
|
if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) {
|
||||||
|
Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maven proxy.
|
||||||
|
*
|
||||||
|
* @return the maven proxy
|
||||||
|
*/
|
||||||
|
private Proxy getMavenProxy() {
|
||||||
|
if (mavenSettings != null) {
|
||||||
|
final List<Proxy> proxies = mavenSettings.getProxies();
|
||||||
|
if (proxies != null && proxies.size() > 0) {
|
||||||
|
if (mavenSettingsProxyId != null) {
|
||||||
|
for (Proxy proxy : proxies) {
|
||||||
|
if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) {
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (proxies.size() == 1) {
|
||||||
|
return proxies.get(0);
|
||||||
|
} else {
|
||||||
|
LOGGER.warning("Multiple proxy defentiions exist in the Maven settings. In the dependency-check "
|
||||||
|
+ "configuration set the maveSettingsProxyId so that the correct proxy will be used.");
|
||||||
|
throw new IllegalStateException("Ambiguous proxy definition");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests is the artifact should be included in the scan (i.e. is the dependency in a scope that is being scanned).
|
||||||
|
*
|
||||||
|
* @param a the Artifact to test
|
||||||
|
* @return <code>true</code> if the artifact is in an excluded scope; otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
protected boolean excludeFromScan(Artifact a) {
|
||||||
|
if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reference to the current project. This method is used instead of auto-binding the project via component
|
||||||
|
* annotation in concrete implementations of this. If the child has a <code>@Component MavenProject project;</code>
|
||||||
|
* defined then the abstract class (i.e. this class) will not have access to the current project (just the way Maven
|
||||||
|
* works with the binding).
|
||||||
|
*
|
||||||
|
* @return returns a reference to the current project
|
||||||
|
*/
|
||||||
|
protected MavenProject getProject() {
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of Maven Projects in this build.
|
||||||
|
*
|
||||||
|
* @return the list of Maven Projects in this build
|
||||||
|
*/
|
||||||
|
protected List<MavenProject> getReactorProjects() {
|
||||||
|
return reactorProjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the report format.
|
||||||
|
*
|
||||||
|
* @return the report format
|
||||||
|
*/
|
||||||
|
protected String getFormat() {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the reports for a given dependency-check engine.
|
||||||
|
*
|
||||||
|
* @param engine a dependency-check engine
|
||||||
|
* @param p the maven project
|
||||||
|
* @param outputDir the directory path to write the report(s).
|
||||||
|
*/
|
||||||
|
protected void writeReports(Engine engine, MavenProject p, File outputDir) {
|
||||||
|
DatabaseProperties prop = null;
|
||||||
|
CveDB cve = null;
|
||||||
|
try {
|
||||||
|
cve = new CveDB();
|
||||||
|
cve.open();
|
||||||
|
prop = cve.getDatabaseProperties();
|
||||||
|
} catch (DatabaseException ex) {
|
||||||
|
LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
|
||||||
|
} finally {
|
||||||
|
if (cve != null) {
|
||||||
|
cve.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop);
|
||||||
|
try {
|
||||||
|
r.generateReports(outputDir.getAbsolutePath(), format);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.SEVERE,
|
||||||
|
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
|
||||||
|
LOGGER.log(Level.FINE, null, ex);
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
LOGGER.log(Level.SEVERE,
|
||||||
|
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
|
||||||
|
LOGGER.log(Level.FINE, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary">
|
||||||
|
/**
|
||||||
|
* Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the
|
||||||
|
* configuration.
|
||||||
|
*
|
||||||
|
* @param dependencies the list of dependency objects
|
||||||
|
* @throws MojoFailureException thrown if a CVSS score is found that is higher then the threshold set
|
||||||
|
*/
|
||||||
|
protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException {
|
||||||
|
if (failBuildOnCVSS <= 10) {
|
||||||
|
final StringBuilder ids = new StringBuilder();
|
||||||
|
for (Dependency d : dependencies) {
|
||||||
|
boolean addName = true;
|
||||||
|
for (Vulnerability v : d.getVulnerabilities()) {
|
||||||
|
if (v.getCvssScore() >= failBuildOnCVSS) {
|
||||||
|
if (addName) {
|
||||||
|
addName = false;
|
||||||
|
ids.append(NEW_LINE).append(d.getFileName()).append(": ");
|
||||||
|
ids.append(v.getName());
|
||||||
|
} else {
|
||||||
|
ids.append(", ").append(v.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ids.length() > 0) {
|
||||||
|
final String msg = String.format("%n%nDependency-Check Failure:%n"
|
||||||
|
+ "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
|
||||||
|
+ "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
|
||||||
|
throw new MojoFailureException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries.
|
||||||
|
*
|
||||||
|
* @param dependencies a list of dependency objects
|
||||||
|
*/
|
||||||
|
protected void showSummary(List<Dependency> dependencies) {
|
||||||
|
if (showSummary) {
|
||||||
|
final StringBuilder summary = new StringBuilder();
|
||||||
|
for (Dependency d : dependencies) {
|
||||||
|
boolean firstEntry = true;
|
||||||
|
final StringBuilder ids = new StringBuilder();
|
||||||
|
for (Vulnerability v : d.getVulnerabilities()) {
|
||||||
|
if (firstEntry) {
|
||||||
|
firstEntry = false;
|
||||||
|
} else {
|
||||||
|
ids.append(", ");
|
||||||
|
}
|
||||||
|
ids.append(v.getName());
|
||||||
|
}
|
||||||
|
if (ids.length() > 0) {
|
||||||
|
summary.append(d.getFileName()).append(" (");
|
||||||
|
firstEntry = true;
|
||||||
|
for (Identifier id : d.getIdentifiers()) {
|
||||||
|
if (firstEntry) {
|
||||||
|
firstEntry = false;
|
||||||
|
} else {
|
||||||
|
summary.append(", ");
|
||||||
|
}
|
||||||
|
summary.append(id.getValue());
|
||||||
|
}
|
||||||
|
summary.append(") : ").append(ids).append(NEW_LINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (summary.length() > 0) {
|
||||||
|
final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities:%n%n%s"
|
||||||
|
+ "%n%nSee the dependency-check report for more details.%n%n", summary.toString());
|
||||||
|
LOGGER.log(Level.WARNING, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//</editor-fold>
|
||||||
|
//<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file">
|
||||||
|
/**
|
||||||
|
* Returns the key used to store the path to the data file that is saved by <code>writeDataFile()</code>. This key
|
||||||
|
* is used in the <code>MavenProject.(set|get)ContextValue</code>.
|
||||||
|
*
|
||||||
|
* @return the key used to store the path to the data file
|
||||||
|
*/
|
||||||
|
protected String getDataFileContextKey() {
|
||||||
|
return "dependency-check-path-" + dataFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key used to store the path to the output directory. When generating the report in the
|
||||||
|
* <code>executeAggregateReport()</code> the output directory should be obtained by using this key.
|
||||||
|
*
|
||||||
|
* @return the key used to store the path to the output directory
|
||||||
|
*/
|
||||||
|
protected String getOutputDirectoryContextKey() {
|
||||||
|
return "dependency-output-dir-" + dataFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the scan data to disk. This is used to serialize the scan data between the "check" and "aggregate" phase.
|
||||||
|
*
|
||||||
|
* @param dependencies the list of dependencies to serialize
|
||||||
|
*/
|
||||||
|
protected void writeDataFile(List<Dependency> dependencies) {
|
||||||
|
File file = null;
|
||||||
|
if (dependencies != null && project.getContextValue(this.getDataFileContextKey()) == null) {
|
||||||
|
file = new File(project.getBuild().getDirectory(), dataFileName);
|
||||||
|
OutputStream os = null;
|
||||||
|
OutputStream bos = null;
|
||||||
|
ObjectOutputStream out = null;
|
||||||
|
try {
|
||||||
|
os = new FileOutputStream(file);
|
||||||
|
bos = new BufferedOutputStream(os);
|
||||||
|
out = new ObjectOutputStream(bos);
|
||||||
|
out.writeObject(dependencies);
|
||||||
|
out.flush();
|
||||||
|
|
||||||
|
//call reset to prevent resource leaks per
|
||||||
|
//https://www.securecoding.cert.org/confluence/display/java/SER10-J.+Avoid+memory+and+resource+leaks+during+serialization
|
||||||
|
out.reset();
|
||||||
|
project.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath());
|
||||||
|
LOGGER.fine(String.format("Serialized data file written to '%s'", file.getAbsolutePath()));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "Unable to create data file used for report aggregation; "
|
||||||
|
+ "if report aggregation is being used the results may be incomplete.");
|
||||||
|
LOGGER.log(Level.FINE, ex.getMessage(), ex);
|
||||||
|
} finally {
|
||||||
|
if (out != null) {
|
||||||
|
try {
|
||||||
|
out.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.FINEST, "ignore", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bos != null) {
|
||||||
|
try {
|
||||||
|
bos.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.FINEST, "ignore", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (os != null) {
|
||||||
|
try {
|
||||||
|
os.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.FINEST, "ignore", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the serialized scan data from disk. This is used to serialize the scan data between the "check" and
|
||||||
|
* "aggregate" phase.
|
||||||
|
*
|
||||||
|
* @param project the Maven project to read the data file from
|
||||||
|
* @return a <code>Engine</code> object populated with dependencies if the serialized data file exists; otherwise
|
||||||
|
* <code>null</code> is returned
|
||||||
|
*/
|
||||||
|
protected List<Dependency> readDataFile(MavenProject project) {
|
||||||
|
final Object oPath = project.getContextValue(this.getDataFileContextKey());
|
||||||
|
if (oPath == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<Dependency> ret = null;
|
||||||
|
final String path = (String) oPath;
|
||||||
|
ObjectInputStream ois = null;
|
||||||
|
try {
|
||||||
|
ois = new ObjectInputStream(new FileInputStream(path));
|
||||||
|
ret = (List<Dependency>) ois.readObject();
|
||||||
|
} catch (FileNotFoundException ex) {
|
||||||
|
//TODO fix logging
|
||||||
|
LOGGER.log(Level.SEVERE, null, ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.SEVERE, null, ex);
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
LOGGER.log(Level.SEVERE, null, ex);
|
||||||
|
} finally {
|
||||||
|
if (ois != null) {
|
||||||
|
try {
|
||||||
|
ois.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-maven.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.maven;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.apache.maven.artifact.Artifact;
|
||||||
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
|
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||||
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maven Plugin that checks the project dependencies to see if they have any known published vulnerabilities.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
@Mojo(
|
||||||
|
name = "check",
|
||||||
|
defaultPhase = LifecyclePhase.COMPILE,
|
||||||
|
threadSafe = true,
|
||||||
|
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
|
||||||
|
requiresOnline = true
|
||||||
|
)
|
||||||
|
public class CheckMojo extends BaseDependencyCheckMojo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger field reference.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CheckMojo.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not a the report can be generated.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the report can be generated; otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean canGenerateReport() {
|
||||||
|
boolean isCapable = false;
|
||||||
|
for (Artifact a : getProject().getArtifacts()) {
|
||||||
|
if (!excludeFromScan(a)) {
|
||||||
|
isCapable = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isCapable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the dependency-check engine on the project's dependencies and generates the report.
|
||||||
|
*
|
||||||
|
* @throws MojoExecutionException thrown if there is an exception executing the goal
|
||||||
|
* @throws MojoFailureException thrown if dependency-check is configured to fail the build
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||||
|
final Engine engine;
|
||||||
|
try {
|
||||||
|
engine = initializeEngine();
|
||||||
|
} catch (DatabaseException ex) {
|
||||||
|
LOGGER.log(Level.FINE, "Database connection error", ex);
|
||||||
|
throw new MojoExecutionException("An exception occured connecting to the local database. Please see the log file for more details.", ex);
|
||||||
|
}
|
||||||
|
scanArtifacts(getProject(), engine);
|
||||||
|
if (engine.getDependencies().isEmpty()) {
|
||||||
|
LOGGER.info("No dependencies were identified that could be analyzed by dependency-check");
|
||||||
|
} else {
|
||||||
|
engine.analyzeDependencies();
|
||||||
|
writeReports(engine, getProject(), getCorrectOutputDirectory());
|
||||||
|
writeDataFile(engine.getDependencies());
|
||||||
|
showSummary(engine.getDependencies());
|
||||||
|
checkForFailure(engine.getDependencies());
|
||||||
|
}
|
||||||
|
engine.cleanup();
|
||||||
|
Settings.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the report name.
|
||||||
|
*
|
||||||
|
* @param locale the location
|
||||||
|
* @return the report name
|
||||||
|
*/
|
||||||
|
public String getName(Locale locale) {
|
||||||
|
return "dependency-check";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
|
||||||
|
*
|
||||||
|
* @param locale The Locale to get the description for
|
||||||
|
* @return the description
|
||||||
|
*/
|
||||||
|
public String getDescription(Locale locale) {
|
||||||
|
return "Generates a report providing details on any published vulnerabilities within project dependencies. "
|
||||||
|
+ "This report is a best effort and may contain false positives and false negatives.";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-maven.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.maven;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.apache.maven.project.MavenProject;
|
||||||
|
import org.owasp.dependencycheck.analyzer.Analyzer;
|
||||||
|
import org.owasp.dependencycheck.analyzer.CPEAnalyzer;
|
||||||
|
import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A modified version of the core engine specifically designed to persist some data between multiple executions of a
|
||||||
|
* multi-module Maven project.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
public class Engine extends org.owasp.dependencycheck.Engine {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger.
|
||||||
|
*/
|
||||||
|
private static final transient Logger LOGGER = Logger.getLogger(Engine.class.getName());
|
||||||
|
/**
|
||||||
|
* A key used to persist an object in the MavenProject.
|
||||||
|
*/
|
||||||
|
private static final String CPE_ANALYZER_KEY = "dependency-check-CPEAnalyzer";
|
||||||
|
/**
|
||||||
|
* The current MavenProject.
|
||||||
|
*/
|
||||||
|
private MavenProject currentProject;
|
||||||
|
/**
|
||||||
|
* The list of MavenProjects that are part of the current build.
|
||||||
|
*/
|
||||||
|
private List<MavenProject> reactorProjects;
|
||||||
|
/**
|
||||||
|
* Key used in the MavenProject context values to note whether or not an update has been executed.
|
||||||
|
*/
|
||||||
|
public static final String UPDATE_EXECUTED_FLAG = "dependency-check-update-executed";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Engine to perform anyalsis on dependencies.
|
||||||
|
*
|
||||||
|
* @param project the current Maven project
|
||||||
|
* @param reactorProjects the reactor projects for the current Maven execution
|
||||||
|
* @throws DatabaseException thrown if there is an issue connecting to the database
|
||||||
|
*/
|
||||||
|
public Engine(MavenProject project, List<MavenProject> reactorProjects) throws DatabaseException {
|
||||||
|
this.currentProject = project;
|
||||||
|
this.reactorProjects = reactorProjects;
|
||||||
|
final MavenProject root = getExecutionRoot();
|
||||||
|
if (root != null) {
|
||||||
|
LOGGER.fine(String.format("Checking root project, %s, if updates have already been completed", root.getArtifactId()));
|
||||||
|
} else {
|
||||||
|
LOGGER.fine("Checking root project, null, if updates have already been completed");
|
||||||
|
}
|
||||||
|
if (root != null && root.getContextValue(UPDATE_EXECUTED_FLAG) != null) {
|
||||||
|
System.setProperty(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE.toString());
|
||||||
|
}
|
||||||
|
initializeEngine();
|
||||||
|
if (root != null) {
|
||||||
|
root.setContextValue(UPDATE_EXECUTED_FLAG, Boolean.TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This constructor should not be called. Use Engine(MavenProject) instead.
|
||||||
|
*
|
||||||
|
* @throws DatabaseException thrown if there is an issue connecting to the database
|
||||||
|
*/
|
||||||
|
private Engine() throws DatabaseException {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given analyzer. This skips the initialization of the CPEAnalyzer if it has been initialized by a
|
||||||
|
* previous execution.
|
||||||
|
*
|
||||||
|
* @param analyzer the analyzer to initialize
|
||||||
|
* @return the initialized analyzer
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Analyzer initializeAnalyzer(Analyzer analyzer) {
|
||||||
|
if ((analyzer instanceof CPEAnalyzer)) {
|
||||||
|
CPEAnalyzer cpe = getPreviouslyLoadedCPEAnalyzer();
|
||||||
|
if (cpe != null) {
|
||||||
|
return cpe;
|
||||||
|
}
|
||||||
|
cpe = (CPEAnalyzer) super.initializeAnalyzer(analyzer);
|
||||||
|
storeCPEAnalyzer(cpe);
|
||||||
|
}
|
||||||
|
return super.initializeAnalyzer(analyzer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases resources used by the analyzers by calling close() on each analyzer.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void cleanup() {
|
||||||
|
super.cleanup();
|
||||||
|
if (currentProject == null || reactorProjects == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.currentProject == reactorProjects.get(reactorProjects.size() - 1)) {
|
||||||
|
final CPEAnalyzer cpe = getPreviouslyLoadedCPEAnalyzer();
|
||||||
|
if (cpe != null) {
|
||||||
|
cpe.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the given analyzer. This skips closing the CPEAnalyzer.
|
||||||
|
*
|
||||||
|
* @param analyzer the analyzer to close
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void closeAnalyzer(Analyzer analyzer) {
|
||||||
|
if ((analyzer instanceof CPEAnalyzer)) {
|
||||||
|
if (getPreviouslyLoadedCPEAnalyzer() == null) {
|
||||||
|
super.closeAnalyzer(analyzer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.closeAnalyzer(analyzer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the CPEAnalyzer from the root Maven Project.
|
||||||
|
*
|
||||||
|
* @return an initialized CPEAnalyzer
|
||||||
|
*/
|
||||||
|
private CPEAnalyzer getPreviouslyLoadedCPEAnalyzer() {
|
||||||
|
CPEAnalyzer cpe = null;
|
||||||
|
final MavenProject project = getExecutionRoot();
|
||||||
|
if (project != null) {
|
||||||
|
final Object obj = project.getContextValue(CPE_ANALYZER_KEY);
|
||||||
|
if (obj != null && obj instanceof CPEAnalyzer) {
|
||||||
|
cpe = (CPEAnalyzer) project.getContextValue(CPE_ANALYZER_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cpe;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a CPEAnalyzer in the root Maven Project.
|
||||||
|
*
|
||||||
|
* @param cpe the CPEAnalyzer to store
|
||||||
|
*/
|
||||||
|
private void storeCPEAnalyzer(CPEAnalyzer cpe) {
|
||||||
|
final MavenProject p = getExecutionRoot();
|
||||||
|
if (p != null) {
|
||||||
|
p.setContextValue(CPE_ANALYZER_KEY, cpe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the root Maven Project.
|
||||||
|
*
|
||||||
|
* @return the root Maven Project
|
||||||
|
*/
|
||||||
|
private MavenProject getExecutionRoot() {
|
||||||
|
if (reactorProjects == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (MavenProject p : reactorProjects) {
|
||||||
|
if (p.isExecutionRoot()) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//the following should never run, but leaving it as a failsafe.
|
||||||
|
if (this.currentProject == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MavenProject p = this.currentProject;
|
||||||
|
while (p.getParent() != null) {
|
||||||
|
p = p.getParent();
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the file type analyzers so that they can be re-used to scan additional directories. Without the reset the
|
||||||
|
* analyzer might be disabled because the first scan/analyze did not identify any files that could be processed by
|
||||||
|
* the analyzer.
|
||||||
|
*/
|
||||||
|
public void resetFileTypeAnalyzers() {
|
||||||
|
for (FileTypeAnalyzer a : getFileTypeAnalyzers()) {
|
||||||
|
a.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,19 @@
|
|||||||
|
Goals
|
||||||
|
====================
|
||||||
|
|
||||||
|
Goal | Description
|
||||||
|
-----------|-----------------------
|
||||||
|
aggregate | Runs dependency-check against the child projects and aggregates the results into a single report.
|
||||||
|
check | Runs dependency-check against the project and generates a report.
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
====================
|
====================
|
||||||
The following properties can be set on the dependency-check-maven plugin.
|
The following properties can be set on the dependency-check-maven plugin.
|
||||||
|
|
||||||
Property | Description | Default Value
|
Property | Description | Default Value
|
||||||
---------------------|------------------------------------|------------------
|
---------------------|------------------------------------|------------------
|
||||||
|
aggregate | Deprecated - use the aggregate goal instead. |
|
||||||
autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true
|
autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true
|
||||||
externalReport | When using as a Site plugin this parameter sets whether or not the external report format should be used. | false
|
|
||||||
outputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target'
|
outputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target'
|
||||||
failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11
|
failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11
|
||||||
format | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML
|
format | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML
|
||||||
@@ -23,38 +31,45 @@ Note, that specific analyzers will automatically disable themselves if no file
|
|||||||
types that they support are detected - so specifically disabling them may not
|
types that they support are detected - so specifically disabling them may not
|
||||||
be needed.
|
be needed.
|
||||||
|
|
||||||
Property | Description | Default Value
|
Property | Description | Default Value
|
||||||
------------------------|------------------------------------|------------------
|
------------------------|---------------------------------------------------------------------------|------------------
|
||||||
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
|
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
|
||||||
zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |
|
zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |
|
||||||
jarAnalyzer | Sets whether Jar Analyzer will be used. | true
|
jarAnalyzer | Sets whether Jar Analyzer will be used. | true
|
||||||
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. | true
|
centralAnalyzerEnabled | Sets whether Central Analyzer will be used. If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true
|
||||||
nexusUrl | Defines the Nexus URL. | https://repository.sonatype.org/service/local/
|
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. | true
|
||||||
|
nexusUrl | Defines the Nexus Pro Server URL. If not set the Nexus Analyzer will be disabled. |
|
||||||
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
|
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
|
||||||
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
|
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
|
||||||
assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true
|
assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true
|
||||||
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems |
|
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. |
|
||||||
|
|
||||||
Advanced Configuration
|
Advanced Configuration
|
||||||
====================
|
====================
|
||||||
The following properties can be configured in the plugin. However, they are less frequently changed. One exception
|
The following properties can be configured in the plugin. However, they are less frequently changed. One exception
|
||||||
may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment.
|
may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment.
|
||||||
|
|
||||||
Property | Description | Default Value
|
Property | Description | Default Value
|
||||||
---------------------|-------------------------------------------------------------------------|------------------
|
---------------------|--------------------------------------------------------------------------|------------------
|
||||||
cveUrl12Modified | URL for the modified CVE 1.2 | http://nvd.nist.gov/download/nvdcve-modified.xml
|
cveUrl12Modified | URL for the modified CVE 1.2. | http://nvd.nist.gov/download/nvdcve-modified.xml
|
||||||
cveUrl20Modified | URL for the modified CVE 2.0 | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
|
cveUrl20Modified | URL for the modified CVE 2.0. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
|
||||||
cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year | http://nvd.nist.gov/download/nvdcve-%d.xml
|
cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year. | http://nvd.nist.gov/download/nvdcve-%d.xml
|
||||||
cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
|
cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
|
||||||
connectionTimeout | The URL Connection Timeout. |
|
connectionTimeout | Sets the URL Connection Timeout used when downloading external data. |
|
||||||
dataDirectory | Data directory to hold SQL CVEs contents. This should generally not be changed. |
|
dataDirectory | Sets the data directory to hold SQL CVEs contents. This should generally not be changed. |
|
||||||
databaseDriverName | The name of the database driver. Example: org.h2.Driver. |
|
databaseDriverName | The name of the database driver. Example: org.h2.Driver. |
|
||||||
databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. |
|
databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. |
|
||||||
connectionString | The connection string used to connect to the database. |
|
connectionString | The connection string used to connect to the database. |
|
||||||
databaseUser | The username used when connecting to the database. |
|
databaseUser | The username used when connecting to the database. |
|
||||||
databasePassword | The password used when connecting to the database. |
|
databasePassword | The password used when connecting to the database. |
|
||||||
|
metaFileName | Sets the name of the file to use for storing the metadata about the project. | dependency-check.ser
|
||||||
|
|
||||||
Proxy Configuration
|
Proxy Configuration
|
||||||
====================
|
====================
|
||||||
Use [Maven's settings](https://maven.apache.org/settings.html#Proxies) to configure a proxy server.
|
Use [Maven's settings](https://maven.apache.org/settings.html#Proxies) to configure a proxy server. If multiple proxies
|
||||||
|
are configured in the Maven settings file you must tell dependency-check which proxy to use with the following property:
|
||||||
|
|
||||||
|
Property | Description | Default Value
|
||||||
|
---------------------|--------------------------------------------------------------------------------------|------------------
|
||||||
|
mavenSettingsProxyId | The id for the proxy, configured via settings.xml, that dependency-check should use. |
|
||||||
|
|
||||||
|
|||||||
@@ -13,11 +13,13 @@ seven days the update will only take a few seconds.
|
|||||||
#set( $H = '#' )
|
#set( $H = '#' )
|
||||||
|
|
||||||
$H$H$H Example 1:
|
$H$H$H Example 1:
|
||||||
Create the DependencyCheck-report.html in the target directory
|
Create the DependencyCheck-report.html in the target directory.
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<project>
|
<project>
|
||||||
|
...
|
||||||
<build>
|
<build>
|
||||||
|
...
|
||||||
<plugins>
|
<plugins>
|
||||||
...
|
...
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -41,11 +43,45 @@ Create the DependencyCheck-report.html in the target directory
|
|||||||
```
|
```
|
||||||
|
|
||||||
$H$H$H Example 2:
|
$H$H$H Example 2:
|
||||||
Create the DependencyCheck-report.html and fail the build for CVSS greater then 8
|
Create an aggregated dependency-check report within the site.
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<project>
|
<project>
|
||||||
|
...
|
||||||
|
<reporting>
|
||||||
|
...
|
||||||
|
<plugins>
|
||||||
|
...
|
||||||
|
<plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.owasp</groupId>
|
||||||
|
<artifactId>dependency-check-maven</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<reportSets>
|
||||||
|
<reportSet>
|
||||||
|
<reports>
|
||||||
|
<report>aggregate</report>
|
||||||
|
</reports>
|
||||||
|
</reportSet>
|
||||||
|
</reportSets>
|
||||||
|
</plugin>
|
||||||
|
</plugin>
|
||||||
|
...
|
||||||
|
</plugins>
|
||||||
|
...
|
||||||
|
</reporting>
|
||||||
|
...
|
||||||
|
</project>
|
||||||
|
```
|
||||||
|
|
||||||
|
$H$H$H Example 3:
|
||||||
|
Create the DependencyCheck-report.html and fail the build for CVSS greater then 8.
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<project>
|
||||||
|
...
|
||||||
<build>
|
<build>
|
||||||
|
...
|
||||||
<plugins>
|
<plugins>
|
||||||
...
|
...
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -71,44 +107,14 @@ Create the DependencyCheck-report.html and fail the build for CVSS greater then
|
|||||||
</project>
|
</project>
|
||||||
```
|
```
|
||||||
|
|
||||||
$H$H$H Example 3:
|
|
||||||
Create the dependency-check report within the site
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<project>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
...
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-site-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<reportPlugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.owasp</groupId>
|
|
||||||
<artifactId>dependency-check-maven</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<configuration>
|
|
||||||
<externalReport>false</externalReport>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</reportPlugins>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
...
|
|
||||||
</plugins>
|
|
||||||
...
|
|
||||||
</build>
|
|
||||||
...
|
|
||||||
</project>
|
|
||||||
```
|
|
||||||
|
|
||||||
$H$H$H Example 4:
|
$H$H$H Example 4:
|
||||||
Create the DependencyCheck-report.html and skip artifacts no bundled in distribution (Provided and Runtime scope)
|
Create the DependencyCheck-report.html and skip artifacts not bundled in distribution (Provided and Runtime scope).
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<project>
|
<project>
|
||||||
|
...
|
||||||
<build>
|
<build>
|
||||||
|
...
|
||||||
<plugins>
|
<plugins>
|
||||||
...
|
...
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -136,11 +142,13 @@ Create the DependencyCheck-report.html and skip artifacts no bundled in distribu
|
|||||||
```
|
```
|
||||||
|
|
||||||
$H$H$H Example 5:
|
$H$H$H Example 5:
|
||||||
Create the DependencyCheck-report.html and use internal mirroring of CVE contents
|
Create the DependencyCheck-report.html and use internal mirroring of CVE contents.
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<project>
|
<project>
|
||||||
|
...
|
||||||
<build>
|
<build>
|
||||||
|
...
|
||||||
<plugins>
|
<plugins>
|
||||||
...
|
...
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-maven.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.maven;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import mockit.Mock;
|
||||||
|
import mockit.MockUp;
|
||||||
|
import org.apache.maven.artifact.Artifact;
|
||||||
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
|
import org.apache.maven.plugin.testing.stubs.ArtifactStub;
|
||||||
|
import org.apache.maven.project.MavenProject;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
|
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
public class BaseDependencyCheckMojoTest extends BaseTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of scanArtifacts method, of class BaseDependencyCheckMojo.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testScanArtifacts() throws DatabaseException, InvalidSettingException {
|
||||||
|
MavenProject project = new MockUp<MavenProject>() {
|
||||||
|
@Mock
|
||||||
|
public Set<Artifact> getArtifacts() {
|
||||||
|
Set<Artifact> artifacts = new HashSet<Artifact>();
|
||||||
|
Artifact a = new ArtifactStub();
|
||||||
|
try {
|
||||||
|
File file = new File(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI());
|
||||||
|
a.setFile(file);
|
||||||
|
artifacts.add(a);
|
||||||
|
} catch (URISyntaxException ex) {
|
||||||
|
Logger.getLogger(BaseDependencyCheckMojoTest.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
//File file = new File(this.getClass().getClassLoader().getResource("daytrader-ear-2.1.7.ear").getPath());
|
||||||
|
|
||||||
|
return artifacts;
|
||||||
|
}
|
||||||
|
}.getMockInstance();
|
||||||
|
|
||||||
|
boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
|
||||||
|
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
|
||||||
|
Engine engine = new Engine(null, null);
|
||||||
|
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
|
||||||
|
|
||||||
|
assertTrue(engine.getDependencies().isEmpty());
|
||||||
|
BaseDependencyCheckMojoImpl instance = new BaseDependencyCheckMojoImpl();
|
||||||
|
instance.scanArtifacts(project, engine);
|
||||||
|
assertFalse(engine.getDependencies().isEmpty());
|
||||||
|
engine.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BaseDependencyCheckMojoImpl extends BaseDependencyCheckMojo {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName(Locale locale) {
|
||||||
|
return "test implementation";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription(Locale locale) {
|
||||||
|
return "test implementation";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canGenerateReport() {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-maven.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.maven;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
public class BaseTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The properties file location.
|
||||||
|
*/
|
||||||
|
public static final String PROPERTIES_FILE = "mojo.properties";
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpClass() throws Exception {
|
||||||
|
Settings.initialize();
|
||||||
|
InputStream mojoProperties = BaseTest.class.getClassLoader().getResourceAsStream(BaseTest.PROPERTIES_FILE);
|
||||||
|
Settings.mergeProperties(mojoProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDownClass() throws Exception {
|
||||||
|
Settings.cleanup(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of dependency-check-maven.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package org.owasp.dependencycheck.maven;
|
|
||||||
|
|
||||||
import org.apache.maven.plugin.testing.AbstractMojoTestCase;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO - figure out how to get the test harness to work. ATM no tests are running.
|
|
||||||
*
|
|
||||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
|
||||||
*/
|
|
||||||
public class DependencyCheckMojoTest extends AbstractMojoTestCase {
|
|
||||||
|
|
||||||
public DependencyCheckMojoTest() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void setUpClass() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void tearDownClass() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() {
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Test of execute method, of class DependencyCheckMojo.
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// public void testExecute() throws Exception {
|
|
||||||
// System.out.println("execute");
|
|
||||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
|
||||||
// instance.execute();
|
|
||||||
// // TODO review the generated test code and remove the default call to fail.
|
|
||||||
// fail("The test case is a prototype.");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Test of generate method, of class DependencyCheckMojo.
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// public void testGenerate_Sink_Locale() throws Exception {
|
|
||||||
// System.out.println("generate");
|
|
||||||
// org.codehaus.doxia.sink.Sink sink = null;
|
|
||||||
// Locale locale = null;
|
|
||||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
|
||||||
// instance.generate(sink, locale);
|
|
||||||
// // TODO review the generated test code and remove the default call to fail.
|
|
||||||
// fail("The test case is a prototype.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test of generate method, of class DependencyCheckMojo.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testGenerate_Sink_SinkFactory_Locale() throws Exception {
|
|
||||||
//can't get the test-harness to work.
|
|
||||||
// File samplePom = new File(this.getClass().getClassLoader().getResource("sample.xml").toURI());
|
|
||||||
// DependencyCheckMojo mojo = (DependencyCheckMojo) lookupMojo("check", samplePom);
|
|
||||||
// assertNotNull("Unable to load mojo", mojo);
|
|
||||||
//
|
|
||||||
// File out = mojo.getReportOutputDirectory();
|
|
||||||
// OutputStream os = new FileOutputStream(out);
|
|
||||||
// MySink sink = new MySink(os);
|
|
||||||
// Locale locale = new Locale("en");
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// mojo.generate(sink, null, locale);
|
|
||||||
// sink.close();
|
|
||||||
}
|
|
||||||
// /**
|
|
||||||
// * Test of getOutputName method, of class DependencyCheckMojo.
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// public void testGetOutputName() {
|
|
||||||
// System.out.println("getOutputName");
|
|
||||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
|
||||||
// String expResult = "";
|
|
||||||
// String result = instance.getOutputName();
|
|
||||||
// assertEquals(expResult, result);
|
|
||||||
// // TODO review the generated test code and remove the default call to fail.
|
|
||||||
// fail("The test case is a prototype.");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Test of getCategoryName method, of class DependencyCheckMojo.
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// public void testGetCategoryName() {
|
|
||||||
// System.out.println("getCategoryName");
|
|
||||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
|
||||||
// String expResult = "";
|
|
||||||
// String result = instance.getCategoryName();
|
|
||||||
// assertEquals(expResult, result);
|
|
||||||
// // TODO review the generated test code and remove the default call to fail.
|
|
||||||
// fail("The test case is a prototype.");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Test of getName method, of class DependencyCheckMojo.
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// public void testGetName() {
|
|
||||||
// System.out.println("getName");
|
|
||||||
// Locale locale = null;
|
|
||||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
|
||||||
// String expResult = "";
|
|
||||||
// String result = instance.getName(locale);
|
|
||||||
// assertEquals(expResult, result);
|
|
||||||
// // TODO review the generated test code and remove the default call to fail.
|
|
||||||
// fail("The test case is a prototype.");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Test of setReportOutputDirectory method, of class DependencyCheckMojo.
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// public void testSetReportOutputDirectory() {
|
|
||||||
// System.out.println("setReportOutputDirectory");
|
|
||||||
// File directory = null;
|
|
||||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
|
||||||
// instance.setReportOutputDirectory(directory);
|
|
||||||
// // TODO review the generated test code and remove the default call to fail.
|
|
||||||
// fail("The test case is a prototype.");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Test of getReportOutputDirectory method, of class DependencyCheckMojo.
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// public void testGetReportOutputDirectory() {
|
|
||||||
// System.out.println("getReportOutputDirectory");
|
|
||||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
|
||||||
// File expResult = null;
|
|
||||||
// File result = instance.getReportOutputDirectory();
|
|
||||||
// assertEquals(expResult, result);
|
|
||||||
// // TODO review the generated test code and remove the default call to fail.
|
|
||||||
// fail("The test case is a prototype.");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Test of getDescription method, of class DependencyCheckMojo.
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// public void testGetDescription() {
|
|
||||||
// System.out.println("getDescription");
|
|
||||||
// Locale locale = null;
|
|
||||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
|
||||||
// String expResult = "";
|
|
||||||
// String result = instance.getDescription(locale);
|
|
||||||
// assertEquals(expResult, result);
|
|
||||||
// // TODO review the generated test code and remove the default call to fail.
|
|
||||||
// fail("The test case is a prototype.");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Test of isExternalReport method, of class DependencyCheckMojo.
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// public void testIsExternalReport() {
|
|
||||||
// System.out.println("isExternalReport");
|
|
||||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
|
||||||
// boolean expResult = false;
|
|
||||||
// boolean result = instance.isExternalReport();
|
|
||||||
// assertEquals(expResult, result);
|
|
||||||
// // TODO review the generated test code and remove the default call to fail.
|
|
||||||
// fail("The test case is a prototype.");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Test of canGenerateReport method, of class DependencyCheckMojo.
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// public void testCanGenerateReport() {
|
|
||||||
// System.out.println("canGenerateReport");
|
|
||||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
|
||||||
// boolean expResult = false;
|
|
||||||
// boolean result = instance.canGenerateReport();
|
|
||||||
// assertEquals(expResult, result);
|
|
||||||
// // TODO review the generated test code and remove the default call to fail.
|
|
||||||
// fail("The test case is a prototype.");
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
@@ -1,601 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of dependency-check-maven.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package org.owasp.dependencycheck.maven;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import org.apache.maven.doxia.logging.Log;
|
|
||||||
import org.apache.maven.doxia.sink.Sink;
|
|
||||||
import org.apache.maven.doxia.sink.SinkEventAttributes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
|
||||||
*/
|
|
||||||
public class MySink implements Sink {
|
|
||||||
|
|
||||||
private OutputStreamWriter out = null;
|
|
||||||
|
|
||||||
public MySink(OutputStream os) {
|
|
||||||
out = new OutputStreamWriter(os);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeTag(String tag) {
|
|
||||||
try {
|
|
||||||
out.write(tag);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.getLogger(MySink.class.getName()).log(Level.SEVERE, "Error writing a tag; unable to generate the report");
|
|
||||||
Logger.getLogger(MySink.class.getName()).log(Level.FINE, null, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void head() {
|
|
||||||
writeTag("<head>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void head_() {
|
|
||||||
writeTag("</head>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void title() {
|
|
||||||
writeTag("<title>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void title_() {
|
|
||||||
writeTag("</title>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void author() {
|
|
||||||
writeTag("<author>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void author_() {
|
|
||||||
writeTag("</author>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void date() {
|
|
||||||
writeTag("<time>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void date_() {
|
|
||||||
writeTag("</time>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void body() {
|
|
||||||
writeTag("<body>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void body_() {
|
|
||||||
writeTag("</body>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle() {
|
|
||||||
writeTag("<h1>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle_() {
|
|
||||||
writeTag("</h1>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void section1() {
|
|
||||||
writeTag("<div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void section1_() {
|
|
||||||
writeTag("</div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle1() {
|
|
||||||
writeTag("<h2>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle1_() {
|
|
||||||
writeTag("</h2>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void section2() {
|
|
||||||
writeTag("<div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void section2_() {
|
|
||||||
writeTag("</div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle2() {
|
|
||||||
writeTag("<h3>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle2_() {
|
|
||||||
writeTag("</h3>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void section3() {
|
|
||||||
writeTag("<div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void section3_() {
|
|
||||||
writeTag("</div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle3() {
|
|
||||||
writeTag("<h4>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle3_() {
|
|
||||||
writeTag("</h4>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void section4() {
|
|
||||||
writeTag("<div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void section4_() {
|
|
||||||
writeTag("</div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle4() {
|
|
||||||
writeTag("<h5>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle4_() {
|
|
||||||
writeTag("</h5>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void section5() {
|
|
||||||
writeTag("<div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void section5_() {
|
|
||||||
writeTag("</div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle5() {
|
|
||||||
writeTag("<h6>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sectionTitle5_() {
|
|
||||||
writeTag("</h6>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void list() {
|
|
||||||
writeTag("<ul>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void list_() {
|
|
||||||
writeTag("</ul>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void listItem() {
|
|
||||||
writeTag("<li>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void listItem_() {
|
|
||||||
writeTag("</li>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void numberedList(int numbering) {
|
|
||||||
writeTag("<ol>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void numberedList_() {
|
|
||||||
writeTag("</ol>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void numberedListItem() {
|
|
||||||
writeTag("<li>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void numberedListItem_() {
|
|
||||||
writeTag("</li>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void definitionList() {
|
|
||||||
writeTag("<dl>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void definitionList_() {
|
|
||||||
writeTag("</dl>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void definitionListItem() {
|
|
||||||
writeTag("<dt>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void definitionListItem_() {
|
|
||||||
writeTag("</dt>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void definition() {
|
|
||||||
writeTag("<dd>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void definition_() {
|
|
||||||
writeTag("</dd>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void definedTerm() {
|
|
||||||
writeTag("<dt>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void definedTerm_() {
|
|
||||||
writeTag("</dt>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void figure() {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void figure_() {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void figureCaption() {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void figureCaption_() {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void figureGraphics(String name) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void table() {
|
|
||||||
writeTag("<table>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void table_() {
|
|
||||||
writeTag("</table>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableRows(int[] justification, boolean grid) {
|
|
||||||
writeTag("<tr>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableRows_() {
|
|
||||||
writeTag("</tr>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableRow() {
|
|
||||||
writeTag("<tr>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableRow_() {
|
|
||||||
writeTag("</tr>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableCell() {
|
|
||||||
writeTag("<td>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableCell(String width) {
|
|
||||||
writeTag("<td>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableCell_() {
|
|
||||||
writeTag("</td>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableHeaderCell() {
|
|
||||||
writeTag("<th>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableHeaderCell(String width) {
|
|
||||||
writeTag("<th>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableHeaderCell_() {
|
|
||||||
writeTag("</th>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableCaption() {
|
|
||||||
writeTag("<caption>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableCaption_() {
|
|
||||||
writeTag("</caption>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void paragraph() {
|
|
||||||
writeTag("<p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void paragraph_() {
|
|
||||||
writeTag("</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void verbatim(boolean boxed) {
|
|
||||||
writeTag("<pre>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void verbatim_() {
|
|
||||||
writeTag("</pre>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void horizontalRule() {
|
|
||||||
writeTag("<hr/>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pageBreak() {
|
|
||||||
writeTag("<br/>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void anchor(String name) {
|
|
||||||
writeTag("<a href=\"" + name + "\">");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void anchor_() {
|
|
||||||
writeTag("</a>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void link(String name) {
|
|
||||||
writeTag("<link href=\"" + name + "\">");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void link_() {
|
|
||||||
writeTag("</link>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void italic() {
|
|
||||||
writeTag("<i>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void italic_() {
|
|
||||||
writeTag("</i>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bold() {
|
|
||||||
writeTag("<b>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bold_() {
|
|
||||||
writeTag("</b>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void monospaced() {
|
|
||||||
writeTag("<pre>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void monospaced_() {
|
|
||||||
writeTag("</pre>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void lineBreak() {
|
|
||||||
writeTag("<br>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void nonBreakingSpace() {
|
|
||||||
writeTag(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void text(String text) {
|
|
||||||
try {
|
|
||||||
//TODO add HTML Encoding - or figure out how to get the doxia xhtmlsink to work.
|
|
||||||
out.write(text);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.getLogger(MySink.class.getName()).log(Level.SEVERE, "Error writing a text; unable to generate the report");
|
|
||||||
Logger.getLogger(MySink.class.getName()).log(Level.FINE, null, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void rawText(String text) {
|
|
||||||
try {
|
|
||||||
out.write(text);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.getLogger(MySink.class.getName()).log(Level.SEVERE, "Error writing raw text; unable to generate the report");
|
|
||||||
Logger.getLogger(MySink.class.getName()).log(Level.FINE, null, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void flush() {
|
|
||||||
try {
|
|
||||||
out.flush();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.getLogger(MySink.class.getName()).log(Level.FINEST, null, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
flush();
|
|
||||||
try {
|
|
||||||
out.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.getLogger(MySink.class.getName()).log(Level.FINEST, null, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void head(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void title(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void author(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void date(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void body(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void section(int i, SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void section_(int i) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sectionTitle(int i, SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sectionTitle_(int i) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void list(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void listItem(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void numberedList(int i, SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void numberedListItem(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void definitionList(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void definitionListItem(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void definition(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void definedTerm(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void figure(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void figureCaption(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void figureGraphics(String string, SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void table(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tableRow(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tableCell(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tableHeaderCell(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tableCaption(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void paragraph(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void verbatim(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void horizontalRule(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void anchor(String string, SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void link(String string, SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void lineBreak(SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void text(String string, SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void comment(String string) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unknown(String string, Object[] os, SinkEventAttributes sea) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enableLogging(Log log) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# the path to the data directory
|
||||||
|
data.directory=[JAR]/dependency-check-data
|
||||||
@@ -21,18 +21,18 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-parent</artifactId>
|
<artifactId>dependency-check-parent</artifactId>
|
||||||
<version>1.2.3</version>
|
<version>1.2.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>dependency-check-utils</artifactId>
|
<artifactId>dependency-check-utils</artifactId>
|
||||||
<name>Dependency-Check Utils</name>
|
<name>Dependency-Check Utils</name>
|
||||||
<description>Dependency-check-utils a collection of common utlity classes used within dependency-check.</description>
|
<description>dependency-check-utils is a collection of common utlity classes used within dependency-check that might be useful in other projects.</description>
|
||||||
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
<site>
|
<site>
|
||||||
<id>github-pages-site</id>
|
<id>github-pages-site</id>
|
||||||
<name>Deployment through GitHub's site deployment plugin</name>
|
<name>Deployment through GitHub's site deployment plugin</name>
|
||||||
<url>${basedir}/../target/site/${project.version}/dependency-check-ant</url>
|
<url>${basedir}/../target/site/${project.version}/dependency-check-utils</url>
|
||||||
</site>
|
</site>
|
||||||
</distributionManagement>
|
</distributionManagement>
|
||||||
<!-- end copy -->
|
<!-- end copy -->
|
||||||
@@ -158,6 +158,9 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>2.9.1</version>
|
<version>2.9.1</version>
|
||||||
|
<configuration>
|
||||||
|
<bottom>Copyright© 2012-14 Jeremy Long. All Rights Reserved.</bottom>
|
||||||
|
</configuration>
|
||||||
<reportSets>
|
<reportSets>
|
||||||
<reportSet>
|
<reportSet>
|
||||||
<id>default</id>
|
<id>default</id>
|
||||||
@@ -246,6 +249,9 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
|
|||||||
<targetJdk>1.6</targetJdk>
|
<targetJdk>1.6</targetJdk>
|
||||||
<linkXref>true</linkXref>
|
<linkXref>true</linkXref>
|
||||||
<sourceEncoding>utf-8</sourceEncoding>
|
<sourceEncoding>utf-8</sourceEncoding>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/org/owasp/dependencycheck/org/apache/**/*.java</exclude>
|
||||||
|
</excludes>
|
||||||
<rulesets>
|
<rulesets>
|
||||||
<ruleset>../src/main/config/dcrules.xml</ruleset>
|
<ruleset>../src/main/config/dcrules.xml</ruleset>
|
||||||
<ruleset>/rulesets/java/basic.xml</ruleset>
|
<ruleset>/rulesets/java/basic.xml</ruleset>
|
||||||
@@ -258,6 +264,9 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
|
|||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>findbugs-maven-plugin</artifactId>
|
<artifactId>findbugs-maven-plugin</artifactId>
|
||||||
<version>2.5.3</version>
|
<version>2.5.3</version>
|
||||||
|
<configuration>
|
||||||
|
<onlyAnalyze>org.owasp.dependencycheck.utils.*</onlyAnalyze>
|
||||||
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</reportPlugins>
|
</reportPlugins>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.org.apache.tools.ant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals an error condition during a build
|
||||||
|
*/
|
||||||
|
public class BuildException extends RuntimeException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -5419014565354664240L;
|
||||||
|
|
||||||
|
/** Location in the build file where the exception occurred */
|
||||||
|
private Location location = Location.UNKNOWN_LOCATION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a build exception with no descriptive information.
|
||||||
|
*/
|
||||||
|
public BuildException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an exception with the given descriptive message.
|
||||||
|
*
|
||||||
|
* @param message A description of or information about the exception.
|
||||||
|
* Should not be <code>null</code>.
|
||||||
|
*/
|
||||||
|
public BuildException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an exception with the given message and exception as
|
||||||
|
* a root cause.
|
||||||
|
*
|
||||||
|
* @param message A description of or information about the exception.
|
||||||
|
* Should not be <code>null</code> unless a cause is specified.
|
||||||
|
* @param cause The exception that might have caused this one.
|
||||||
|
* May be <code>null</code>.
|
||||||
|
*/
|
||||||
|
public BuildException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an exception with the given message and exception as
|
||||||
|
* a root cause and a location in a file.
|
||||||
|
*
|
||||||
|
* @param msg A description of or information about the exception.
|
||||||
|
* Should not be <code>null</code> unless a cause is specified.
|
||||||
|
* @param cause The exception that might have caused this one.
|
||||||
|
* May be <code>null</code>.
|
||||||
|
* @param location The location in the project file where the error
|
||||||
|
* occurred. Must not be <code>null</code>.
|
||||||
|
*/
|
||||||
|
public BuildException(String msg, Throwable cause, Location location) {
|
||||||
|
this(msg, cause);
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an exception with the given exception as a root cause.
|
||||||
|
*
|
||||||
|
* @param cause The exception that might have caused this one.
|
||||||
|
* Should not be <code>null</code>.
|
||||||
|
*/
|
||||||
|
public BuildException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an exception with the given descriptive message and a
|
||||||
|
* location in a file.
|
||||||
|
*
|
||||||
|
* @param message A description of or information about the exception.
|
||||||
|
* Should not be <code>null</code>.
|
||||||
|
* @param location The location in the project file where the error
|
||||||
|
* occurred. Must not be <code>null</code>.
|
||||||
|
*/
|
||||||
|
public BuildException(String message, Location location) {
|
||||||
|
super(message);
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an exception with the given exception as
|
||||||
|
* a root cause and a location in a file.
|
||||||
|
*
|
||||||
|
* @param cause The exception that might have caused this one.
|
||||||
|
* Should not be <code>null</code>.
|
||||||
|
* @param location The location in the project file where the error
|
||||||
|
* occurred. Must not be <code>null</code>.
|
||||||
|
*/
|
||||||
|
public BuildException(Throwable cause, Location location) {
|
||||||
|
this(cause);
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nested exception, if any.
|
||||||
|
*
|
||||||
|
* @return the nested exception, or <code>null</code> if no
|
||||||
|
* exception is associated with this one
|
||||||
|
* @deprecated Use {@link #getCause} instead.
|
||||||
|
*/
|
||||||
|
public Throwable getException() {
|
||||||
|
return getCause();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the location of the error and the error message.
|
||||||
|
*
|
||||||
|
* @return the location of the error and the error message
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
return location.toString() + getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the file location where the error occurred.
|
||||||
|
*
|
||||||
|
* @param location The file location where the error occurred.
|
||||||
|
* Must not be <code>null</code>.
|
||||||
|
*/
|
||||||
|
public void setLocation(Location location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the file location where the error occurred.
|
||||||
|
*
|
||||||
|
* @return the file location where the error occurred.
|
||||||
|
*/
|
||||||
|
public Location getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user