Compare commits

...

307 Commits

Author SHA1 Message Date
Jeremy Long
72f9564757 version 1.2.0
Former-commit-id: b678810925b242d0ab9c17cc43c7edc4583ef8e3
2014-04-28 08:58:09 -04:00
Jeremy Long
ab1a80152d excluded HelpMojo from PMD
Former-commit-id: 01cd292267305c6b6ed017dfcbe40ea53d4313e8
2014-04-28 08:20:11 -04:00
Jeremy Long
a87c677a35 checkstyle correction
Former-commit-id: 542c5817a18cc0f372dabd8e8010c4c93b5ef34b
2014-04-28 08:19:54 -04:00
Jeremy Long
9e0ed57cec checkstyle corrections... javadoc, final variables, etc.
Former-commit-id: 87905c8a957efb5b57e1c142eda9e7c2e7312f78
2014-04-27 17:16:49 -04:00
Jeremy Long
767f4797b0 moved checkstyle configuration to match pmd
Former-commit-id: ef4ac52a2fa483d776b6191356ce98486832a250
2014-04-27 09:31:16 -04:00
Jeremy Long
8f8c9c4582 updated to reduce exception messages during build when mono isn't available
Former-commit-id: b6701c012669d3b5fc9e8b7cc168ac8d5df4d8f0
2014-04-27 09:18:50 -04:00
Jeremy Long
9acfe3afdb Merge branch 'master' of github.com:jeremylong/DependencyCheck
Former-commit-id: 45916cc4a0b3334ac9d0fe5d849032556db59f8e
2014-04-27 08:51:31 -04:00
Jeremy Long
9c03962c26 Merge branch 'master' of github.com:bkimminich/DependencyCheck into bkimminich-master
Former-commit-id: a25a71286aed7adb384e7efde40278006e67d847
2014-04-27 08:50:59 -04:00
Jeremy Long
a135460caa moved pmd rules to follow the maven directory structure
Former-commit-id: 71f80a18aad5c92662a2eab142009f243e7416bf
2014-04-27 08:50:03 -04:00
Jeremy Long
7f72ef88e0 removed code duplication ensuring temporary directory exists
Former-commit-id: fba6dfcd3a133378c5f46f4126fa97c02ab110be
2014-04-27 08:42:02 -04:00
Steve Springett
fa1adc5294 Cleaning up Velocity. Minor change to Engine and ServiceLoaders to optionally use custom ClassLoader.
Former-commit-id: 8c1a58247faeaa032ca7389106378b095ac45edf
2014-04-26 01:25:56 -05:00
Björn Kimminich
579b526196 organized imports
extracted exception handling


Former-commit-id: 5fa0d46fc4241e8feae58e4f1e8fd365aedb27f5
2014-04-25 14:39:56 +02:00
Björn Kimminich
654e6942cb attempt to locate suppressions in classpath when they cannot be found via URL or file path
Former-commit-id: 03e7f14d9561940bb83a38faab926a5e45f2748b
2014-04-25 14:33:15 +02:00
Jeremy Long
b7ed1429de added new test case for the hint analyzer
Former-commit-id: 019194943dd81b11201ef41e00bb4f5d9aa6fe73
2014-04-24 07:23:39 -04:00
Will Stranathan
6642c23761 Updated PMD configuration to work with all the projects.
Former-commit-id: 80b9aac40019ef95d95ac5dcd3cb417290c37d7e
2014-04-22 20:50:06 -04:00
Jeremy Long
f2b908c859 checkstyle corrections
Former-commit-id: 8833f928a384474df1dd5b306e835ec8919a572a
2014-04-22 09:01:53 -04:00
Jeremy Long
709840ca02 removed unused variable and inner assignment
Former-commit-id: 24b669e885ae51c2812ed1b31d86241b0a13509d
2014-04-22 08:14:30 -04:00
Jeremy Long
9fe596f3de checkstyle corrections
Former-commit-id: 2f6fb660cd0152de284b55de3aab9cbb1b22b0b0
2014-04-22 08:10:54 -04:00
Jeremy Long
228bb2fc86 converted long running tests to integration tests
Former-commit-id: 36a20d08b8de14b369a083d1c52e0f458b276d47
2014-04-21 21:46:54 -04:00
Jeremy Long
d07947f712 spelling corrections
Former-commit-id: 6b3c1ae8e8150cca82449f5e5b4448a9a829e680
2014-04-21 21:01:10 -04:00
Jeremy Long
70022088fb spelling corrections
Former-commit-id: 43b77de6e21a4d586f7b66b6da0045572c097f42
2014-04-21 20:59:18 -04:00
Jeremy Long
9143564d41 merged update from Will
Former-commit-id: ee4020e643221aa4ea403a6fb59314e65ab9e1b5
2014-04-21 20:42:58 -04:00
Jeremy Long
55440ae32b Merge branch 'master' of github.com:jeremylong/DependencyCheck
Former-commit-id: ddb7a60c533bf82e5f6faa9a5fbd794ca7dfaf5f
2014-04-21 20:31:48 -04:00
Jeremy Long
db65c0b422 spelling corrections
Former-commit-id: 35f1650765a5e8de33ef078a13b20bfa2994eb71
2014-04-21 20:31:26 -04:00
Jeremy Long
f0297938b6 spelling corrections
Former-commit-id: 56795c1f9276347f4b383e911c8c1b35918d55d9
2014-04-21 20:21:53 -04:00
Steve Springett
4d390b65fe Removing Jenkins workaround for previous snapshot's race condition
Former-commit-id: 69304c08687945ebecaf3f253e16861dd9627d43
2014-04-21 14:19:30 -05:00
Will Stranathan
294df359d5 Added PMD rule to find Loggers that weren't fields and corrected existing instances.
Former-commit-id: d1844676a9e2f9ccbbc584d51f9dc13ecc255c11
2014-04-19 22:08:17 -04:00
Jeremy Long
a855d53542 checkstyle corrections
Former-commit-id: 8caae0e4f0dd1828419c84b081fbc32d4d7be93c
2014-04-19 12:49:57 -04:00
Jeremy Long
57a0c48293 speed up test by disabling auto-update
Former-commit-id: 55e2cbff478577b7e2fc49b91f1e58c2e1563da7
2014-04-19 10:00:06 -04:00
Jeremy Long
bbc82d827e speed up test by disabling auto-update
Former-commit-id: 709c870c42d8b67b1e02ef8669981f2726c653e1
2014-04-19 09:59:45 -04:00
Jeremy Long
742b49e302 updated test case to perform autoupdate
Former-commit-id: 3e93783a97af223a1c63cde2b8f5916158a729e9
2014-04-19 09:59:09 -04:00
Jeremy Long
8716f14941 updated settings initialization
Former-commit-id: f53733aa65df96d09a817b74fd440da133b8be08
2014-04-19 09:58:40 -04:00
Jeremy Long
8b7b41de47 removed singleton pattern from service loaders
Former-commit-id: 0e7b90141333548c47fbb4c9944b44fe295acfec
2014-04-19 09:58:16 -04:00
Jeremy Long
36fd4dbcf4 updated to initialize the settings object
Former-commit-id: 7920a16418cb0b539571058942606dfd3b142525
2014-04-19 08:59:04 -04:00
Jeremy Long
291a8c2bfb Merge branch 'master' of github.com:bkimminich/DependencyCheck into bkimminich-master
Former-commit-id: 4b8d77255bef86d4cb4243eefd80eedadf5ca8f7
2014-04-19 08:22:47 -04:00
Jeremy Long
a1db394d93 added a mechanism to copy the global settings object to forked threads
Former-commit-id: 2932ae216d79d3cd08f4fb57695f3bd979c95c59
2014-04-19 08:21:59 -04:00
Jeremy Long
0933d96954 updated to use BaseTest to initialize the Settings correctly
Former-commit-id: 473e0db1cc94efe745c1d4664d2c204731e1b931
2014-04-19 08:08:53 -04:00
Björn Kimminich
c4fcb6c88c fixed documentation of suppressionFile parameter
Former-commit-id: 937974c6952f8ba4d90ece584c46ada635da1d50
2014-04-17 11:17:17 +02:00
Björn Kimminich
2390b20e68 extracted logger as field
Former-commit-id: 3a9819dcd526191bb7156d2012c248bb7914cf29
2014-04-16 16:35:40 +02:00
Jeremy Long
a6fd0434de made the settings ThreadLocal to solve a threading issue
Former-commit-id: 052839b76cd6d914e66c79b2fe88321eef735146
2014-04-16 08:19:35 -04:00
Jeremy Long
53b36472a0 initial base test class to support the new Settings implementation
Former-commit-id: 5414eb1c0b4b4e6c9462728f3ed0be270b2c8c01
2014-04-16 08:18:40 -04:00
Jeremy Long
ccefea6b59 added additional error handling
Former-commit-id: 7853689d3273afaa348a7e16c26d3c2cf14b5c9b
2014-04-16 08:13:38 -04:00
Jeremy Long
b24c63cb49 updated to support the new Settings implementation
Former-commit-id: 2e275cd7333b0e44b46745d5f51f89f3f1687b8f
2014-04-16 08:12:36 -04:00
Jeremy Long
38f69fd7cc updated to support the new Settings implementation
Former-commit-id: e2a2b98e2742580e52750a1a1bcdbeddae3c5787
2014-04-16 08:12:16 -04:00
Jeremy Long
6a9ea3bc0f updated to support the new Settings implementation
Former-commit-id: 7382682e8fe7ab4d93c19dc35c7e1c300fd02886
2014-04-16 08:11:56 -04:00
Jeremy Long
d1b4e93f9e updated to support the new Settings implementation
Former-commit-id: 50235f22de97afc2a352f8dc7d2de9120cf73c75
2014-04-16 08:11:09 -04:00
Jeremy Long
9a6a61151d minor javadoc update
Former-commit-id: 0611618b0abde40a3f8fd5cb98c63ae5cc71c387
2014-04-16 08:10:50 -04:00
Jeremy Long
497d0f0c74 removed un-needed methods
Former-commit-id: 8276c1e9554a1c69c764103611c53ef85803a006
2014-04-16 08:10:24 -04:00
Jeremy Long
ecf1c90c22 updated to support the new Settings implementation
Former-commit-id: 8ec7546bb8437406da724d7296fea765781a9640
2014-04-16 08:09:47 -04:00
Jeremy Long
1aa13c1c8c updated to support the new Settings implementation
Former-commit-id: 3e39bbadb32b7f3d447676ce04dfb7d4a22a4478
2014-04-16 08:09:24 -04:00
Jeremy Long
251ad23a9e removed unused methods
Former-commit-id: 9b66b0a3362d6299c9c9b61ad9267f80bfe6cdc4
2014-04-16 08:08:54 -04:00
Jeremy Long
22876e5a25 removed unused methods
Former-commit-id: 70d7e89ae7f62b42eb7fe2cd8085caa270c8f381
2014-04-16 08:08:36 -04:00
Jeremy Long
12162e2aae updated to support the new Settings implementation
Former-commit-id: 572697ad9f84f341e1ac5a4f4e6036df0ed02f3a
2014-04-16 08:07:52 -04:00
Jeremy Long
2af09fb49d updated to support the new Settings implementation
Former-commit-id: 58ea4b5d184999aa7c2f67e00374a7c52fef639f
2014-04-16 08:07:32 -04:00
Jeremy Long
c58589026c updated to support the new Settings implementation
Former-commit-id: 00b11fb5e4eb3c288d4017e8974dac39e7a6f2c6
2014-04-16 08:07:09 -04:00
Jeremy Long
5b83919eb2 updated to support the new Settings implementation
Former-commit-id: d559571b5adf664155b12075c7f42644c001d4be
2014-04-16 08:06:52 -04:00
Jeremy Long
f26f02c986 removed unused methods
Former-commit-id: cb23f2dbc928c46149be608144aa79fcdcd6e815
2014-04-16 08:04:46 -04:00
Jeremy Long
c5d16a49d0 updated to support the new Settings implementation
Former-commit-id: 00ccc5ae2b0ceac9b1bffae27e25dfb55b262f08
2014-04-16 08:04:13 -04:00
Jeremy Long
260b2c3532 updated to support the new Settings implementation
Former-commit-id: 9cbc15ce470881f316a8ede89b94c7122c1381c1
2014-04-16 08:03:55 -04:00
Jeremy Long
420da8f476 updated to support the new Settings implementation
Former-commit-id: 8eccff73254d27425813dfac1646b8832fac8604
2014-04-16 08:03:36 -04:00
Jeremy Long
c2a39d3296 updated to support the new Settings implementation
Former-commit-id: b2b4137934983f3688f115f31ced54004d33d2e9
2014-04-16 08:03:15 -04:00
Jeremy Long
6cd4bf337e updated to support the new Settings implementation
Former-commit-id: a530f8ae502e47345f36c1e563c001797b223280
2014-04-16 08:02:50 -04:00
Jeremy Long
095c48a942 updated to support the new Settings implementation
Former-commit-id: e34221085daf9880ce658cd71df15f9f8b0def9d
2014-04-16 08:02:24 -04:00
Jeremy Long
e61ef1ae85 updated to support the new Settings implementation
Former-commit-id: 9715d8c76c5667d813a64c56d74a366fa83d2470
2014-04-16 08:02:05 -04:00
Jeremy Long
886b21af68 updated to support the new Settings implementation
Former-commit-id: bc891a90f8e0d234fbefcd19bc559bf828af5636
2014-04-16 08:01:45 -04:00
Jeremy Long
7bba66737f updated to support the new Settings implementation
Former-commit-id: d6e86661ae20968179c729fd21bfb07df00858a7
2014-04-16 08:01:15 -04:00
Jeremy Long
52fd2772cf updated to support the new Settings implementation
Former-commit-id: c84709a4cf38a6e55166de59b6a8b372c1f082e4
2014-04-16 08:00:55 -04:00
Jeremy Long
48043b5ec4 updated to support the new Settings implementation
Former-commit-id: 39536545c92d2c56017a4a8279704f2184b8124c
2014-04-16 08:00:10 -04:00
Jeremy Long
1f67ae82bd updated to support the new Settings implementation
Former-commit-id: 624d4c04e4fa208ef0da60245ca20ca755610c81
2014-04-16 07:59:13 -04:00
Jeremy Long
e7749c161d updated to support the new Settings implementation
Former-commit-id: dd98df72654badebf3d4b7fa24da718ff588339d
2014-04-16 07:58:50 -04:00
Jeremy Long
144f913aa9 updated to support the new Settings implementation
Former-commit-id: 3b0db7eb50c088342b7c49d23f43ba23edd5458f
2014-04-16 07:58:28 -04:00
Jeremy Long
e28b6b9f73 updated to support the new Settings implementation
Former-commit-id: dd2d8cdd1c8688482752a8f1df2fc54ef6f638c8
2014-04-16 07:57:11 -04:00
Jeremy Long
691636de7b removed unused methods
Former-commit-id: 6e0577ad17ed28f5e6e4f72fa35c10c5250343b4
2014-04-16 07:56:51 -04:00
Jeremy Long
6f2b1b8f06 updated to support the new Settings implementation
Former-commit-id: 18ba158d3b4651b424ee2d3ec02907410f7ea8ba
2014-04-16 07:56:23 -04:00
Jeremy Long
139640e768 updated to support the new Settings implementation
Former-commit-id: 4731df058a88b10661ea70addb082aced7590e80
2014-04-16 07:55:56 -04:00
Jeremy Long
ae2fa19c0e updated documentation
Former-commit-id: c374ee235b5c0e1beff55f678e02523213ef5868
2014-04-13 07:47:50 -04:00
Jeremy Long
f8867abe49 reordered operations
Former-commit-id: 1a487bcc4400d881c8dda7118318b183a68a0fe3
2014-04-13 07:45:54 -04:00
Jeremy Long
fd83e72177 Merge branch 'master' of github.com:jeremylong/DependencyCheck
Former-commit-id: 3a30dd648eef49290e9290be719fb0eb25f79764
2014-04-12 05:33:02 -04:00
Jeremy Long
1ff45c8e02 improved error handling
Former-commit-id: f5086f9ebae6dab987fedf5e87d885c243af188e
2014-04-11 06:38:13 -04:00
Steve Springett
608c338403 Added archive support for JAR, SAR, and APK file formats. Ticket #106
Former-commit-id: 19991f8b32e746d9691e48eeac15343178dd3e99
2014-04-10 23:39:52 -05:00
Jeremy Long
f23da0dd5a updated connection string to use FILE_LOCK=SERIALIZED instead of AUTO_SERVER=TRUE
Former-commit-id: 59bc2334093063d99c67bcef2c73690895ce9c72
2014-04-09 06:40:25 -04:00
Jeremy Long
8c3f887cac redirected standard error to hide expected [fatal] message from being displayed during tests
Former-commit-id: 4a5d1e47a0e613e2b8a14e14fc8cd73b1bd4519a
2014-04-09 06:34:57 -04:00
Jeremy Long
6e6f16d6ee updated report to show suppressed vulnerabilities and identifiers per issue #66
Former-commit-id: 0669a01ae3cc11bbeb36951411e95d2a7f8c5cf8
2014-04-04 06:46:31 -04:00
Jeremy Long
8a83385c7f fixed formating in support of issue #66
Former-commit-id: 3b27d6fefb6745ffe2e6169d248166a3408791c9
2014-04-04 06:46:04 -04:00
Jeremy Long
147bc797a2 updated schema to 1.2 to support changes for issue #66
Former-commit-id: fc7d7e8b8453bb8065be1d83cbc7ce3d5f47ea88
2014-04-04 06:45:35 -04:00
Jeremy Long
1735f36b82 added to simplify velocity templates
Former-commit-id: 0d9c1624b7cc81a7843ff7db4488b115405a9e74
2014-04-02 06:54:25 -04:00
Jeremy Long
a782354874 Merge branch 'master' of github.com:jeremylong/DependencyCheck
Former-commit-id: 2ff2fbf86c9ebbf7bc1aec2aaf833bdd2ef00851
2014-04-02 06:52:59 -04:00
Jeremy Long
21a709cf89 simplified velocity report generation
Former-commit-id: dc690db1eb9186f1bfbf49472f893137e7602953
2014-04-02 06:52:26 -04:00
Jeremy Long
76a0c1d96e coveritys copy paste analysis is awsome - identified a real bug that has been fixed
Former-commit-id: bccecaef9181eeb60a79873ebefc6f8ead259f71
2014-03-31 21:32:38 -04:00
Jeremy Long
1c30e555dc updated test case to ensure suppressed vulnerabilities were tracked correctly per issue #66
Former-commit-id: 657213bab4b2f0a9538fb03319ff945971765b47
2014-03-30 06:31:52 -04:00
Jeremy Long
9bdff89833 Updated to support the tracking of suppressed CPE/CVE per issue #66
Former-commit-id: 12b514a914a1b1df96e92efd78e6a7ec6b9c42bd
2014-03-30 06:26:50 -04:00
Jeremy Long
08105eee48 updated to ignore coverity directory
Former-commit-id: 9db069c9e11d8a387dd944399023cb485ac4e63b
2014-03-30 06:25:56 -04:00
Steve Springett
40e13184ca Fix to prevent rules from being cached between Jenkins builds even if suppression file is not specified.
Former-commit-id: 860fded462d768acb207ebe35464936d7f80f59c
2014-03-29 22:57:44 -05:00
Jeremy Long
b5a65c5e43 updated commons-compress version
Former-commit-id: 4aeedcf31bb2a99b73c35aa68bd1dd1876512c67
2014-03-29 08:56:04 -04:00
Jeremy Long
7eac65fec2 specifically set InputStreamReader to use UTF-8
Former-commit-id: 517159b6d919a98d83ebbf1037b5d375285f8390
2014-03-29 08:37:39 -04:00
Jeremy Long
9bc974661c updated to version 1.1.5-SNAPSHOT
Former-commit-id: 529545190847cf43edec6934ab6393583adc6e47
2014-03-29 08:37:03 -04:00
Jeremy Long
b8c41a91e1 updated to version 1.1.5-SNAPSHOT
Former-commit-id: 09c36d34a5390b22e3a870c8317e8e309083b5f2
2014-03-29 08:36:43 -04:00
Jeremy Long
3264becdc2 minor correction to unit tests
Former-commit-id: 44829f536b0940ed95750890262a1ab668c57745
2014-03-29 07:28:24 -04:00
Jeremy Long
845bf6ada1 version 1.1.4
Former-commit-id: 9d8e2cc70f7779b99e98aac396475f70980d7147
2014-03-29 06:55:03 -04:00
Jeremy Long
865ef2beb3 FindBugs corrections
Former-commit-id: 3bde1ba8aa05c0007a40be7594a6ded6675f5441
2014-03-29 05:58:56 -04:00
Jeremy Long
ace5353595 find bugs corrections
Former-commit-id: 34820edd6de652dc6f62702de332447d0ba48398
2014-03-29 05:54:53 -04:00
Jeremy Long
56a43fe17b checkstyle corrections
Former-commit-id: c49596f06b497f80dbe6b5b9656a5221312c7e3f
2014-03-29 05:34:46 -04:00
Jeremy Long
46f36dc7ab updated cli help to indicate wild cards can be used to limit scan to specific file extensions
Former-commit-id: 1369c129ee4a774ce22fda28a4e74468b578da40
2014-03-29 05:26:07 -04:00
Jeremy Long
db0ac70b71 checkstyle corrections
Former-commit-id: 2d7107de4141937a5be66c42b170130118c7d613
2014-03-29 05:23:49 -04:00
Jeremy Long
6cfcc903df updated documentation to support wild card file extensions
Former-commit-id: fb64ad0e0997dfb3dc3c607ef6d2818afd0b3606
2014-03-29 05:23:34 -04:00
Jeremy Long
2ccae9f434 added back in scan methods that were removed by mistake
Former-commit-id: c4a26c76c2668a2b635f361a55d3c840a842f6f7
2014-03-28 05:28:17 -04:00
Jeremy Long
139bf0ee35 updated delete file method
Former-commit-id: d5821f9476d9b230633eb0feac20d72f60baf337
2014-03-28 05:21:16 -04:00
Jeremy Long
1ce6e37e78 added support for wildcard extensions in scan path for issue #95
Former-commit-id: d02eaf80664e4525d9b00ba5978bec5cced0970a
2014-03-28 05:03:37 -04:00
Jeremy Long
462026e7e9 fixed bug causing analyzer to hang reading from an empty error input steam
Former-commit-id: 1b474a3376df612a13a62d8a31efb035c421afc5
2014-03-28 04:06:42 -04:00
Jeremy Long
2f180510b8 Merge branch 'master' of github.com:colezlaw/DependencyCheck into colezlaw-master
Former-commit-id: 1eb983f1cbcd44b029b912b7a87f19ee78d6233e
2014-03-28 02:40:26 -04:00
Will Stranathan
53e67dfb27 Updated waitFor semantics
Former-commit-id: 1080c4eca42029535508f2503ac0a76e853a7fcc
2014-03-27 17:34:45 -04:00
Jeremy Long
ff951130b6 added initial version of legal disclaimer - it will need to be updated
Former-commit-id: 776adc94aad64db842ce216f3f88354ffba79091
2014-03-27 15:35:59 -04:00
Will Stranathan
69ebb53a05 Squashed commit of the following:
commit 1d1a06a5ae7ea4f6e3adbf5a4b8163eba50562a3
Author: Will Stranathan <will@thestranathans.com>
Date:   Wed Mar 26 22:59:15 2014 -0400

    Updated unit tests and logging

commit bb00174e62c9657809d6e5a9cde7c7308d905593
Author: Will Stranathan <will@thestranathans.com>
Date:   Wed Mar 26 22:20:28 2014 -0400

    Updated GrokAssembly to not fail if the vendor can't be gotten

commit 27f7c9366acca8abbff9c6e9fa9ce1a1329da887
Author: Will Stranathan <will@thestranathans.com>
Date:   Wed Mar 26 22:18:33 2014 -0400

    Updated unit test to not care about version number


Former-commit-id: e700a5f81b7b0f6d6ccf392e846723e67fff591c
2014-03-26 23:02:17 -04:00
Jeremy Long
1a2a3d1945 added another test jar
Former-commit-id: c1eee9a685aed640be0d3a535f2888bf9e972990
2014-03-26 07:38:13 -04:00
Jeremy Long
c8b967ba37 updated engine to fix bug with archive analyzer prematurely deleting fiels
Former-commit-id: dd4400e3c852f2d9bf7bf3b89f54913be79d6d68
2014-03-26 07:33:52 -04:00
Jeremy Long
83b713a781 updated documentation for PR #98
Former-commit-id: 2121e1d535939646b3c7ce9b9b485c00f5b4bef8
2014-03-24 23:55:36 -04:00
Will Stranathan
c930568df7 Switched default Nexus to SSL to fix 301 issues
Former-commit-id: 231a5f20652fd83123f614881198edf675dd1105
2014-03-24 19:59:13 -04:00
Jeremy Long
95e2c6179f applied PR from Steve to close issue #96 and issue #97
Former-commit-id: d758d881a762c38b27d1a6ef1e17ebdab1efd5a7
2014-03-23 23:27:49 -04:00
Jeremy Long
dfdf690575 added configuration settings to the interfaces to support disabling of specific analyzers per issue #86
Former-commit-id: ce5fe7e4340a4df6f0a59a78acee6429a10ba01b
2014-03-23 23:08:03 -04:00
Jeremy Long
db30517516 various findbug, checkstyle, documentation fixes
Former-commit-id: 436d6de72216aa90360c96b5f2d23adbbd733e7b
2014-03-23 23:07:27 -04:00
Jeremy Long
534b2e59a0 fixed bug where the analyzers were not being closed
Former-commit-id: 50f1859e79cf11a19837a389b4edd3c563d2c7c8
2014-03-23 23:06:14 -04:00
Jeremy Long
5028216058 added enabled properties in support of issue #86
Former-commit-id: e6df3962e1e96b28fad499694b580423cd1cb7b5
2014-03-23 23:05:41 -04:00
Jeremy Long
173947fd7d updated documentation
Former-commit-id: b2036f354cc3d16db7e01bef9aad6aa494650fd2
2014-03-23 23:03:51 -04:00
Jeremy Long
9aa6ad216d updated tests to fix issues with the analyzer disabling themselves
Former-commit-id: 8286f053801efa11e10d3ea07529444a585859b8
2014-03-23 00:36:54 -04:00
Jeremy Long
b2a5963f5a added the ability to have a default value for getBoolean
Former-commit-id: 3768e635a48b42f198fd9e11a248f93cc8662aaa
2014-03-23 00:36:10 -04:00
Jeremy Long
c80fdee99b updated to allow turning off individual file type analyzers via configuration
Former-commit-id: c492d41e1b5ad0c890cb750370dff326c3d0de05
2014-03-23 00:33:00 -04:00
Jeremy Long
270db7829d fixed teest case
Former-commit-id: 7ced3ad498d077c8bed116c161744dd817250d96
2014-03-17 20:42:43 -04:00
Jeremy Long
5ff9ec9942 improved the abstract base class to support enabling/disabling each FileTypeAnalyzer
Former-commit-id: a2464c7041d292e6f3a2ec0d2b1e75f3bcfce425
2014-03-17 00:08:04 -04:00
Jeremy Long
2fc554e1d4 major revision to patch issue #86; file type analyzers will no longer initialize if no files were detected that they can process during the scan phase.
Former-commit-id: 1d9ef39d5f7898de73ac72bbb9573af763368e95
2014-03-16 22:39:44 -04:00
Jeremy Long
7a35c1638b updated initialization of the analyzers to use less looping
Former-commit-id: 517e0b87d6673c44d50ba60e4e4d50693f22ab98
2014-03-16 07:50:41 -04:00
Jeremy Long
916243468f added a vulnerability suppression analyzer test case
Former-commit-id: 415f214241e2ac6e882ea0291e6c11d991d4be8f
2014-03-16 07:05:05 -04:00
Jeremy Long
cb56bbc122 updated class name
Former-commit-id: 7cda28ba656b243a6b64d1101cd81a2868837c2c
2014-03-16 07:04:36 -04:00
Jeremy Long
d1b2d5cb27 renamed class
Former-commit-id: 216b78611cee90c521c36b2c20c9324cb5086f4f
2014-03-16 07:02:58 -04:00
Jeremy Long
884b56a4ef renamed class
Former-commit-id: f27ba73aff027de16b9f950401b4fee125cb19eb
2014-03-16 07:02:34 -04:00
Jeremy Long
eeb8d9cdf5 fixed a bug that caused the suppression file not to load
Former-commit-id: 3cc9ab64b4f9efbc51c497b82d9b63e2edd8376d
2014-03-16 07:02:10 -04:00
Jeremy Long
e8d7bbd280 updated the base class name to be more accurate
Former-commit-id: 38c9eed0e4226ce08d11f95b4e7f2a1ecca1f67c
2014-03-16 07:01:24 -04:00
Jeremy Long
277ee4c4b2 changed the logging level on the "entrance" log
Former-commit-id: 92b0b110cbcf05ca71e22fc244d1daefd5072e26
2014-03-16 07:00:44 -04:00
Jeremy Long
efa6c8135d improved manifest parsing to exclude additional entries per issue #88
Former-commit-id: 0665b1d9967324f6c07e95b593d6b199da5b5ee3
2014-03-16 04:49:09 -04:00
Jeremy Long
cbb705c367 updated so that the Filename was properely escaped in Javascript so that it shows up correctly in the report to fix issue #91
Former-commit-id: ec161508db21c0a3d1f4f6f4130e5fdc63d9b367
2014-03-16 04:13:43 -04:00
Jeremy Long
44326cd8c1 minor update to the generated report names
Former-commit-id: e072df44801e468c7a5d46e2f8eb039a8733865e
2014-03-15 07:48:19 -04:00
Jeremy Long
4592ab4bf5 updated to resolve issue #87
Former-commit-id: 03c12742bbd99b980c605d78b3d25fb1f89ab3cd
2014-03-15 07:46:29 -04:00
Jeremy Long
870849f01a minor update to the generated report names
Former-commit-id: 2319209d909b7350447c91af693f88e57e437a7e
2014-03-15 07:42:55 -04:00
Jeremy Long
a00bcc3df2 patch from davidkarlsen (PR #85) was applied to resolve issue #84
Former-commit-id: ac2f1c66913d08ae2e39293e98a3e7e5b9318b50
2014-03-12 23:40:42 -04:00
Jeremy Long
122dc5baf4 updated logo
Former-commit-id: 4ea34b9862eef2229bd1ba7c2e3868f12c336055
2014-03-11 11:59:54 -04:00
Jeremy Long
a276d2da4f version 1.1.4-SNAPSHOT
Former-commit-id: 969be860afdca6a1e86f6ef03b2218c34cb07114
2014-03-11 11:52:57 -04:00
Jeremy Long
6f04d4d43b version 1.1.3
Former-commit-id: af8a66cf2ecda07b7005d20f9de9dbe14d61e187
2014-03-11 11:49:32 -04:00
Jeremy Long
a966f263a2 created a new getTempFile() to FileUtils that does not create the file, it only generates the file name
Former-commit-id: 04e275caade0deba97b3b03cf41fa48f962c0172
2014-03-10 21:25:53 -04:00
Jeremy Long
ac5a23ef29 minor checkstyle correctionn
Former-commit-id: 72cfe98796cc4b8ba335c1cf6de293b30e111d99
2014-03-10 14:53:06 -04:00
Jeremy Long
b82804018d updated to ignore .LCKpom.xml~
Former-commit-id: f81c6f5c3fb3e8529275ce8db56bb0919aa32953
2014-03-10 11:25:40 -04:00
Jeremy Long
35b0b684df updated to delete newly created file prior to attempting to copy a new file into its location
Former-commit-id: 584dc6abeab388acf65ab3d5379616005746db6b
2014-03-10 10:36:03 -04:00
Jeremy Long
a627ca2127 minor updates for issue #58
Former-commit-id: 6f4d0edc03654c73dc6de29a47d65e6297814613
2014-03-09 12:40:42 -04:00
Jeremy Long
05a1096e25 initial version of test cases
Former-commit-id: 7fc3697e5cf1dd2730ea15c4bf7de568033ef9eb
2014-03-09 12:39:36 -04:00
Will Stranathan
9600e56344 Fixed two discrepancies in the CLI options
1) Proxy port and Properties files were both using -p. Now the
properties file uses -P.
2) Nexus Proxy was defaulting to true, even if the properties said
false, so moved the check for its setting to happen after the properties
were merged and had it default to checking the properties file and
setting it to true if the properties didn't say.


Former-commit-id: 6a4bcb9b457eea5a55e2cc74acc47d69637b7620
2014-03-08 18:58:39 -05:00
Jeremy Long
1bb0871948 updated grokassembly version in the test case
Former-commit-id: 233cf163ecf40331a3ac175e764e16bd8d044273
2014-03-08 06:36:31 -05:00
Jeremy Long
6ff50689e1 updated to resolve issue #58
Former-commit-id: 8787dadc04127169c2ae4d19ee0ac96399b63b62
2014-03-08 06:28:36 -05:00
Jeremy Long
9b025ddece corrected syntax error caused by copy paste
Former-commit-id: cd7b981f94fbc4e2f5124fc791162c1a96e2c7ce
2014-03-08 06:22:03 -05:00
Jeremy Long
12fd77f0b2 updated to correctly use the correctly configured temp directory
Former-commit-id: 1080d1ae37304188818f59fff5234d29857c64f5
2014-03-08 06:21:08 -05:00
Jeremy Long
0e60883b3d updated to correctly use the correctly configured temp directory
Former-commit-id: e470dd805e126a7b2aae56f067c8fbe4bb85613a
2014-03-08 06:20:32 -05:00
Jeremy Long
33b6bfe5be updated to correctly use the correctly configured temp directory
Former-commit-id: 048a7f7464f454810924a61110f0af18ac206c5b
2014-03-08 06:20:12 -05:00
Jeremy Long
8167146372 added validation for pathToMono argument
Former-commit-id: 5a2a58c96ee91b0d0dbf7b5a658a776da8a7141f
2014-03-08 06:19:21 -05:00
Jeremy Long
21bbedaf04 added option to download a file without using the configured proxy
Former-commit-id: 234d9ba35d11459473a2f6311ffe4fc56003a083
2014-03-08 06:18:44 -05:00
Jeremy Long
998aedde33 added the path to mono as a configurable setting
Former-commit-id: e0b0e5eed59f36060c4ad57052fe3e610ff2d637
2014-03-08 05:42:32 -05:00
Will Stranathan
25050da2c9 Merge branch 'master' of github.com:/colezlaw/DependencyCheck
Former-commit-id: c9d90f875ca9fe981d2bb294a7ed416b1e299987
2014-03-05 21:52:56 -05:00
Will Stranathan
a74cf8ec4d Updated GrokAssembly to catch a couple of possible exceptions
Former-commit-id: dfc1b67da43178d3653c35ab80fa244bbfd3e70b
2014-03-05 21:52:19 -05:00
Will Stranathan
e06f0a5d49 Updated GrokAssembly to catch a couple of possible exceptions
Former-commit-id: 52c6ae3bd8ff6acccecd9aa709dceb3c2aed6265
2014-03-04 13:18:04 -05:00
Will Stranathan
9d1ea4b551 Merge remote-tracking branch 'upstream/master'
Former-commit-id: c980e2c3cbcfbebd38bd99b62ffcca60f0153eb0
2014-03-04 13:13:01 -05:00
Jeremy Long
e0410783be updated version to 1.1.3-SNAPSHOT
Former-commit-id: b0d241a5d856244c5dac22f24d2ea135d2e4f545
2014-03-04 07:33:27 -05:00
Jeremy Long
d064337c15 corrected intellij idea link
Former-commit-id: da919f5e5b81328e35e7a91f0f16f0c07f42a1e4
2014-03-03 19:54:46 -05:00
Jeremy Long
6379bfb8b8 version 1.1.2
Former-commit-id: 876e8a1a02fdb24968779f6988652e0c11afc866
2014-03-03 08:51:17 -05:00
Jeremy Long
220539e51a minor update to formating
Former-commit-id: b3c3f53e6d227c8b08ff908380bf2af94cb64b04
2014-03-03 07:37:33 -05:00
Jeremy Long
95cd215e9e added more javadoc
Former-commit-id: 5b42bdc4fdf6670ea5316d21c02a3223a44505d4
2014-03-03 07:32:43 -05:00
Jeremy Long
88c04714f8 updated pre-flight to correctly skip the proxy if configured to do so
Former-commit-id: eca1f3b7bf24d88b4e80cda9e296e31ad8c1215b
2014-03-03 07:12:58 -05:00
Jeremy Long
6d47e32cac minor update to logging statement
Former-commit-id: 0f197a42a7bdf4eebefed860d5d03b5dd2634a1d
2014-03-03 07:05:24 -05:00
Jeremy Long
fc34b40c0a corrected spelling
Former-commit-id: 9acb6efd615f2327a8235f13bd2054797d8b52f7
2014-03-03 07:02:59 -05:00
Jeremy Long
d95fa8a893 updated logging of properties
Former-commit-id: f9e224a9c5ad0972e2f8ae0fc5850947b1e59c2f
2014-03-03 07:01:19 -05:00
Jeremy Long
b48f83ff49 updated imports
Former-commit-id: f7c013937243063b60f2b5cb7012e476b1fdcc98
2014-03-03 06:36:25 -05:00
Jeremy Long
c189b258b4 corrected long option name for nexus uses proxy argument
Former-commit-id: 4dfcd0fc4324828ff99138ca5d5903aa8e368a39
2014-03-03 05:41:55 -05:00
Jeremy Long
06fc5e71c3 updated documentation
Former-commit-id: 0380144c003adf7a2e50d32d43f3605a30b6b089
2014-03-02 19:23:04 -05:00
Jeremy Long
8093927579 minor checkstyle patch
Former-commit-id: e72e6856d19861fcfcc18e723852ca5fec2ff58a
2014-03-02 19:17:08 -05:00
Jeremy Long
d9eed4a460 updated to address issue #74
Former-commit-id: 9ebe411a6f1dae5c0ffb39399fe5b5c63b927836
2014-03-02 18:26:58 -05:00
Jeremy Long
9d609b6085 added configuration for whether or not the nexus analyzer should use the configured proxy
Former-commit-id: 99f3110346941ebc00c14ae1c00220eef76c1e9f
2014-03-02 18:16:12 -05:00
Jeremy Long
ef97f9c088 checkstyle fix
Former-commit-id: 1968682a460b5b294553f375ea191bcf6a45072b
2014-03-02 12:27:26 -05:00
Jeremy Long
bb8aa0fe6f fixed JavaDoc @link missing close curly bracket
Former-commit-id: 2ae5d38ac5e469c65e986ff0dd0292dcb8267285
2014-03-02 12:26:56 -05:00
Jeremy Long
be441d2aa5 checkstyle fix
Former-commit-id: 108f7d5e6b1ef4f59b2d009eddbcb00671576dd8
2014-03-02 12:26:17 -05:00
Jeremy Long
73e089d330 removed unused argument from runScan
Former-commit-id: 777688a5a541a9d3758294cee13f95c7b0d854e5
2014-03-02 12:25:50 -05:00
Jeremy Long
0a24fb57aa minor code formating change
Former-commit-id: 184bb0405efa2352116c7412efa07bd354df3e96
2014-03-01 16:09:14 -05:00
Jeremy Long
7f2c51f337 cleaned up code duplication
Former-commit-id: 561f5f16b22f07199450d090ebb8c56df3703739
2014-03-01 16:08:58 -05:00
Jeremy Long
537e490f0f Merge branch 'master' of github.com:colezlaw/DependencyCheck into colezlaw-master
Former-commit-id: 852aaebdb276c0974da0a76fe53e7228228a18a1
2014-03-01 15:35:57 -05:00
Will Stranathan
4340368e49 Merge remote-tracking branch 'upstream/master'
Former-commit-id: ec7e5a5f328476863cc1d92354268ccf99bc33cf
2014-03-01 15:26:53 -05:00
Jeremy Long
a85fb3a871 corrected db initialization sequence
Former-commit-id: bfea90ba44673f49b76d509688a6e4a4d6a912a0
2014-03-01 15:26:17 -05:00
Will Stranathan
05a49ff5db Fixed merge conflict
Former-commit-id: b6832bce2c905ca406d328cbf87d45f1ebb50393
2014-03-01 15:07:40 -05:00
Jeremy Long
0bec242b2e added logos
Former-commit-id: e00a53546ce2671eef59b264fc4b2e12b6f9691f
2014-03-01 14:36:51 -05:00
Jeremy Long
831624897b added powered by for cloudbees and built using intellij
Former-commit-id: c0b21530aad1dfa52e0417e67af22ac3c22f0e30
2014-03-01 14:36:33 -05:00
Jeremy Long
ca8a0e9a88 minor format change
Former-commit-id: f96c54e1fb969fc50ff27ab2a177490efdd3ab66
2014-03-01 14:35:48 -05:00
Will Stranathan
865ff7911a Merge branch 'master' of github.com:/colezlaw/DependencyCheck
Former-commit-id: 1e5c7e9d4b41a70a8139afb2d572a96fba113cd6
2014-03-01 07:24:35 -05:00
Will Stranathan
eefc6a5567 Added proper waitfor to the process. Need to add a watchdog to this
Former-commit-id: ff4b0b1f2c1254449e63eb660c1dbd31cef21c3b
2014-03-01 07:24:12 -05:00
Will Stranathan
bf3bc83fd8 Fixed JULI Logging (stupid fix imports)
Former-commit-id: d29bba7ac4ccdf648d9a945e728e9d0dbc301b6e
2014-03-01 07:24:12 -05:00
Will Stranathan
03b06eee67 Fixed logging to JULI
Former-commit-id: b8155251fa7120e33a042115f36ecac05fc7dce2
2014-03-01 07:24:12 -05:00
Will Stranathan
3bc17e7b83 Fixed JULI Logging (stupid fix imports)
Former-commit-id: 65aa4381b27717ec7bc766f37705fd63941849d1
2014-03-01 07:16:38 -05:00
Will Stranathan
458297bf56 Fixed logging to JULI
Former-commit-id: 5f5d9b29a6ba76f9193d47aa485b11cadb47bb67
2014-03-01 07:13:00 -05:00
Jeremy Long
9673b2aa7c ensured output streams are closed
Former-commit-id: c3102271cd7631bd1e38bf39b5f87ebb71da9e52
2014-03-01 06:59:48 -05:00
Jeremy Long
a55710df7b refactored closing input streams
Former-commit-id: 5cb4c326cc8030ff6b776fcc20a6d790494aee43
2014-03-01 06:56:42 -05:00
Jeremy Long
73edd3bc40 made a broad catch even broader
Former-commit-id: 2308606f9459ad25f4b81179f2d93768c5afa35d
2014-03-01 06:46:16 -05:00
Jeremy Long
f2ee243628 made a broad catch even broader
Former-commit-id: 11528d014d58a77c79b80073503352fce77ef45b
2014-03-01 06:45:57 -05:00
Jeremy Long
88b1e668ee made a broad catch even broader
Former-commit-id: 909064cae6d9bac8a9630fb9b8cca13f73353bfb
2014-03-01 06:45:32 -05:00
Jeremy Long
1c92a47d75 checkstyle fixes
Former-commit-id: 1ae545e0e16e3c49e3c6a0d6b95e89bf431c9598
2014-03-01 06:45:06 -05:00
Jeremy Long
d2a9f0583a checkstyle fixes
Former-commit-id: 81cedcd97db9bc7f1f824cdd2f496a05330b8e5f
2014-03-01 06:44:45 -05:00
Jeremy Long
2621d2e1dc checkstyle corrections and Javadoc update
Former-commit-id: 2bec74eecf56f5a758234edbbaccc146da32c835
2014-03-01 06:44:23 -05:00
Jeremy Long
1ce683a95a made a broad catch even broader
Former-commit-id: 1a8c926890702a58037457861f7172cb4916cff5
2014-03-01 06:44:01 -05:00
Jeremy Long
3d5f725004 made a broad catch even broader
Former-commit-id: 303c1ac281443fc121517a4dea88f072bab117bf
2014-03-01 06:43:42 -05:00
Jeremy Long
655bc4bee3 made a broad catch even broader
Former-commit-id: 1a553b664d41760f313245584ecec0dfd25a55c3
2014-03-01 06:43:23 -05:00
Jeremy Long
c67d372667 made a broad catch even broader
Former-commit-id: e9900933e58227f32b32b1562f17ae9bf50fe836
2014-03-01 06:43:02 -05:00
Jeremy Long
54e45dac51 checkstyle fixes
Former-commit-id: 377512fe3a5d5fcf92cd2690bff64f53f12e6d4f
2014-03-01 06:42:44 -05:00
Jeremy Long
5b0b594761 made a broad catch even broader and some minor format changes
Former-commit-id: 42c434756593c80eaa02146d2a6a1fd517d9b8e3
2014-03-01 06:42:18 -05:00
Jeremy Long
cdf6e3b456 made a broad catch even broader and checkstyle corrections
Former-commit-id: 5b6eb0775bfa5604bf27e510d75a693d5eb5dc66
2014-03-01 06:41:40 -05:00
Jeremy Long
cf46afea94 made a broad catch even broader
Former-commit-id: 3ae82930f8d25eeb59f162c44491d2f298ca3031
2014-03-01 06:41:11 -05:00
Jeremy Long
ea6cca588c made a broad catch even broader
Former-commit-id: 34ca7cd3269aca17a24e08e0db9d04ef21a17f89
2014-03-01 06:40:54 -05:00
Jeremy Long
1f9996fe62 made a broad catch even broader
Former-commit-id: 419f42bfbdab2328b6d6eb32baaa6b409ce20b82
2014-03-01 06:40:29 -05:00
Jeremy Long
e0be6c746c checkstyle fixes
Former-commit-id: 0970762bb0105e36ae089aa17013a7be78b988f3
2014-03-01 06:40:07 -05:00
Jeremy Long
2b62bf0337 made a broad catch even broader
Former-commit-id: bf8e7083115bce94128112645eac4d0883e58cbf
2014-03-01 06:39:45 -05:00
Jeremy Long
845825c0bf made a broad catch even broader
Former-commit-id: aefe84c760d9146e76ce950bdb83fd15b6772813
2014-03-01 06:39:20 -05:00
Jeremy Long
f9b09e5b61 minor update to the author JavaDoc
Former-commit-id: d4d7f5dae1a2951c0f9175c05afad4ab83afea9c
2014-03-01 05:47:26 -05:00
Jeremy Long
1403aa18eb minor formating change
Former-commit-id: 2be516fedafbdb88603bf3c041e327fe08e536db
2014-03-01 05:47:10 -05:00
Will Stranathan
ba2fff249d Added colezlaw to the developers list
Former-commit-id: 1055a7ca09579e010792777feeae0e8282635bc5
2014-02-28 13:14:54 -05:00
Jeremy Long
17447d3cdc updated deletion and logging of temporary files to resolve issue #73
Former-commit-id: 566b0629dc20e7f8fb1fa00fa8d7b3485e739815
2014-02-28 06:52:51 -05:00
Jeremy Long
3f4c1e7029 refactored the creation of the HttpUrlConnection objects to a factory
Former-commit-id: 984968995bf68ad9889bac843770a0d615d4478c
2014-02-28 06:25:08 -05:00
Jeremy Long
543bbf34c2 removed my previous "correction" for the if statement...
Former-commit-id: 70509cee3c061bfbfad927a0eb72cd32bc40ad6f
2014-02-28 06:03:26 -05:00
Jeremy Long
5394151e42 minor correction to an if statement that missed the explicit check against null
Former-commit-id: 115a691e3eb74038a1ed7f5d7fe357cb0b2b2a06
2014-02-28 05:52:49 -05:00
Will Stranathan
9349e9cd99 Fixes issue 75
Changed getConnection to public and made one which makes using the proxy optional, even if configured

Added a preflight request and proxy logic


Former-commit-id: 19fdfcf4edacacfa3724c8969c7da74a593f9a7c
2014-02-26 22:19:13 -05:00
Will Stranathan
594aa03c5a Merge remote-tracking branch 'upstream/master'
Former-commit-id: 0bd0189c8d6b432de170452118a0a6d8f0864191
2014-02-26 20:45:30 -05:00
Jeremy Long
ff1328dbdd changed log level to hide extraction of Grok Assembly from users
Former-commit-id: c2701066dc9fe268d82539a83e4b5a27e1ad0e04
2014-02-23 08:45:04 -05:00
Jeremy Long
9ba44e32fb re-wrote the retrieval of the vendor product list to use a generic pair and completely encapsulate all sql objects in CveDB
Former-commit-id: f84c88e2acc3c876228150736c71290b3467e2d2
2014-02-23 08:42:16 -05:00
Jeremy Long
245becdc8c pmd corrections - unused exceptions
Former-commit-id: 25ac03c35e7805ec5b9a77c3a3deb5c667ae32c7
2014-02-23 07:45:43 -05:00
Jeremy Long
56f77e88a8 checkstyle corrections
Former-commit-id: 54a8da5be77dc5c13ebaa275de668e746d306762
2014-02-23 07:42:56 -05:00
Jeremy Long
695e35634c updated error messages
Former-commit-id: 57b15967c6df98c13a0fd2d940ff20a9166bbaed
2014-02-22 17:43:12 -05:00
Jeremy Long
1f408dd7a7 ensured engine.cleanup() is now being called
Former-commit-id: 99afdd8d82d6dce65d8dd3ac23893070b318c082
2014-02-22 16:46:59 -05:00
Jeremy Long
303a3ac376 updated log levels when logging exceptions
Former-commit-id: 343daf8cf4176d1bb810d7ecd30d56c8cdc6bf4d
2014-02-22 15:50:20 -05:00
Jeremy Long
221537601f updated so compilation/tests work on linux
Former-commit-id: 3759e9438065138e6339aa3a56c81c08215406e4
2014-02-22 15:30:50 -05:00
Jeremy Long
f08919a829 made initialize and cleanup synchronized so we can avoid un-needed duplicate initialization/cleanup
Former-commit-id: 061d6a1a5c56806ea7c23d2599a6c6f7df1dae58
2014-02-22 09:25:52 -05:00
Jeremy Long
cfb1f8c767 re-structured the database connection factory
Former-commit-id: 5d84399dcb20a271a8e41414ca0604e8a9908727
2014-02-22 08:43:42 -05:00
Jeremy Long
39d3e447ab added the AssemblyAnalylzer to the list of analyzer services
Former-commit-id: 1099b9174450efa073d25f86d99e710b831ff954
2014-02-19 19:41:24 -05:00
Jeremy Long
bb76242632 added temporary hack to allow compilation on linux systems - H2 fails to load with AUTO_SERVER=true
Former-commit-id: b41ab9787071e97a5cff8c329716f8ff86b215c8
2014-02-18 19:38:13 -05:00
Jeremy Long
6bfb709233 fix for issue #72
Former-commit-id: 866b658eddb30ac1617d2d0d1729333a4864f753
2014-02-18 19:36:20 -05:00
Will Stranathan
ab9ec7145d Ignore the test if we can't run GrokAssembly.exe
Former-commit-id: f1241a8b701cb989c55de50fc5728306bea06ccd
2014-02-15 15:58:44 -05:00
Jeremy Long
6ec931fcd7 updates to resolve issue #71 - added configuration for cve urls to the ant task
Former-commit-id: d30b9b01f9af8392e1e8a2493a7c8951d088241f
2014-02-15 08:32:20 -05:00
Jeremy Long
ae76a7f7d4 updates to resolve issue #71 - added configuration for cve urls
Former-commit-id: 5b1ce45649cdefc92c694cea54cedd18fa30b005
2014-02-15 07:50:00 -05:00
Jeremy Long
2f20bf1bee removed old cwe data file that is not used
Former-commit-id: 9c5edd6f16d1d2b0a2af4ec23ecf7f1c0729c45a
2014-02-14 22:21:28 -05:00
Jeremy Long
f9d01d2fad updated test case to build serialized hashmap for CWE version 2.5 for issue #68
Former-commit-id: 9246126c1915e65862fddf2fe57a1cf58a2d8401
2014-02-14 22:15:13 -05:00
Jeremy Long
1eb1329f68 updated to CWE version 2.5 to close issue #68
Former-commit-id: dcc564320e283425f70f67830047d73cf8099fe4
2014-02-14 22:14:33 -05:00
Jeremy Long
51a3e60913 removed unused property
Former-commit-id: 2a808617fae27e023b322604d3364bde29274a01
2014-02-14 22:09:34 -05:00
Jeremy Long
30c88a2fe7 added additional logging to try and solve issue #49
Former-commit-id: 5a4e804aa461b3d2603a70ee4aa79b236306d3cc
2014-02-14 08:20:26 -05:00
Jeremy Long
4ffd336c72 Merge branch 'master' of github.com:hgomez/DependencyCheck into hgomez-master
Former-commit-id: 031bd2f2e7c9ff211245654fc594fdb1b8630d9f
2014-02-14 08:05:33 -05:00
Jeremy Long
7cbc047b41 commented out unused properties
Former-commit-id: 80ef6ece02e7e8ed74a34ecb6a580c339ad69431
2014-02-14 08:02:50 -05:00
Henri Gomez
adf4222b24 tipo
Former-commit-id: 61cfcee87376f7fe1a1cb1bebc5a0fed875745b4
2014-02-14 12:16:17 +01:00
Henri Gomez
c095118e98 Skipped Scope parametized
Former-commit-id: 7a0807b77afef6a3db24af30ca98b770b44bea04
2014-02-14 12:14:06 +01:00
Jeremy Long
11d7d25037 patch for issue #34 - hibernate3.jar no longer reports cpe:/a:jboss:jboss
Former-commit-id: e67337af94b3b83cae112f10beed5020540c6440
2014-02-13 20:51:54 -05:00
Jeremy Long
c45ff40250 added hibernate3.jar to test resources to test and fix issue #34
Former-commit-id: c88585d08a3ff93057a81ea15720d6cd88a0d047
2014-02-13 20:31:09 -05:00
Jeremy Long
2f8c2b05bd fixes for issue #63 and issue #65
Former-commit-id: 6b5f22ffe706cf8aafa36fc8a118e7119c7f0cdf
2014-02-13 20:20:19 -05:00
Jeremy Long
a4c17bb308 Merge branch 'master' of github.com:hgomez/DependencyCheck into hgomez-master
Former-commit-id: 7ce63ad527be7a6270cf877d87c5ad56fe2abb1b
2014-02-13 06:08:33 -05:00
Jeremy Long
75eff7f083 updated getParentLogger to compile under 1.6 for issue #62
Former-commit-id: 67a48a7f1e48bd922ee772bf7e407c2f8b3ed7e1
2014-02-11 09:18:41 -05:00
Henri Gomez
a5b9a707a4 Add support for extra extensions provided externally
Former-commit-id: 6c8632566de0a46ff4ce24ef5285bbd84c8ef89f
2014-02-11 14:05:26 +01:00
Henri Gomez
1b013db312 No need to redefined Test Scope String
Former-commit-id: 1da78b9b9994d055b38f1f5aeebb6fb67a1fb756
2014-02-11 12:54:26 +01:00
Henri Gomez
158250e98d Artifact with scope Provided and Runtime should be excluded too
Former-commit-id: 53e086b5bf02eee8cb4c4f3703a61923608c13dd
2014-02-11 12:51:59 +01:00
jeremylong
f9f4be181d corrected link for issue #59
Former-commit-id: 8b45674adfa218b82738cf910a7ebe03054c1be6
2014-02-10 19:53:17 -05:00
Jeremy Long
3bea99c000 added dependencies to a testAll profile for issue #34
Former-commit-id: 9cc56005bcb3e33a364a3929d1f361bd45b03662
2014-02-08 23:54:11 -05:00
Jeremy Long
05e52ca236 updated how the description is processsed from the manifest to fix issue #34 for wss4j-1.5.7.jar
Former-commit-id: 2a9d9fc46b0437778383cdb4f1c34c04ef746c20
2014-02-08 23:53:47 -05:00
Jeremy Long
f268a48a16 added build-id to specific items in the manifest to patch dependencies like batli-util.jar in issue #34
Former-commit-id: 0a6727676c5fa63a32fa7d4be18859ca622bad24
2014-02-08 22:37:11 -05:00
Jeremy Long
96bb9a2f8e applied patch for m-core CPE per issue #34 - xstreamcore
Former-commit-id: 9f683ade5473688c106d7bc82e464635a900277e
2014-02-08 22:35:24 -05:00
Jeremy Long
f9b977d266 noop
Former-commit-id: c522f08c16c28265c96b846f58461aa83fe82ed1
2014-02-08 22:05:08 -05:00
Jeremy Long
7fca2a9cc6 removed analysisExceptions from the dependency object, instead we are logging the exception for issue #46
Former-commit-id: feee45a009165fce559d3bad2e9c45f95f230200
2014-02-08 12:35:53 -05:00
Jeremy Long
e473ef36b1 removed analysisExceptions for issue #46
Former-commit-id: d18690baa5de2ad38a46936e5d3e64681b2ccc29
2014-02-08 12:24:25 -05:00
Jeremy Long
3b5b832bbc update to make failure more verbose for issue #57
Former-commit-id: 7315afe74cc78c65254e5f12032ece0a461be751
2014-02-08 12:09:58 -05:00
Jeremy Long
4cfb451755 updated cobertura version and configuration
Former-commit-id: edd13a1df620a51e1c72a232310d72b90580e81c
2014-02-08 11:57:52 -05:00
Jeremy Long
368d1ad354 moved exceptions to their own package to avoid clutter in the org.owasp.dependencycheck.analyzer package
Former-commit-id: 26bba207b470459d4ca238145592c2b4e776684a
2014-02-02 07:13:53 -05:00
Will Stranathan
9a8f7ccba8 Refactored the test run of GrokAssembly to avoid double-closing
Former-commit-id: edc5ae7da2cb52900f9eed1cd133c843f161a9aa
2014-02-01 09:33:47 -05:00
Jeremy Long
032c8e9fac Changed from using the ConditionalIgnoreRule to using junit's core assumeFalse
Former-commit-id: fa9e77a19adeda13aa30c48c3ffa903ec50ed762
2014-02-01 09:11:52 -05:00
Jeremy Long
20d1abd2e1 updated test case using an invalid mono path so that it does not run on Windows
Former-commit-id: 4a26ca21e64614bf74cb329d8d9b424442e7647c
2014-02-01 08:49:00 -05:00
Jeremy Long
73903cbd1f added conditional ignore for JUnit tests
Former-commit-id: ed8a216bc31a7ac8f69b08d34a0ffc356f1cd912
2014-02-01 08:48:14 -05:00
Jeremy Long
bff22a4e4e explicitly closed the FileOutputStream after writting the assembly
Former-commit-id: 70d6fbcd06acad1cb950c7dff8829891cd5c4721
2014-02-01 08:20:24 -05:00
Jeremy Long
daaaed4118 Merge branch 'grokassembly-work' of https://github.com/colezlaw/DependencyCheck
Former-commit-id: bfee1c77cc20c2fdd34a20a12696ad8009a86cd0
2014-02-01 08:10:22 -05:00
Will Stranathan
c2c9db66e2 Fixed merge conflicts
Former-commit-id: 64182608dd121fd22aded543552d857009cf7af9
2014-01-31 21:52:08 -05:00
Will Stranathan
09308083a9 Adding the AssemblyAnalyzer to analyze .NET assemblies
Changed the author on a few files

Added GrokAssembly.exe for grokking assemblies

First revision of the assembly analyzer

Added ability to configure where mono is located


Former-commit-id: c0fa65ecb227f23c8432a5950403483be8b5de25
2014-01-31 21:44:28 -05:00
Jeremy Long
cf492355b4 updated to use markdown syntax rather then HTML (fixing vm/md interaction)
Former-commit-id: bde9d01fb7a656bd115ec23994bc474c82bfcf74
2014-01-31 06:15:37 -05:00
Jeremy Long
1cd1b1cb08 updated version to 1.1.2-SNAPSHOT
Former-commit-id: 0ee7b4a66d817b5e78e6838ddd0c66527146a684
2014-01-31 05:38:29 -05:00
Jeremy Long
91a137ab95 version 1.1.1
Former-commit-id: bde142783532d8d46b468e644f3af8ecc42c40d3
2014-01-30 06:23:34 -05:00
Jeremy Long
efd4b8ec11 test cases for javascript analyzer
Former-commit-id: 1660584330a7cfc79a1b9aa99a3bc727e7dba231
2014-01-29 20:07:48 -05:00
Jeremy Long
9803c75fbd removed test case for issue #51 - need more information as I cannot get the exception to be thrown
Former-commit-id: 03b40b0b3e83ff008f562894851242f062a49161
2014-01-29 06:14:30 -05:00
Jeremy Long
509bbc7743 disabled nexus analyzer for ArchiveAnalyzer tests
Former-commit-id: 0966a39d20f8aabe1c64d970affe1cf2ce92794e
2014-01-29 05:58:19 -05:00
Jeremy Long
f7a2428ba9 updated compareTo test to use cpe:/a:yahoo:toolbar:3.1.0.20130813024103 to test the fix for issue #53
Former-commit-id: 38775e8c129e8ecd7f603ae7d86d0583b4b5fe77
2014-01-29 05:55:28 -05:00
Jeremy Long
c79a9f2ce3 Converted integer.compareTo to long.compareTo and added a fall back of string compareTo to fix issue #53
Former-commit-id: 91d7ae202006dbebf21e6cdfadbfa7995ace08ca
2014-01-29 05:45:53 -05:00
Jeremy Long
685569e131 patched issue #52 - corrected the @parameter for the connectionString field
Former-commit-id: b725fc34543d4c540f337cfcf34e4a98656be9ad
2014-01-28 19:48:35 -05:00
Will Stranathan
ca44e3062e First revision of the assembly analyzer
Former-commit-id: ebe1edf714da079f80af33ed257e37b2750304fd
2014-01-28 19:23:13 -05:00
Will Stranathan
3d919f1836 Added GrokAssembly.exe for grokking assemblies
Former-commit-id: 3886ba720b7ed3d090f3d58fa372be7d2a7aee52
2014-01-28 19:21:54 -05:00
Will Stranathan
f4fa2150b5 Changed the author on a few files
Former-commit-id: 67923ceb8b5419eaccfbc33a9b34bf92f0916c00
2014-01-28 17:10:48 -05:00
Jeremy Long
0e28c8e0d5 test data for JavaScript Analyzer
Former-commit-id: 16067187a5347cdee260b4137a40480eae5b04d6
2014-01-28 05:25:54 -05:00
Jeremy Long
cb25fc03f9 added getActualFile() to return a file reference
Former-commit-id: 0c04828262c08a962766240275afb340293bd0dd
2014-01-28 05:24:54 -05:00
Jeremy Long
7a64b84c5f Merge branch 'nuspec' of https://github.com/colezlaw/DependencyCheck into colezlaw-nuspec
Former-commit-id: e6405eaa708463b1182917ac46cff99a4e369034
2014-01-27 06:12:15 -05:00
Jeremy Long
1cac8a857d Merge branch 'master' of github.com:jeremylong/DependencyCheck
Former-commit-id: 181804ca53fa09f7eebefe28be71d3163d4cda4c
2014-01-27 06:11:14 -05:00
Jeremy Long
f6e02aec2a updated version to 1.1.1-SNAPSHOT
Former-commit-id: 5945cef222dceb28d8a94939178e33994ef344b4
2014-01-27 06:10:04 -05:00
Will Stranathan
78f7152f6c Converted to XPath instead of SAX
Former-commit-id: e6062e1b9497a7134b6923f7f85e1fe3f18cefcc
2014-01-26 22:11:11 -05:00
Steve Springett
1f4746c90a Update index.md
Former-commit-id: 19311fc6b0ca9e4fc1f287a221fd9d5472f06010
2014-01-26 16:04:50 -06:00
Steve Springett
c5f95e79d6 Update index.md
Former-commit-id: 7562696a0d4451fccf833b7a12cb4acd0c0acd9a
2014-01-26 16:04:26 -06:00
Steve Springett
bd4cbc54fb Update README.md
Synched file with version on jenkins-ci

Former-commit-id: 798c1812cfa62bc7905e70638e3826effbea2069
2014-01-26 16:03:11 -06:00
Will Stranathan
17e3e51607 Updated javadocs
Former-commit-id: 9c054f0396b8b1431cc87759b0e43e13d1b14086
2014-01-25 11:27:28 -05:00
Will Stranathan
b9f5799c1b Added the NuspecAnalyzer to the list of analyzers
Former-commit-id: 7472ceb2fefef23c0b6aad112f4e4e7e04ce93e5
2014-01-24 07:11:18 -05:00
Will Stranathan
8b6e9b7f76 Initial checkin of an analyzer which gets info from .nuspec files
Former-commit-id: 7d14609e887829f67a23dd51412761b1691bc135
2014-01-24 07:10:53 -05:00
Will Stranathan
4a02c87c27 Added nupkg to the list of supported ZIP-like extensions
Former-commit-id: a70f09ba9cadec56034a178d76692276f7946255
2014-01-24 07:09:45 -05:00
163 changed files with 18853 additions and 179524 deletions

6
.gitignore vendored
View File

@@ -15,4 +15,8 @@ dependency-reduced-pom.xml
#ruby Gemfile, etc. This is a java project, Gemfile is here to check site problem with Jekyll
Gemfile
Gemfile.lock
_site/**
_site/**
#unknown as to why these are showing up... but need to be ignored.
.LCKpom.xml~
#coverity
/cov-int/

View File

@@ -29,7 +29,7 @@ On Windows
### Maven Plugin
More detailed instructions can be found on the [dependency-check-maven github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-maven/installation.html).
More detailed instructions can be found on the [dependency-check-maven github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-maven/usage.html).
The plugin can be configured using the following:
```xml

View File

@@ -1,9 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Puppy Crawl//DTD Suppressions 1.0//EN"
"http://www.puppycrawl.com/dtds/suppressions_1_0.dtd">
<suppressions>
<suppress checks=".*" files=".*[\\/]package-info\.java" />
</suppressions>

View File

@@ -21,7 +21,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.1.0</version>
<version>1.2.0</version>
</parent>
<artifactId>dependency-check-ant</artifactId>
@@ -237,8 +237,11 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.5.2</version>
<version>2.6</version>
<configuration>
<instrumentation>
<ignoreTrivial>true</ignoreTrivial>
</instrumentation>
<check>
<branchRate>85</branchRate>
<lineRate>85</lineRate>
@@ -270,11 +273,6 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<version>2.16</version>
<configuration>
<systemProperties>
<property>
<name>net.sourceforge.cobertura.datafile</name>
<value>${project.build.directory}/cobertura/cobertura.ser</value>
<workingDirectory>target</workingDirectory>
</property>
<property>
<name>data.directory</name>
<value>${project.build.directory}/dependency-check-data</value>
@@ -356,7 +354,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.5.2</version>
<version>2.6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -400,9 +398,9 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<version>2.11</version>
<configuration>
<enableRulesSummary>false</enableRulesSummary>
<configLocation>${basedir}/config/checkstyle-checks.xml</configLocation>
<headerLocation>${basedir}/config/checkstyle-header.txt</headerLocation>
<suppressionsLocation>${basedir}/config/checkstyle-suppressions.xml</suppressionsLocation>
<configLocation>${basedir}/../src/main/config/checkstyle-checks.xml</configLocation>
<headerLocation>${basedir}/../src/main/config/checkstyle-header.txt</headerLocation>
<suppressionsLocation>${basedir}/../src/main/config/checkstyle-suppressions.xml</suppressionsLocation>
<suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
</configuration>
</plugin>
@@ -414,6 +412,15 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<targetJdk>1.6</targetJdk>
<linkXref>true</linkXref>
<sourceEncoding>utf-8</sourceEncoding>
<excludes>
<exclude>**/generated/*.java</exclude>
</excludes>
<rulesets>
<ruleset>../src/main/config/dcrules.xml</ruleset>
<ruleset>/rulesets/java/basic.xml</ruleset>
<ruleset>/rulesets/java/imports.xml</ruleset>
<ruleset>/rulesets/java/unusedcode.xml</ruleset>
</rulesets>
</configuration>
</plugin>
<plugin>

View File

@@ -62,6 +62,10 @@ public class DependencyCheckTask extends Task {
* System specific new line character.
*/
private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(DependencyCheckTask.class.getName());
/**
* Construct a new DependencyCheckTask.
@@ -457,6 +461,81 @@ public class DependencyCheckTask extends Task {
this.showSummary = showSummary;
}
/**
* Sets whether or not the analyzer is enabled.
*
* @param jarAnalyzerEnabled the value of the new setting
*/
public void setJarAnalyzerEnabled(boolean jarAnalyzerEnabled) {
this.jarAnalyzerEnabled = jarAnalyzerEnabled;
}
/**
* Whether or not the Archive Analyzer is enabled.
*/
private boolean archiveAnalyzerEnabled = true;
/**
* Returns whether or not the analyzer is enabled.
*
* @return true if the analyzer is enabled
*/
public boolean isArchiveAnalyzerEnabled() {
return archiveAnalyzerEnabled;
}
/**
* Whether or not the .NET Assembly Analyzer is enabled.
*/
private boolean assemblyAnalyzerEnabled = true;
/**
* Sets whether or not the analyzer is enabled.
*
* @param archiveAnalyzerEnabled the value of the new setting
*/
public void setArchiveAnalyzerEnabled(boolean archiveAnalyzerEnabled) {
this.archiveAnalyzerEnabled = archiveAnalyzerEnabled;
}
/**
* Returns whether or not the analyzer is enabled.
*
* @return true if the analyzer is enabled
*/
public boolean isAssemblyAnalyzerEnabled() {
return assemblyAnalyzerEnabled;
}
/**
* Sets whether or not the analyzer is enabled.
*
* @param assemblyAnalyzerEnabled the value of the new setting
*/
public void setAssemblyAnalyzerEnabled(boolean assemblyAnalyzerEnabled) {
this.assemblyAnalyzerEnabled = assemblyAnalyzerEnabled;
}
/**
* Whether or not the .NET Nuspec Analyzer is enabled.
*/
private boolean nuspecAnalyzerEnabled = true;
/**
* Returns whether or not the analyzer is enabled.
*
* @return true if the analyzer is enabled
*/
public boolean isNuspecAnalyzerEnabled() {
return nuspecAnalyzerEnabled;
}
/**
* Sets whether or not the analyzer is enabled.
*
* @param nuspecAnalyzerEnabled the value of the new setting
*/
public void setNuspecAnalyzerEnabled(boolean nuspecAnalyzerEnabled) {
this.nuspecAnalyzerEnabled = nuspecAnalyzerEnabled;
}
/**
* Whether or not the nexus analyzer is enabled.
*/
@@ -502,6 +581,28 @@ public class DependencyCheckTask extends Task {
public void setNexusUrl(String nexusUrl) {
this.nexusUrl = nexusUrl;
}
/**
* Whether or not the defined proxy should be used when connecting to Nexus.
*/
private boolean nexusUsesProxy = true;
/**
* Get the value of nexusUsesProxy.
*
* @return the value of nexusUsesProxy
*/
public boolean isNexusUsesProxy() {
return nexusUsesProxy;
}
/**
* Set the value of nexusUsesProxy.
*
* @param nexusUsesProxy new value of nexusUsesProxy
*/
public void setNexusUsesProxy(boolean nexusUsesProxy) {
this.nexusUsesProxy = nexusUsesProxy;
}
/**
* The database driver name; such as org.h2.Driver.
@@ -616,6 +717,144 @@ public class DependencyCheckTask extends Task {
this.databasePassword = databasePassword;
}
/**
* Additional ZIP File extensions to add analyze. This should be a comma-separated list of file extensions to treat
* like ZIP files.
*/
private String zipExtensions;
/**
* Get the value of zipExtensions.
*
* @return the value of zipExtensions
*/
public String getZipExtensions() {
return zipExtensions;
}
/**
* Set the value of zipExtensions.
*
* @param zipExtensions new value of zipExtensions
*/
public void setZipExtensions(String zipExtensions) {
this.zipExtensions = zipExtensions;
}
/**
* The url for the modified NVD CVE (1.2 schema).
*/
private String cveUrl12Modified;
/**
* Get the value of cveUrl12Modified.
*
* @return the value of cveUrl12Modified
*/
public String getCveUrl12Modified() {
return cveUrl12Modified;
}
/**
* Set the value of cveUrl12Modified.
*
* @param cveUrl12Modified new value of cveUrl12Modified
*/
public void setCveUrl12Modified(String cveUrl12Modified) {
this.cveUrl12Modified = cveUrl12Modified;
}
/**
* The url for the modified NVD CVE (2.0 schema).
*/
private String cveUrl20Modified;
/**
* Get the value of cveUrl20Modified.
*
* @return the value of cveUrl20Modified
*/
public String getCveUrl20Modified() {
return cveUrl20Modified;
}
/**
* Set the value of cveUrl20Modified.
*
* @param cveUrl20Modified new value of cveUrl20Modified
*/
public void setCveUrl20Modified(String cveUrl20Modified) {
this.cveUrl20Modified = cveUrl20Modified;
}
/**
* Base Data Mirror URL for CVE 1.2.
*/
private String cveUrl12Base;
/**
* Get the value of cveUrl12Base.
*
* @return the value of cveUrl12Base
*/
public String getCveUrl12Base() {
return cveUrl12Base;
}
/**
* Set the value of cveUrl12Base.
*
* @param cveUrl12Base new value of cveUrl12Base
*/
public void setCveUrl12Base(String cveUrl12Base) {
this.cveUrl12Base = cveUrl12Base;
}
/**
* Data Mirror URL for CVE 2.0.
*/
private String cveUrl20Base;
/**
* Get the value of cveUrl20Base.
*
* @return the value of cveUrl20Base
*/
public String getCveUrl20Base() {
return cveUrl20Base;
}
/**
* Set the value of cveUrl20Base.
*
* @param cveUrl20Base new value of cveUrl20Base
*/
public void setCveUrl20Base(String cveUrl20Base) {
this.cveUrl20Base = cveUrl20Base;
}
/**
* The path to Mono for .NET assembly analysis on non-windows systems.
*/
private String pathToMono;
/**
* Get the value of pathToMono.
*
* @return the value of pathToMono
*/
public String getPathToMono() {
return pathToMono;
}
/**
* Set the value of pathToMono.
*
* @param pathToMono new value of pathToMono
*/
public void setPathToMono(String pathToMono) {
this.pathToMono = pathToMono;
}
@Override
public void execute() throws BuildException {
final InputStream in = DependencyCheckTask.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
@@ -625,46 +864,58 @@ public class DependencyCheckTask extends Task {
validateConfiguration();
populateSettings();
final Engine engine = new Engine();
for (Resource resource : path) {
final FileProvider provider = resource.as(FileProvider.class);
if (provider != null) {
final File file = provider.getFile();
if (file != null && file.exists()) {
engine.scan(file);
}
}
}
Engine engine = null;
try {
engine.analyzeDependencies();
DatabaseProperties prop = null;
CveDB cve = null;
try {
cve = new CveDB();
cve.open();
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex);
} finally {
if (cve != null) {
cve.close();
engine = new Engine();
for (Resource resource : path) {
final FileProvider provider = resource.as(FileProvider.class);
if (provider != null) {
final File file = provider.getFile();
if (file != null && file.exists()) {
engine.scan(file);
}
}
}
final ReportGenerator reporter = new ReportGenerator(applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
reporter.generateReports(reportOutputDirectory, reportFormat);
try {
engine.analyzeDependencies();
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 reporter = new ReportGenerator(applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
reporter.generateReports(reportOutputDirectory, reportFormat);
if (this.failBuildOnCVSS <= 10) {
checkForFailure(engine.getDependencies());
if (this.failBuildOnCVSS <= 10) {
checkForFailure(engine.getDependencies());
}
if (this.showSummary) {
showSummary(engine.getDependencies());
}
} catch (IOException ex) {
LOGGER.log(Level.FINE, "Unable to generate dependency-check report", ex);
throw new BuildException("Unable to generate dependency-check report", ex);
} catch (Exception ex) {
LOGGER.log(Level.FINE, "An exception occurred; unable to continue task", ex);
throw new BuildException("An exception occurred; unable to continue task", ex);
}
if (this.showSummary) {
showSummary(engine.getDependencies());
} catch (DatabaseException ex) {
LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
LOGGER.log(Level.FINE, "", ex);
} finally {
Settings.cleanup();
if (engine != null) {
engine.cleanup();
}
} catch (IOException ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "Unable to generate dependency-check report", ex);
throw new BuildException("Unable to generate dependency-check report", ex);
} catch (Exception ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "An exception occurred; unable to continue task", ex);
throw new BuildException("An exception occurred; unable to continue task", ex);
}
}
@@ -687,19 +938,20 @@ public class DependencyCheckTask extends Task {
* properties required to change the proxy url, port, and connection timeout.
*/
private void populateSettings() {
Settings.initialize();
InputStream taskProperties = null;
try {
taskProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
Settings.mergeProperties(taskProperties);
} catch (IOException ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.WARNING, "Unable to load the dependency-check ant task.properties file.");
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, "Unable to load the dependency-check ant task.properties file.");
LOGGER.log(Level.FINE, null, ex);
} finally {
if (taskProperties != null) {
try {
taskProperties.close();
} catch (IOException ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}
@@ -733,10 +985,29 @@ public class DependencyCheckTask extends Task {
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_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);
}
if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
}
@@ -752,6 +1023,18 @@ public class DependencyCheckTask extends Task {
if (databasePassword != null && !databasePassword.isEmpty()) {
Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
}
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);
}
}
/**
@@ -818,7 +1101,7 @@ public class DependencyCheckTask extends Task {
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.getLogger(DependencyCheckTask.class.getName()).log(Level.WARNING, msg);
LOGGER.log(Level.WARNING, msg);
}
}
@@ -843,4 +1126,18 @@ public class DependencyCheckTask extends Task {
return values;
}
}
/**
* Whether or not the Jar Analyzer is enabled.
*/
private boolean jarAnalyzerEnabled = true;
/**
* Returns whether or not the analyzer is enabled.
*
* @return true if the analyzer is enabled
*/
public boolean isJarAnalyzerEnabled() {
return jarAnalyzerEnabled;
}
}

View File

@@ -18,29 +18,60 @@ the project's dependencies.
</dependency-check>
</target>
```
The following table lists the configurable properties:
Property | Description | Requirement
----------------------|-------------|---------
ApplicationName | The name of the application to use in the generated report. | Required
ReportFormat | The format of the report to be generated. Allowed values are: HTML, XML, VULN, or ALL. The default value is HTML.| Optional
ReportOutputDirectory | The directory where dependency-check will store data used for analysis. Defaults to the current working directory. | Optional
FailBuildOn | If set and a CVE is found that is greater then the specified value the build will fail. The default value is 11 which means that the build will not fail. Valid values are 0-11. | Optional
AutoUpdate | If set to false the NVD CVE data is not automatically updated. Setting this to false could result in false negatives. However, this may be required in some environments. The default value is true. | Optional
DataDirectory | The directory where dependency-check will store data used for analysis. Defaults to a folder called, called 'dependency-check-data', that is in the same directory as the dependency-check-ant jar file was installed in. *It is not recommended to change this.* | Optional
LogFile | The file path to write verbose logging information. | Optional
SuppressionFile | An XML file conforming to the suppression schema that suppresses findings; this is used to hide [false positives](../suppression.html). | Optional
ProxyUrl | Defines the proxy used to connect to the Internet. | Optional
ProxyPort | Defines the port for the proxy. | Optional
ProxyUsername | Defines the proxy user name. | Optional
ProxyPassword | Defines the proxy password. | Optional
ConnectionTimeout | The connection timeout used when downloading data files from the Internet. | Optional
nexusAnalyzerEnabled | The connection timeout used when downloading data files from the Internet. | Optional
nexusUrl | The connection timeout used when downloading data files from the Internet. | Optional
databaseDriverName | The name of the database driver. Example: org.h2.Driver. | Optional
databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. | Optional
connectionString | The connection string used to connect to the database. | Optional
databaseUser | The username used when connecting to the database. | Optional
databasePassword | The password used when connecting to the database. | Optional
Configuration
====================
The following properties can be set on the dependency-check-maven plugin.
Property | Description | Default Value
---------------------|------------------------------------|------------------
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'
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
logFile | The file path to write verbose logging information. | &nbsp;
suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../suppression.html) | &nbsp;
proxyUrl | The Proxy URL. | &nbsp;
proxyPort | The Proxy Port. | &nbsp;
proxyUsername | Defines the proxy user name. | &nbsp;
proxyPassword | Defines the proxy password. | &nbsp;
connectionTimeout | The URL Connection Timeout. | &nbsp;
Analyzer Configuration
====================
The following properties are used to configure the various file type analyzers.
These properties can be used to turn off specific analyzers if it is not needed.
Note, that specific analyzers will automatically disable themselves if no file
types that they support are detected - so specifically disabling them may not
be needed.
Property | Description | Default Value
------------------------|------------------------------------|------------------
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. | &nbsp;
jarAnalyzer | Sets whether Jar Analyzer will be used. | true
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. | true
nexusUrl | Defines the Nexus URL. | https://repository.sonatype.org/service/local/
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
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 | &nbsp;
Advanced Configuration
====================
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.
Property | Description | Default Value
---------------------|-------------------------------------------------------------------------|------------------
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
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
dataDirectory | Data directory to hold SQL CVEs contents. This should generally not be changed. | &nbsp;
databaseDriverName | The name of the database driver. Example: org.h2.Driver. | &nbsp;
databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. | &nbsp;
connectionString | The connection string used to connect to the database. | &nbsp;
databaseUser | The username used when connecting to the database. | &nbsp;
databasePassword | The password used when connecting to the database. | &nbsp;

View File

@@ -18,14 +18,12 @@
package org.owasp.dependencycheck.taskdefs;
import java.io.File;
import static junit.framework.TestCase.assertTrue;
import org.apache.tools.ant.BuildFileTest;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase;
import org.owasp.dependencycheck.utils.Settings;
/**
*
@@ -33,20 +31,10 @@ import org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase;
*/
public class DependencyCheckTaskTest extends BuildFileTest {
public DependencyCheckTaskTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
@Override
public void setUp() throws Exception {
Settings.initialize();
BaseDBTestCase.ensureDBExists();
final String buildFile = this.getClass().getClassLoader().getResource("build.xml").getPath();
configureProject(buildFile);
@@ -57,6 +45,7 @@ public class DependencyCheckTaskTest extends BuildFileTest {
public void tearDown() {
//no cleanup...
//executeTarget("cleanup");
Settings.cleanup();
}
/**
@@ -64,7 +53,7 @@ public class DependencyCheckTaskTest extends BuildFileTest {
*/
@Test
public void testAddFileSet() throws Exception {
File report = new File("target/DependencyCheck-Report.html");
File report = new File("target/dependency-check-report.html");
if (report.exists()) {
if (!report.delete()) {
throw new Exception("Unable to delete 'target/DependencyCheck-Report.html' prior to test.");
@@ -83,7 +72,7 @@ public class DependencyCheckTaskTest extends BuildFileTest {
*/
@Test
public void testAddFileList() throws Exception {
File report = new File("target/DependencyCheck-Report.xml");
File report = new File("target/dependency-check-report.xml");
if (report.exists()) {
if (!report.delete()) {
throw new Exception("Unable to delete 'target/DependencyCheck-Report.xml' prior to test.");
@@ -101,7 +90,7 @@ public class DependencyCheckTaskTest extends BuildFileTest {
*/
@Test
public void testAddDirSet() throws Exception {
File report = new File("target/DependencyCheck-Vulnerability.html");
File report = new File("target/dependency-check-vulnerability.html");
if (report.exists()) {
if (!report.delete()) {
throw new Exception("Unable to delete 'target/DependencyCheck-Vulnerability.html' prior to test.");

View File

@@ -1,223 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker">
<!--
If you set the basedir property below, then all reported file
names will be relative to the specified directory. See
http://checkstyle.sourceforge.net/5.x/config.html#Checker
<property name="basedir" value="${basedir}"/>
-->
<property name="severity" value="error"/>
<module name="SuppressionFilter">
<property name="file" value="${checkstyle.suppressions.file}"/>
</module>
<module name="JavadocPackage">
<property name="allowLegacy" value="false"/>
</module>
<module name="Translation">
<property name="severity" value="warning"/>
</module>
<module name="FileTabCharacter">
<property name="eachLine" value="false"/>
</module>
<module name="FileLength">
<property name="fileExtensions" value="java"/>
</module>
<module name="NewlineAtEndOfFile">
<property name="fileExtensions" value="java"/>
<property name="lineSeparator" value="lf"/>
</module>
<module name="RegexpHeader">
<property name="headerFile" value="${checkstyle.header.file}"/>
<property name="fileExtensions" value="java"/>
<property name="id" value="header"/>
</module>
<module name="RegexpSingleline">
<property name="format" value="\s+$"/>
<property name="minimum" value="0"/>
<property name="maximum" value="0"/>
</module>
<module name="TreeWalker">
<property name="tabWidth" value="4"/>
<module name="AvoidStarImport"/>
<module name="ConstantName"/>
<module name="EmptyBlock"/>
<module name="EmptyForIteratorPad"/>
<module name="EqualsHashCode"/>
<module name="OneStatementPerLine"/>
<!-- module name="IllegalCatch"/ -->
<!--module name="ImportControl">
<property name="file" value="${checkstyle.importcontrol.file}"/>
</module-->
<module name="IllegalImport"/>
<module name="IllegalInstantiation"/>
<module name="IllegalThrows"/>
<module name="InnerAssignment"/>
<module name="JavadocType">
<property name="authorFormat" value="\S"/>
</module>
<module name="JavadocMethod">
<property name="allowUndeclaredRTE" value="true"/>
<property name="allowThrowsTagsForSubclasses" value="true"/>
<property name="allowMissingPropertyJavadoc" value="true"/>
</module>
<module name="JavadocVariable"/>
<module name="JavadocStyle">
<property name="scope" value="public"/>
</module>
<module name="LeftCurly">
<property name="option" value="eol"/>
<property name="tokens" value="CLASS_DEF"/>
<property name="tokens" value="CTOR_DEF"/>
<property name="tokens" value="INTERFACE_DEF"/>
<property name="tokens" value="METHOD_DEF"/>
<property name="tokens" value="LITERAL_CATCH"/>
<property name="tokens" value="LITERAL_DO"/>
<property name="tokens" value="LITERAL_ELSE"/>
<property name="tokens" value="LITERAL_FINALLY"/>
<property name="tokens" value="LITERAL_FOR"/>
<property name="tokens" value="LITERAL_IF"/>
<property name="tokens" value="LITERAL_SWITCH"/>
<property name="tokens" value="LITERAL_SYNCHRONIZED"/>
<property name="tokens" value="LITERAL_TRY"/>
<property name="tokens" value="LITERAL_WHILE"/>
</module>
<module name="OuterTypeNumber"/>
<module name="LineLength">
<property name="ignorePattern" value="^ *\* *[^ ]+$"/>
<property name="max" value="150"/>
</module>
<module name="MethodCount">
<property name="maxTotal" value="40"/>
</module>
<module name="LocalFinalVariableName"/>
<module name="LocalVariableName"/>
<module name="MemberName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
<module name="MethodLength">
<property name="max" value="160"/>
<property name="countEmpty" value="false"/>
</module>
<module name="MethodName"/>
<module name="MethodParamPad"/>
<module name="ModifierOrder"/>
<module name="NeedBraces"/>
<module name="NoWhitespaceAfter">
<property name="tokens" value="ARRAY_INIT"/>
<property name="tokens" value="BNOT"/>
<property name="tokens" value="DEC"/>
<property name="tokens" value="DOT"/>
<property name="tokens" value="INC"/>
<property name="tokens" value="LNOT"/>
<property name="tokens" value="UNARY_MINUS"/>
<property name="tokens" value="UNARY_PLUS"/>
</module>
<module name="NoWhitespaceBefore"/>
<module name="NoWhitespaceBefore">
<property name="tokens" value="DOT"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="OperatorWrap"/>
<module name="OperatorWrap">
<property name="tokens" value="ASSIGN"/>
<property name="tokens" value="DIV_ASSIGN"/>
<property name="tokens" value="PLUS_ASSIGN"/>
<property name="tokens" value="MINUS_ASSIGN"/>
<property name="tokens" value="STAR_ASSIGN"/>
<property name="tokens" value="MOD_ASSIGN"/>
<property name="tokens" value="SR_ASSIGN"/>
<property name="tokens" value="BSR_ASSIGN"/>
<property name="tokens" value="SL_ASSIGN"/>
<property name="tokens" value="BXOR_ASSIGN"/>
<property name="tokens" value="BOR_ASSIGN"/>
<property name="tokens" value="BAND_ASSIGN"/>
<property name="option" value="eol"/>
</module>
<module name="PackageName"/>
<module name="ParameterName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
<module name="ParameterNumber">
<property name="id" value="paramNum"/>
</module>
<module name="ParenPad"/>
<module name="TypecastParenPad"/>
<module name="RedundantImport"/>
<module name="RedundantModifier"/>
<module name="RightCurly">
<property name="option" value="same"/>
</module>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<module name="StaticVariableName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
<module name="TypeName"/>
<module name="UnusedImports"/>
<module name="UpperEll"/>
<module name="VisibilityModifier"/>
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround"/>
<module name="GenericWhitespace"/>
<module name="FinalClass"/>
<module name="MissingSwitchDefault"/>
<!--module name="MagicNumber"/-->
<!--module name="Indentation">
<property name="basicOffset" value="4"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="0"/>
</module-->
<module name="ArrayTrailingComma"/>
<module name="FinalLocalVariable"/>
<module name="EqualsAvoidNull"/>
<module name="ParameterAssignment"/>
<!-- Generates quite a few errors -->
<module name="CyclomaticComplexity">
<property name="severity" value="ignore"/>
</module>
<module name="NestedForDepth">
<property name="max" value="2"/>
</module>
<module name="NestedIfDepth">
<property name="max" value="4"/>
</module>
<module name="NestedTryDepth">
<property name="max" value="2"/>
</module>
<!--module name="ExplicitInitialization"/-->
<module name="AnnotationUseStyle"/>
<module name="MissingDeprecated"/>
<module name="MissingOverride">
<property name="javaFiveCompatibility" value="true"/>
</module>
<module name="PackageAnnotation"/>
<module name="SuppressWarnings"/>
<module name="OuterTypeFilename"/>
<module name="HideUtilityClassConstructor"/>
</module>
</module>

View File

@@ -1,18 +0,0 @@
^/\*\s*$
^ \* This file is part of dependency-check-cli\.\s*$
^ \*\s*$
^ \* Licensed under the Apache License, Version 2\.0 \(the "License"\);\s*$
^ \* you may not use this file except in compliance with the License.\s*$
^ \* You may obtain a copy of the License at\s*$
^ \*\s*$
^ \*\s*http://www.apache.org/licenses/LICENSE-2\.0\s*$
^ \*\s*$
^ \* Unless required by applicable law or agreed to in writing, software\s*$
^ \* distributed under the License is distributed on an "AS IS" BASIS,\s*$
^ \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.\s*$
^ \* See the License for the specific language governing permissions and\s*$
^ \* limitations under the License\.\s*$
^ \*\s*$
^ \* Copyright \(c\) 201[234] (Jeremy Long|Steve Springett)\. All Rights Reserved\.\s*$
^ \*/\s*$
^package

View File

@@ -1,9 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Puppy Crawl//DTD Suppressions 1.0//EN"
"http://www.puppycrawl.com/dtds/suppressions_1_0.dtd">
<suppressions>
<suppress checks=".*" files=".*[\\/]package-info\.java" />
</suppressions>

View File

@@ -21,7 +21,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.1.0</version>
<version>1.2.0</version>
</parent>
<artifactId>dependency-check-cli</artifactId>
@@ -77,8 +77,11 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.5.2</version>
<version>2.6</version>
<configuration>
<instrumentation>
<ignoreTrivial>true</ignoreTrivial>
</instrumentation>
<check>
<branchRate>85</branchRate>
<lineRate>85</lineRate>
@@ -115,11 +118,6 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<version>2.16</version>
<configuration>
<systemProperties>
<property>
<name>net.sourceforge.cobertura.datafile</name>
<value>${project.build.directory}/cobertura/cobertura.ser</value>
<workingDirectory>target</workingDirectory>
</property>
<property>
<name>cpe</name>
<value>data/cpe</value>
@@ -206,7 +204,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.5.2</version>
<version>2.6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -250,16 +248,16 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<version>2.11</version>
<configuration>
<enableRulesSummary>false</enableRulesSummary>
<configLocation>${basedir}/config/checkstyle-checks.xml</configLocation>
<headerLocation>${basedir}/config/checkstyle-header.txt</headerLocation>
<suppressionsLocation>${basedir}/config/checkstyle-suppressions.xml</suppressionsLocation>
<configLocation>${basedir}/../src/main/config/checkstyle-checks.xml</configLocation>
<headerLocation>${basedir}/../src/main/config/checkstyle-header.txt</headerLocation>
<suppressionsLocation>${basedir}/../src/main/config/checkstyle-suppressions.xml</suppressionsLocation>
<suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.0.1</version>
<version>3.1</version>
<configuration>
<targetJdk>1.6</targetJdk>
<linkXref>true</linkXref>
@@ -267,6 +265,12 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<excludes>
<exclude>**/generated/*.java</exclude>
</excludes>
<rulesets>
<ruleset>../src/main/config/dcrules.xml</ruleset>
<ruleset>/rulesets/java/basic.xml</ruleset>
<ruleset>/rulesets/java/imports.xml</ruleset>
<ruleset>/rulesets/java/unusedcode.xml</ruleset>
</rulesets>
</configuration>
</plugin>
<plugin>

View File

@@ -46,6 +46,11 @@ public class App {
*/
private static final String LOG_PROPERTIES_FILE = "log.properties";
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(App.class.getName());
/**
* The main method for the application.
*
@@ -82,7 +87,7 @@ public class App {
if (cli.isGetVersion()) {
cli.printVersionInfo();
} else if (cli.isRunScan()) {
updateSettings(cli);
populateSettings(cli);
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles());
} else {
cli.printHelp();
@@ -98,36 +103,47 @@ public class App {
* @param files the files/directories to scan
*/
private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files) {
final Engine scanner = new Engine();
for (String file : files) {
scanner.scan(file);
}
scanner.analyzeDependencies();
final List<Dependency> dependencies = scanner.getDependencies();
DatabaseProperties prop = null;
CveDB cve = null;
Engine scanner = null;
try {
cve = new CveDB();
cve.open();
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
Logger.getLogger(App.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex);
} finally {
if (cve != null) {
cve.close();
scanner = new Engine();
for (String file : files) {
scanner.scan(file);
}
scanner.analyzeDependencies();
final List<Dependency> dependencies = scanner.getDependencies();
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 report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers(), prop);
try {
report.generateReports(reportDirectory, outputFormat);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "There was an IO error while attempting to generate the report.");
LOGGER.log(Level.FINE, null, ex);
} catch (Throwable ex) {
LOGGER.log(Level.SEVERE, "There was an error while attempting to generate the report.");
LOGGER.log(Level.FINE, null, ex);
}
} catch (DatabaseException ex) {
LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
LOGGER.log(Level.FINE, "", ex);
} finally {
Settings.cleanup();
if (scanner != null) {
scanner.cleanup();
}
}
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers(), prop);
try {
report.generateReports(reportDirectory, outputFormat);
} catch (IOException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, "There was an IO error while attempting to generate the report.");
Logger.getLogger(App.class.getName()).log(Level.INFO, null, ex);
} catch (Exception ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, "There was an error while attempting to generate the report.");
Logger.getLogger(App.class.getName()).log(Level.INFO, null, ex);
}
}
@@ -137,7 +153,9 @@ public class App {
* @param cli a reference to the CLI Parser that contains the command line arguments used to set the corresponding
* settings in the core engine.
*/
private void updateSettings(CliParser cli) {
private void populateSettings(CliParser cli) {
Settings.initialize();
final boolean autoUpdate = cli.isAutoUpdate();
final String connectionTimeout = cli.getConnectionTimeout();
@@ -148,6 +166,10 @@ public class App {
final String dataDirectory = cli.getDataDirectory();
final File propertiesFile = cli.getPropertiesFile();
final String suppressionFile = cli.getSuppressionFile();
final boolean jarDisabled = cli.isJarDisabled();
final boolean archiveDisabled = cli.isArchiveDisabled();
final boolean assemblyDisabled = cli.isAssemblyDisabled();
final boolean nuspecDisabled = cli.isNuspecDisabled();
final boolean nexusDisabled = cli.isNexusDisabled();
final String nexusUrl = cli.getNexusUrl();
final String databaseDriverName = cli.getDatabaseDriverName();
@@ -155,20 +177,26 @@ public class App {
final String connectionString = cli.getConnectionString();
final String databaseUser = cli.getDatabaseUser();
final String databasePassword = cli.getDatabasePassword();
final String additionalZipExtensions = cli.getAdditionalZipExtensions();
final String pathToMono = cli.getPathToMono();
if (propertiesFile != null) {
try {
Settings.mergeProperties(propertiesFile);
} catch (FileNotFoundException ex) {
final String msg = String.format("Unable to load properties file '%s'", propertiesFile.getPath());
Logger.getLogger(App.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(App.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, msg);
LOGGER.log(Level.FINE, null, ex);
} catch (IOException ex) {
final String msg = String.format("Unable to find properties file '%s'", propertiesFile.getPath());
Logger.getLogger(App.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(App.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, msg);
LOGGER.log(Level.FINE, null, ex);
}
}
// We have to wait until we've merged the properties before attempting to set whether we use
// the proxy for Nexus since it could be disabled in the properties, but not explicitly stated
// on the command line
final boolean nexusUsesProxy = cli.isNexusUsesProxy();
if (dataDirectory != null) {
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
} else if (System.getProperty("basedir") != null) {
@@ -200,11 +228,18 @@ public class App {
if (suppressionFile != null && !suppressionFile.isEmpty()) {
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
}
//File Type Analyzer Settings
Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !jarDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !archiveDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !nuspecDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !assemblyDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !nexusDisabled);
if (nexusUrl != null && !nexusUrl.isEmpty()) {
Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
}
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
}
@@ -220,5 +255,11 @@ public class App {
if (databasePassword != null && !databasePassword.isEmpty()) {
Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
}
if (additionalZipExtensions != null && !additionalZipExtensions.isEmpty()) {
Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions);
}
if (pathToMono != null && !pathToMono.isEmpty()) {
Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
}
}
}

View File

@@ -29,6 +29,7 @@ import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
/**
@@ -84,8 +85,11 @@ public final class CliParser {
*/
private void validateArgs() throws FileNotFoundException, ParseException {
if (isRunScan()) {
validatePathExists(getScanFiles(), "scan");
validatePathExists(getReportDirectory(), "out");
validatePathExists(getScanFiles(), ArgumentName.SCAN);
validatePathExists(getReportDirectory(), ArgumentName.OUT);
if (getPathToMono() != null) {
validatePathExists(getPathToMono(), ArgumentName.PATH_TO_MONO);
}
if (!line.hasOption(ArgumentName.APP_NAME)) {
throw new ParseException("Missing 'app' argument; the scan cannot be run without the an application name.");
}
@@ -121,16 +125,18 @@ public final class CliParser {
* FileNotFoundException is thrown.
*
* @param path the paths to validate if they exists
* @param optType the option being validated (e.g. scan, out, etc.)
* @param argumentName the argument being validated (e.g. scan, out, etc.)
* @throws FileNotFoundException is thrown if the path being validated does not exist.
*/
private void validatePathExists(String path, String optType) throws FileNotFoundException {
final File f = new File(path);
if (!f.exists()) {
isValid = false;
final String msg = String.format("Invalid '%s' argument: '%s'", optType, path);
throw new FileNotFoundException(msg);
}
private void validatePathExists(String path, String argumentName) throws FileNotFoundException {
if (!path.contains("*.")) {
final File f = new File(path);
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.
}
/**
@@ -173,7 +179,8 @@ public final class CliParser {
.create(ArgumentName.APP_NAME_SHORT);
final Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.SCAN)
.withDescription("The path to scan - this option can be specified multiple times.")
.withDescription("The path to scan - this option can be specified multiple times. To limit the scan"
+ " to specific file types *.[ext] can be added to the end of the path.")
.create(ArgumentName.SCAN_SHORT);
final Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.PROP)
@@ -192,18 +199,10 @@ public final class CliParser {
.withDescription("The file path to write verbose logging information.")
.create(ArgumentName.VERBOSE_LOG_SHORT);
final Option suppressionFile = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.SUPPRESION_FILE)
final Option suppressionFile = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.SUPPRESSION_FILE)
.withDescription("The file path to the suppression XML file.")
.create();
final Option disableNexusAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_NEXUS)
.withDescription("Disable the Nexus Analyzer.")
.create();
final Option nexusUrl = OptionBuilder.withArgName("url").hasArg().withLongOpt(ArgumentName.NEXUS_URL)
.withDescription("The url to the Nexus Server.")
.create();
//This is an option group because it can be specified more then once.
final OptionGroup og = new OptionGroup();
og.addOption(path);
@@ -218,9 +217,7 @@ public final class CliParser {
.addOption(noUpdate)
.addOption(props)
.addOption(verboseLog)
.addOption(suppressionFile)
.addOption(disableNexusAnalyzer)
.addOption(nexusUrl);
.addOption(suppressionFile);
}
/**
@@ -260,19 +257,58 @@ public final class CliParser {
final Option connectionString = OptionBuilder.withArgName("connStr").hasArg().withLongOpt(ArgumentName.CONNECTION_STRING)
.withDescription("The connection string to the database.")
.create();
final Option dbUser = OptionBuilder.withArgName("user").hasArg().withLongOpt(ArgumentName.DB_NAME)
.withDescription("The username used to connect to the database.")
.create();
final Option dbPassword = OptionBuilder.withArgName("password").hasArg().withLongOpt(ArgumentName.DB_PASSWORD)
.withDescription("The password for connecting to the database.")
.create();
final Option dbDriver = OptionBuilder.withArgName("driver").hasArg().withLongOpt(ArgumentName.DB_DRIVER)
.withDescription("The database driver name.")
.create();
final Option dbDriverPath = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.DB_DRIVER_PATH)
.withDescription("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.")
.create();
final Option disableJarAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_JAR)
.withDescription("Disable the Jar Analyzer.")
.create();
final Option disableArchiveAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_ARCHIVE)
.withDescription("Disable the Archive Analyzer.")
.create();
final Option disableNuspecAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_NUSPEC)
.withDescription("Disable the Nuspec Analyzer.")
.create();
final Option disableAssemblyAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_ASSEMBLY)
.withDescription("Disable the .NET Assembly Analyzer.")
.create();
final Option disableNexusAnalyzer = OptionBuilder.withLongOpt(ArgumentName.DISABLE_NEXUS)
.withDescription("Disable the Nexus Analyzer.")
.create();
final Option nexusUrl = OptionBuilder.withArgName("url").hasArg().withLongOpt(ArgumentName.NEXUS_URL)
.withDescription("The url to the Nexus Server.")
.create();
final Option nexusUsesProxy = OptionBuilder.withArgName("true/false").hasArg().withLongOpt(ArgumentName.NEXUS_USES_PROXY)
.withDescription("Whether or not the configured proxy should be used when connecting to Nexus.")
.create();
final Option additionalZipExtensions = OptionBuilder.withArgName("extensions").hasArg()
.withLongOpt(ArgumentName.ADDITIONAL_ZIP_EXTENSIONS)
.withDescription("A comma separated list of additional extensions to be scanned as ZIP files "
+ "(ZIP, EAR, WAR are already treated as zip files)")
.create();
final Option pathToMono = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.PATH_TO_MONO)
.withDescription("The path to Mono for .NET Assembly analysis on non-windows systems.")
.create();
options.addOption(proxyPort)
.addOption(proxyUrl)
.addOption(proxyUsername)
@@ -283,7 +319,16 @@ public final class CliParser {
.addOption(data)
.addOption(dbPassword)
.addOption(dbDriver)
.addOption(dbDriverPath);
.addOption(dbDriverPath)
.addOption(disableJarAnalyzer)
.addOption(disableArchiveAnalyzer)
.addOption(disableAssemblyAnalyzer)
.addOption(disableNuspecAnalyzer)
.addOption(disableNexusAnalyzer)
.addOption(nexusUrl)
.addOption(nexusUsesProxy)
.addOption(additionalZipExtensions)
.addOption(pathToMono);
}
/**
@@ -313,6 +358,42 @@ public final class CliParser {
return (line != null) && isValid && line.hasOption(ArgumentName.SCAN);
}
/**
* Returns true if the disableJar command line argument was specified.
*
* @return true if the disableJar command line argument was specified; otherwise false
*/
public boolean isJarDisabled() {
return (line != null) && line.hasOption(ArgumentName.DISABLE_JAR);
}
/**
* Returns true if the disableArchive command line argument was specified.
*
* @return true if the disableArchive command line argument was specified; otherwise false
*/
public boolean isArchiveDisabled() {
return (line != null) && line.hasOption(ArgumentName.DISABLE_ARCHIVE);
}
/**
* Returns true if the disableNuspec command line argument was specified.
*
* @return true if the disableNuspec command line argument was specified; otherwise false
*/
public boolean isNuspecDisabled() {
return (line != null) && line.hasOption(ArgumentName.DISABLE_NUSPEC);
}
/**
* Returns true if the disableAssembly command line argument was specified.
*
* @return true if the disableAssembly command line argument was specified; otherwise false
*/
public boolean isAssemblyDisabled() {
return (line != null) && line.hasOption(ArgumentName.DISABLE_ASSEMBLY);
}
/**
* Returns true if the disableNexus command line argument was specified.
*
@@ -335,6 +416,26 @@ public final class CliParser {
}
}
/**
* Returns true if the Nexus Analyzer should use the configured proxy to connect to Nexus; otherwise false is
* returned.
*
* @return true if the Nexus Analyzer should use the configured proxy to connect to Nexus; otherwise false
*/
public boolean isNexusUsesProxy() {
// If they didn't specify whether Nexus needs to use the proxy, we should
// still honor the property if it's set.
if (line == null || !line.hasOption(ArgumentName.NEXUS_USES_PROXY)) {
try {
return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY);
} catch (InvalidSettingException ise) {
return true;
}
} else {
return Boolean.parseBoolean(line.getOptionValue(ArgumentName.NEXUS_USES_PROXY));
}
}
/**
* Displays the command line help message to the standard output.
*/
@@ -377,6 +478,15 @@ public final class CliParser {
return line.getOptionValue(ArgumentName.OUT, ".");
}
/**
* Returns the path to Mono for .NET Assembly analysis on non-windows systems.
*
* @return the path to Mono
*/
public String getPathToMono() {
return line.getOptionValue(ArgumentName.PATH_TO_MONO);
}
/**
* Returns the output format specified on the command line. Defaults to HTML if no format was specified.
*
@@ -477,7 +587,7 @@ public final class CliParser {
* @return the path to the suppression file
*/
public String getSuppressionFile() {
return line.getOptionValue(ArgumentName.SUPPRESION_FILE);
return line.getOptionValue(ArgumentName.SUPPRESSION_FILE);
}
/**
@@ -548,6 +658,15 @@ public final class CliParser {
return line.getOptionValue(ArgumentName.DB_PASSWORD);
}
/**
* Returns the additional Extensions if specified; otherwise null is returned.
*
* @return the additional Extensions; otherwise null is returned
*/
public String getAdditionalZipExtensions() {
return line.getOptionValue(ArgumentName.ADDITIONAL_ZIP_EXTENSIONS);
}
/**
* A collection of static final strings that represent the possible command line arguments.
*/
@@ -648,7 +767,7 @@ public final class CliParser {
/**
* The short CLI argument name for setting the location of an additional properties file.
*/
public static final String PROP_SHORT = "p";
public static final String PROP_SHORT = "P";
/**
* The CLI argument name for setting the location of an additional properties file.
*/
@@ -672,7 +791,23 @@ public final class CliParser {
/**
* The CLI argument name for setting the location of the suppression file.
*/
public static final String SUPPRESION_FILE = "suppression";
public static final String SUPPRESSION_FILE = "suppression";
/**
* Disables the Jar Analyzer.
*/
public static final String DISABLE_JAR = "disableJar";
/**
* Disables the Archive Analyzer.
*/
public static final String DISABLE_ARCHIVE = "disableArchive";
/**
* Disables the Assembly Analyzer.
*/
public static final String DISABLE_ASSEMBLY = "disableAssembly";
/**
* Disables the Nuspec Analyzer.
*/
public static final String DISABLE_NUSPEC = "disableNuspec";
/**
* Disables the Nexus Analyzer.
*/
@@ -681,6 +816,10 @@ public final class CliParser {
* The URL of the nexus server.
*/
public static final String NEXUS_URL = "nexus";
/**
* Whether or not the defined proxy should be used when connecting to Nexus.
*/
public static final String NEXUS_USES_PROXY = "nexusUsesProxy";
/**
* The CLI argument name for setting the connection string.
*/
@@ -701,5 +840,13 @@ public final class CliParser {
* The CLI argument name for setting the path to the database driver; in case it is not on the class path.
*/
public static final String DB_DRIVER_PATH = "dbDriverPath";
/**
* The CLI argument name for setting the path to mono for .NET Assembly analysis on non-windows systems.
*/
public static final String PATH_TO_MONO = "mono";
/**
* The CLI argument name for setting extra extensions.
*/
public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
}
}

View File

@@ -1,30 +1,43 @@
Command Line Arguments
====================
======================
The following table lists the command line arguments:
Short | Argument Name | Parameter | Description | Requirement
-------|-----------------------|-------------|-------------|------------
\-a | \-\-app | \<name\> | The name of the application being scanned. This is a required argument. |
\-c | \-\-connectiontimeout | \<timeout\> | The connection timeout (in milliseconds) to use when downloading resources. | Optional
\-d | \-\-data | \<path\> | The location of the data directory used to store persistent data. This option should generally not be set. | Optional
\-f | \-\-format | \<format\> | The output format to write to (XML, HTML, VULN, ALL). The default is HTML. |
\-h | \-\-help | | Print the help message. | Optional
\-l | \-\-log | \<file\> | The file path to write verbose logging information. | Optional
\-n | \-\-noupdate | | Disables the automatic updating of the CPE data. | Optional
\-o | \-\-out | \<folder\> | The folder to write reports to. This defaults to the current directory. | Optional
\-p | \-\-proxyport | \<port\> | The proxy port to use when downloading resources. | Optional
| \-\-proxypass | \<pass\> | The proxy password to use when downloading resources. | Optional
| \-\-proxyuser | \<user\> | The proxy username to use when downloading resources. | Optional
\-s | \-\-scan | \<path\> | The path to scan \- this option can be specified multiple times. |
| \-\-suppression | \<file\> | The file path to the suppression XML file; used to suppress [false positives](../suppression.html). | Optional
\-u | \-\-proxyurl | \<url\> | The proxy url to use when downloading resources. | Optional
\-v | \-\-version | | Print the version information. | Optional
| \-\-advancedHelp | | Print the advanced help message. | Optional
| \-\-connectionString | \<connStr\> | The connection string to the database. | Optional
| \-\-dbDriverName | \<driver\> | The database driver name. | Optional
| \-\-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. | Optional
| \-\-dbPassword | \<password\>| The password for connecting to the database. | Optional
| \-\-dbUser | \<user\> | The username used to connect to the database. | Optional
| \-\-disableNexus | | Disable the Nexus Analyzer. | Optional
| \-\-nexus | \<url\> | The url to the Nexus Server. | Optional
Short | Argument Name | Parameter | Description | Requirement
-------|-----------------------|-----------------|-------------|------------
\-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
\-o | \-\-out | \<folder\> | The folder to write reports to. This defaults to the current directory. | Optional
\-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
\-n | \-\-noupdate | | Disables the automatic updating of the CPE data. | Optional
| \-\-suppression | \<file\> | The file path to the suppression XML file; used to suppress [false positives](../suppression.html). | Optional
\-h | \-\-help | | Print the help message. | Optional
| \-\-advancedHelp | | Print the advanced help message. | Optional
\-v | \-\-version | | Print the version information. | Optional
Advanced Options
================
Short | Argument Name | Parameter | Description | Default Value
-------|-----------------------|-----------------|-------------|---------------
| \-\-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. | &nbsp;
| \-\-disableJar | | Sets whether Jar Analyzer will be used. | false
| \-\-disableNexus | | Sets whether Nexus Analyzer will be used. | false
| \-\-disableNexus | | Disable the Nexus Analyzer. | &nbsp;
| \-\-nexus | \<url\> | The url to the Nexus Server. | https://repository.sonatype.org/service/local/
| \-\-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
| \-\-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. | &nbsp;
| \-\-proxyurl | \<url\> | The proxy url to use when downloading resources. | &nbsp;
| \-\-proxyport | \<port\> | The proxy port to use when downloading resources. | &nbsp;
| \-\-connectiontimeout | \<timeout\> | The connection timeout (in milliseconds) to use when downloading resources. | &nbsp;
| \-\-proxypass | \<pass\> | The proxy password to use when downloading resources. | &nbsp;
| \-\-proxyuser | \<user\> | The proxy username to use when downloading resources. | &nbsp;
| \-\-connectionString | \<connStr\> | The connection string to the database. | &nbsp;
| \-\-dbDriverName | \<driver\> | The database driver name. | &nbsp;
| \-\-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. | &nbsp;
| \-\-dbPassword | \<password\> | The password for connecting to the database. | &nbsp;
| \-\-dbUser | \<user\> | The username used to connect to the database. | &nbsp;
\-d | \-\-data | \<path\> | The location of the data directory used to store persistent data. This option should generally not be set. | &nbsp;

View File

@@ -1,5 +1,5 @@
Installation & Usage
--------------------
====================
Download the dependency-check command line tool [here](http://dl.bintray.com/jeremy-long/owasp/dependency-check-${project.version}-release.zip).
Extract the zip file to a location on your computer and put the 'bin' directory into the
path environment variable. On \*nix systems you will likely need to make the shell
@@ -8,16 +8,18 @@ script executable:
$ chmod +777 dependency-check.sh
To scan a folder on the system you can run:
#set( $H = '#' )
<h3>Windows</h3>
$H$H$H Windows
dependency-check.bat --app "My App Name" --scan "c:\java\application\lib"
<h3>\*nix</h3>
$H$H$H *nix
dependency-check.sh --app "My App Name" --scan "/java/application/lib"
To view the command line arguments, see the <a href="arguments.html">arguments page</a>, or you can run:
<h3>Windows</h3>
$H$H$H Windows
dependency-check.bat --help
<h3>\*nix</h3>
$H$H$H *nix
dependency-check.sh --help

View File

@@ -29,6 +29,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.utils.Settings;
/**
*
@@ -38,10 +39,12 @@ public class CliParserTest {
@BeforeClass
public static void setUpClass() throws Exception {
Settings.initialize();
}
@AfterClass
public static void tearDownClass() throws Exception {
Settings.cleanup();
}
@Before

View File

@@ -1,223 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker">
<!--
If you set the basedir property below, then all reported file
names will be relative to the specified directory. See
http://checkstyle.sourceforge.net/5.x/config.html#Checker
<property name="basedir" value="${basedir}"/>
-->
<property name="severity" value="error"/>
<module name="SuppressionFilter">
<property name="file" value="${checkstyle.suppressions.file}"/>
</module>
<module name="JavadocPackage">
<property name="allowLegacy" value="false"/>
</module>
<module name="Translation">
<property name="severity" value="warning"/>
</module>
<module name="FileTabCharacter">
<property name="eachLine" value="false"/>
</module>
<module name="FileLength">
<property name="fileExtensions" value="java"/>
</module>
<module name="NewlineAtEndOfFile">
<property name="fileExtensions" value="java"/>
<property name="lineSeparator" value="lf"/>
</module>
<module name="RegexpHeader">
<property name="headerFile" value="${checkstyle.header.file}"/>
<property name="fileExtensions" value="java"/>
<property name="id" value="header"/>
</module>
<module name="RegexpSingleline">
<property name="format" value="\s+$"/>
<property name="minimum" value="0"/>
<property name="maximum" value="0"/>
</module>
<module name="TreeWalker">
<property name="tabWidth" value="4"/>
<module name="AvoidStarImport"/>
<module name="ConstantName"/>
<module name="EmptyBlock"/>
<module name="EmptyForIteratorPad"/>
<module name="EqualsHashCode"/>
<module name="OneStatementPerLine"/>
<!-- module name="IllegalCatch"/ -->
<!--module name="ImportControl">
<property name="file" value="${checkstyle.importcontrol.file}"/>
</module-->
<module name="IllegalImport"/>
<module name="IllegalInstantiation"/>
<module name="IllegalThrows"/>
<module name="InnerAssignment"/>
<module name="JavadocType">
<property name="authorFormat" value="\S"/>
</module>
<module name="JavadocMethod">
<property name="allowUndeclaredRTE" value="true"/>
<property name="allowThrowsTagsForSubclasses" value="true"/>
<property name="allowMissingPropertyJavadoc" value="true"/>
</module>
<module name="JavadocVariable"/>
<module name="JavadocStyle">
<property name="scope" value="public"/>
</module>
<module name="LeftCurly">
<property name="option" value="eol"/>
<property name="tokens" value="CLASS_DEF"/>
<property name="tokens" value="CTOR_DEF"/>
<property name="tokens" value="INTERFACE_DEF"/>
<property name="tokens" value="METHOD_DEF"/>
<property name="tokens" value="LITERAL_CATCH"/>
<property name="tokens" value="LITERAL_DO"/>
<property name="tokens" value="LITERAL_ELSE"/>
<property name="tokens" value="LITERAL_FINALLY"/>
<property name="tokens" value="LITERAL_FOR"/>
<property name="tokens" value="LITERAL_IF"/>
<property name="tokens" value="LITERAL_SWITCH"/>
<property name="tokens" value="LITERAL_SYNCHRONIZED"/>
<property name="tokens" value="LITERAL_TRY"/>
<property name="tokens" value="LITERAL_WHILE"/>
</module>
<module name="OuterTypeNumber"/>
<module name="LineLength">
<property name="ignorePattern" value="^ *\* *[^ ]+$"/>
<property name="max" value="150"/>
</module>
<module name="MethodCount">
<property name="maxTotal" value="40"/>
</module>
<module name="LocalFinalVariableName"/>
<module name="LocalVariableName"/>
<module name="MemberName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
<module name="MethodLength">
<property name="max" value="160"/>
<property name="countEmpty" value="false"/>
</module>
<module name="MethodName"/>
<module name="MethodParamPad"/>
<module name="ModifierOrder"/>
<module name="NeedBraces"/>
<module name="NoWhitespaceAfter">
<property name="tokens" value="ARRAY_INIT"/>
<property name="tokens" value="BNOT"/>
<property name="tokens" value="DEC"/>
<property name="tokens" value="DOT"/>
<property name="tokens" value="INC"/>
<property name="tokens" value="LNOT"/>
<property name="tokens" value="UNARY_MINUS"/>
<property name="tokens" value="UNARY_PLUS"/>
</module>
<module name="NoWhitespaceBefore"/>
<module name="NoWhitespaceBefore">
<property name="tokens" value="DOT"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="OperatorWrap"/>
<module name="OperatorWrap">
<property name="tokens" value="ASSIGN"/>
<property name="tokens" value="DIV_ASSIGN"/>
<property name="tokens" value="PLUS_ASSIGN"/>
<property name="tokens" value="MINUS_ASSIGN"/>
<property name="tokens" value="STAR_ASSIGN"/>
<property name="tokens" value="MOD_ASSIGN"/>
<property name="tokens" value="SR_ASSIGN"/>
<property name="tokens" value="BSR_ASSIGN"/>
<property name="tokens" value="SL_ASSIGN"/>
<property name="tokens" value="BXOR_ASSIGN"/>
<property name="tokens" value="BOR_ASSIGN"/>
<property name="tokens" value="BAND_ASSIGN"/>
<property name="option" value="eol"/>
</module>
<module name="PackageName"/>
<module name="ParameterName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
<module name="ParameterNumber">
<property name="id" value="paramNum"/>
</module>
<module name="ParenPad"/>
<module name="TypecastParenPad"/>
<module name="RedundantImport"/>
<module name="RedundantModifier"/>
<module name="RightCurly">
<property name="option" value="same"/>
</module>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<module name="StaticVariableName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
<module name="TypeName"/>
<module name="UnusedImports"/>
<module name="UpperEll"/>
<module name="VisibilityModifier"/>
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround"/>
<module name="GenericWhitespace"/>
<module name="FinalClass"/>
<module name="MissingSwitchDefault"/>
<!--module name="MagicNumber"/-->
<!--module name="Indentation">
<property name="basicOffset" value="4"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="0"/>
</module-->
<module name="ArrayTrailingComma"/>
<module name="FinalLocalVariable"/>
<module name="EqualsAvoidNull"/>
<module name="ParameterAssignment"/>
<!-- Generates quite a few errors -->
<module name="CyclomaticComplexity">
<property name="severity" value="ignore"/>
</module>
<module name="NestedForDepth">
<property name="max" value="2"/>
</module>
<module name="NestedIfDepth">
<property name="max" value="4"/>
</module>
<module name="NestedTryDepth">
<property name="max" value="2"/>
</module>
<!--module name="ExplicitInitialization"/-->
<module name="AnnotationUseStyle"/>
<module name="MissingDeprecated"/>
<module name="MissingOverride">
<property name="javaFiveCompatibility" value="true"/>
</module>
<module name="PackageAnnotation"/>
<module name="SuppressWarnings"/>
<module name="OuterTypeFilename"/>
<module name="HideUtilityClassConstructor"/>
</module>
</module>

View File

@@ -1,18 +0,0 @@
^/\*\s*$
^ \* This file is part of dependency-check-core\.\s*$
^ \*\s*$
^ \* Licensed under the Apache License, Version 2\.0 \(the "License"\);\s*$
^ \* you may not use this file except in compliance with the License.\s*$
^ \* You may obtain a copy of the License at\s*$
^ \*\s*$
^ \*\s*http://www.apache.org/licenses/LICENSE-2\.0\s*$
^ \*\s*$
^ \* Unless required by applicable law or agreed to in writing, software\s*$
^ \* distributed under the License is distributed on an "AS IS" BASIS,\s*$
^ \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.\s*$
^ \* See the License for the specific language governing permissions and\s*$
^ \* limitations under the License\.\s*$
^ \*\s*$
^ \* Copyright \(c\) 201[234] (Jeremy Long|Steve Springett)\. All Rights Reserved\.\s*$
^ \*/\s*$
^package

View File

@@ -21,7 +21,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.1.0</version>
<version>1.2.0</version>
</parent>
<artifactId>dependency-check-core</artifactId>
@@ -144,6 +144,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<version>2.6</version>
<configuration>
<instrumentation>
<ignoreTrivial>true</ignoreTrivial>
<ignores>
<ignore>.*\$KEYS\.class</ignore>
<ignore>.*\$Element\.class</ignore>
@@ -347,16 +348,16 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<version>2.11</version>
<configuration>
<enableRulesSummary>false</enableRulesSummary>
<configLocation>${basedir}/config/checkstyle-checks.xml</configLocation>
<headerLocation>${basedir}/config/checkstyle-header.txt</headerLocation>
<suppressionsLocation>${basedir}/config/checkstyle-suppressions.xml</suppressionsLocation>
<configLocation>${basedir}/../src/main/config/checkstyle-checks.xml</configLocation>
<headerLocation>${basedir}/../src/main/config/checkstyle-header.txt</headerLocation>
<suppressionsLocation>${basedir}/../src/main/config/checkstyle-suppressions.xml</suppressionsLocation>
<suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.0.1</version>
<version>3.1</version>
<configuration>
<targetJdk>1.6</targetJdk>
<linkXref>true</linkXref>
@@ -364,6 +365,12 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<excludes>
<exclude>**/generated/*.java</exclude>
</excludes>
<rulesets>
<ruleset>../src/main/config/dcrules.xml</ruleset>
<ruleset>/rulesets/java/basic.xml</ruleset>
<ruleset>/rulesets/java/imports.xml</ruleset>
<ruleset>/rulesets/java/unusedcode.xml</ruleset>
</rulesets>
</configuration>
</plugin>
<plugin>
@@ -409,6 +416,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<artifactId>commons-cli</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
@@ -494,11 +506,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<version>1.7.2</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.5</version>
</dependency>
<!-- The following dependencies are only used during testing -->
<dependency>
<groupId>org.apache.maven.scm</groupId>
@@ -580,6 +587,20 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa</artifactId>
<version>2.0.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
<profiles>
<profile>
@@ -635,5 +656,40 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</plugins>
</build>
</profile>
<profile>
<!-- The following profile adds additional
dependencies that are only used during testing.
Additionally, these are only added when using "allTests" to
make the build slightly faster in most cases. -->
<id>False Positive Tests</id>
<!--activation>
<property>
<name>allTests</name>
</property>
</activation-->
<dependencies>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-util</artifactId>
<version>1.7</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.2</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.ws.security</groupId>
<artifactId>wss4j</artifactId>
<version>1.5.7</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

View File

@@ -26,12 +26,14 @@ import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.analyzer.AnalysisException;
import org.owasp.dependencycheck.analyzer.AnalysisPhase;
import org.owasp.dependencycheck.analyzer.Analyzer;
import org.owasp.dependencycheck.analyzer.AnalyzerService;
import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
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.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.data.update.CachedWebDataSource;
@@ -55,29 +57,52 @@ public class Engine {
/**
* The list of dependencies.
*/
private final List<Dependency> dependencies;
private List<Dependency> dependencies;
/**
* A Map of analyzers grouped by Analysis phase.
*/
private final EnumMap<AnalysisPhase, List<Analyzer>> analyzers;
/**
* A set of extensions supported by the analyzers.
* A Map of analyzers grouped by Analysis phase.
*/
private final Set<String> extensions;
private final Set<FileTypeAnalyzer> fileTypeAnalyzers;
/**
* The ClassLoader to use when dynamically loading Analyzer and Update services.
*/
private ClassLoader serviceClassLoader;
/**
* The Logger for use throughout the class.
*/
private static final Logger LOGGER = Logger.getLogger(Engine.class.getName());
/**
* Creates a new Engine.
*
* @throws DatabaseException thrown if there is an error connecting to the database
*/
public Engine() {
this.extensions = new HashSet<String>();
public Engine() throws DatabaseException {
this(Thread.currentThread().getContextClassLoader());
}
/**
* 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
*/
public Engine(ClassLoader serviceClassLoader) 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();
boolean autoUpdate = true;
try {
autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
} catch (InvalidSettingException ex) {
Logger.getLogger(Engine.class.getName()).log(Level.FINE, "Invalid setting for auto-update; using true.");
LOGGER.log(Level.FINE, "Invalid setting for auto-update; using true.");
}
if (autoUpdate) {
doUpdates();
@@ -85,6 +110,13 @@ public class Engine {
loadAnalyzers();
}
/**
* Properly cleans up resources allocated during analysis.
*/
public void cleanup() {
ConnectionFactory.cleanup();
}
/**
* Loads the analyzers specified in the configuration file (or system properties).
*/
@@ -94,13 +126,13 @@ public class Engine {
analyzers.put(phase, new ArrayList<Analyzer>());
}
final AnalyzerService service = AnalyzerService.getInstance();
final AnalyzerService service = new AnalyzerService(serviceClassLoader);
final Iterator<Analyzer> iterator = service.getAnalyzers();
while (iterator.hasNext()) {
final Analyzer a = iterator.next();
analyzers.get(a.getAnalysisPhase()).add(a);
if (a.getSupportedExtensions() != null) {
extensions.addAll(a.getSupportedExtensions());
if (a instanceof FileTypeAnalyzer) {
this.fileTypeAnalyzers.add((FileTypeAnalyzer) a);
}
}
}
@@ -124,6 +156,13 @@ public class Engine {
return dependencies;
}
public void setDependencies(List<Dependency> 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
* dependencies identified are added to the dependency collection.
@@ -146,8 +185,21 @@ public class Engine {
* @param path the path to a file or directory to be analyzed.
*/
public void scan(String path) {
final File file = new File(path);
scan(file);
if (path.matches("^.*[\\/]\\*\\.[^\\/:*|?<>\"]+$")) {
final String[] parts = path.split("\\*\\.");
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);
}
}
/**
@@ -236,20 +288,20 @@ public class Engine {
protected void scanFile(File file) {
if (!file.isFile()) {
final String msg = String.format("Path passed to scanFile(File) is not a file: %s. Skipping the file.", file.toString());
Logger.getLogger(Engine.class.getName()).log(Level.FINE, msg);
LOGGER.log(Level.FINE, msg);
return;
}
final String fileName = file.getName();
final String extension = FileUtils.getFileExtension(fileName);
if (extension != null) {
if (extensions.contains(extension)) {
if (supportsExtension(extension)) {
final Dependency dependency = new Dependency(file);
dependencies.add(dependency);
}
} else {
final String msg = String.format("No file extension found on file '%s'. The file was not analyzed.",
file.toString());
Logger.getLogger(Engine.class.getName()).log(Level.FINEST, msg);
LOGGER.log(Level.FINEST, msg);
}
}
@@ -262,13 +314,13 @@ public class Engine {
ensureDataExists();
} catch (NoDataException ex) {
final String msg = String.format("%s%n%nUnable to continue dependency-check analysis.", ex.getMessage());
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(Engine.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, msg);
LOGGER.log(Level.FINE, null, ex);
return;
} catch (DatabaseException ex) {
final String msg = String.format("%s%n%nUnable to continue dependency-check analysis.", ex.getMessage());
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(Engine.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, msg);
LOGGER.log(Level.FINE, null, ex);
return;
}
@@ -277,74 +329,54 @@ public class Engine {
+ "----------------------------------------------------%n"
+ "BEGIN ANALYSIS%n"
+ "----------------------------------------------------");
Logger.getLogger(Engine.class.getName()).log(Level.FINE, logHeader);
Logger.getLogger(Engine.class.getName()).log(Level.INFO, "Analysis Starting");
//phase one initialize
for (AnalysisPhase phase : AnalysisPhase.values()) {
final List<Analyzer> analyzerList = analyzers.get(phase);
for (Analyzer a : analyzerList) {
try {
final String msg = String.format("Initializing %s", a.getName());
Logger.getLogger(Engine.class.getName()).log(Level.FINE, msg);
a.initialize();
} catch (Exception ex) {
final String msg = String.format("Exception occurred initializing %s.", a.getName());
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(Engine.class.getName()).log(Level.INFO, null, ex);
try {
a.close();
} catch (Exception ex1) {
Logger.getLogger(Engine.class.getName()).log(Level.FINEST, null, ex1);
}
}
}
}
LOGGER.log(Level.FINE, logHeader);
LOGGER.log(Level.INFO, "Analysis Starting");
// analysis phases
for (AnalysisPhase phase : AnalysisPhase.values()) {
final List<Analyzer> analyzerList = analyzers.get(phase);
for (Analyzer a : analyzerList) {
initializeAnalyzer(a);
/* need to create a copy of the collection because some of the
* analyzers may modify it. This prevents ConcurrentModificationExceptions.
* This is okay for adds/deletes because it happens per analyzer.
*/
final String msg = String.format("Begin Analyzer '%s'", a.getName());
Logger.getLogger(Engine.class.getName()).log(Level.FINE, msg);
LOGGER.log(Level.FINE, msg);
final Set<Dependency> dependencySet = new HashSet<Dependency>();
dependencySet.addAll(dependencies);
for (Dependency d : dependencySet) {
if (a.supportsExtension(d.getFileExtension())) {
boolean shouldAnalyze = true;
if (a instanceof FileTypeAnalyzer) {
final FileTypeAnalyzer fAnalyzer = (FileTypeAnalyzer) a;
shouldAnalyze = fAnalyzer.supportsExtension(d.getFileExtension());
}
if (shouldAnalyze) {
final String msgFile = String.format("Begin Analysis of '%s'", d.getActualFilePath());
Logger.getLogger(Engine.class.getName()).log(Level.FINE, msgFile);
LOGGER.log(Level.FINE, msgFile);
try {
a.analyze(d, this);
} catch (AnalysisException ex) {
d.addAnalysisException(ex);
final String exMsg = String.format("An error occurred while analyzing '%s'.", d.getActualFilePath());
LOGGER.log(Level.WARNING, exMsg);
LOGGER.log(Level.FINE, "", ex);
} catch (Throwable ex) {
final String axMsg = String.format("An unexpected error occurred during analysis of '%s'", d.getActualFilePath());
final AnalysisException ax = new AnalysisException(axMsg, ex);
d.addAnalysisException(ax);
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, axMsg);
Logger.getLogger(Engine.class.getName()).log(Level.FINE, axMsg, ex);
//final AnalysisException ax = new AnalysisException(axMsg, ex);
LOGGER.log(Level.WARNING, axMsg);
LOGGER.log(Level.FINE, "", ex);
}
}
}
}
}
//close/cleanup
for (AnalysisPhase phase : AnalysisPhase.values()) {
final List<Analyzer> analyzerList = analyzers.get(phase);
for (Analyzer a : analyzerList) {
final String msg = String.format("Closing Analyzer '%s'", a.getName());
Logger.getLogger(Engine.class.getName()).log(Level.FINE, msg);
try {
a.close();
} catch (Exception ex) {
Logger.getLogger(Engine.class.getName()).log(Level.FINEST, null, ex);
}
closeAnalyzer(a);
}
}
@@ -352,24 +384,61 @@ public class Engine {
+ "----------------------------------------------------%n"
+ "END ANALYSIS%n"
+ "----------------------------------------------------");
Logger.getLogger(Engine.class.getName()).log(Level.FINE, logFooter);
Logger.getLogger(Engine.class.getName()).log(Level.INFO, "Analysis Complete");
LOGGER.log(Level.FINE, logFooter);
LOGGER.log(Level.INFO, "Analysis Complete");
}
/**
* Initializes the given analyzer.
*
* @param analyzer the analyzer to initialize
*/
private void initializeAnalyzer(Analyzer analyzer) {
try {
final String msg = String.format("Initializing %s", analyzer.getName());
LOGGER.log(Level.FINE, msg);
analyzer.initialize();
} catch (Throwable ex) {
final String msg = String.format("Exception occurred initializing %s.", analyzer.getName());
LOGGER.log(Level.SEVERE, msg);
LOGGER.log(Level.FINE, null, ex);
try {
analyzer.close();
} catch (Throwable ex1) {
LOGGER.log(Level.FINEST, null, ex1);
}
}
}
/**
* Closes the given analyzer.
*
* @param analyzer the analyzer to close
*/
private void closeAnalyzer(Analyzer analyzer) {
final String msg = String.format("Closing Analyzer '%s'", analyzer.getName());
LOGGER.log(Level.FINE, msg);
try {
analyzer.close();
} catch (Throwable ex) {
LOGGER.log(Level.FINEST, null, ex);
}
}
/**
* Cycles through the cached web data sources and calls update on all of them.
*/
private void doUpdates() {
final UpdateService service = UpdateService.getInstance();
final UpdateService service = new UpdateService(serviceClassLoader);
final Iterator<CachedWebDataSource> iterator = service.getDataSources();
while (iterator.hasNext()) {
final CachedWebDataSource source = iterator.next();
try {
source.update();
} catch (UpdateException ex) {
Logger.getLogger(Engine.class.getName()).log(Level.WARNING,
LOGGER.log(Level.WARNING,
"Unable to update Cached Web DataSource, using local data instead. Results may not include recent vulnerabilities.");
Logger.getLogger(Engine.class.getName()).log(Level.FINE,
LOGGER.log(Level.FINE,
String.format("Unable to update details for %s", source.getClass().getName()), ex);
}
}
@@ -399,15 +468,13 @@ public class Engine {
if (ext == null) {
return false;
}
for (AnalysisPhase phase : AnalysisPhase.values()) {
final List<Analyzer> analyzerList = analyzers.get(phase);
for (Analyzer a : analyzerList) {
if (a.getSupportedExtensions() != null && a.supportsExtension(ext)) {
return true;
}
}
boolean scan = false;
for (FileTypeAnalyzer a : this.fileTypeAnalyzers) {
/* note, we can't break early on this loop as the analyzers need to know if
they have files to work on prior to initialization */
scan |= a.supportsExtension(ext);
}
return false;
return scan;
}
/**

View File

@@ -0,0 +1,971 @@
/*
* 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.agent;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.Engine;
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.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.exception.ScanAgentException;
import org.owasp.dependencycheck.reporting.ReportGenerator;
import org.owasp.dependencycheck.utils.Settings;
/**
* This class provides a way to easily conduct a scan solely based on existing evidence metadata rather than collecting
* evidence from the files themselves. This class is based on the Ant task and Maven plugin with the exception that it
* takes a list of dependencies that can be programmatically added from data in a spreadsheet, database or some other
* datasource and conduct a scan based on this pre-defined evidence.
*
* <h2>Example:</h2>
* <pre>
* List<Dependency> dependencies = new ArrayList<Dependency>();
* Dependency dependency = new Dependency(new File(FileUtils.getBitBucket()));
* dependency.getProductEvidence().addEvidence("my-datasource", "name", "Jetty", Confidence.HIGH);
* dependency.getVersionEvidence().addEvidence("my-datasource", "version", "5.1.10", Confidence.HIGH);
* dependency.getVendorEvidence().addEvidence("my-datasource", "vendor", "mortbay", Confidence.HIGH);
* dependencies.add(dependency);
*
* DependencyCheckScanAgent scan = new DependencyCheckScanAgent();
* scan.setDependencies(dependencies);
* scan.setReportFormat(ReportGenerator.Format.ALL);
* scan.setReportOutputDirectory(System.getProperty("user.home"));
* scan.execute();
* </pre>
*
* @author Steve Springett <steve.springett@owasp.org>
*/
@SuppressWarnings("unused")
public class DependencyCheckScanAgent {
/**
* System specific new line character.
*/
private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
/**
* Logger for use throughout the class.
*/
private static final Logger LOGGER = Logger.getLogger(DependencyCheckScanAgent.class.getName());
/**
* The application name for the report.
*/
private String applicationName = "Dependency-Check";
/**
* Get the value of applicationName.
*
* @return the value of applicationName
*/
public String getApplicationName() {
return applicationName;
}
/**
* Set the value of applicationName.
*
* @param applicationName new value of applicationName
*/
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
/**
* The pre-determined dependencies to scan
*/
private List<Dependency> dependencies;
/**
* Returns a list of pre-determined dependencies.
*
* @return returns a list of dependencies
*/
public List<Dependency> getDependencies() {
return dependencies;
}
/**
* Sets the list of dependencies to scan.
*
* @param dependencies new value of dependencies
*/
public void setDependencies(List<Dependency> dependencies) {
this.dependencies = dependencies;
}
/**
* The location of the data directory that contains
*/
private String dataDirectory = null;
/**
* Get the value of dataDirectory.
*
* @return the value of dataDirectory
*/
public String getDataDirectory() {
return dataDirectory;
}
/**
* Set the value of dataDirectory.
*
* @param dataDirectory new value of dataDirectory
*/
public void setDataDirectory(String dataDirectory) {
this.dataDirectory = dataDirectory;
}
/**
* Specifies the destination directory for the generated Dependency-Check report.
*/
private String reportOutputDirectory;
/**
* Get the value of reportOutputDirectory.
*
* @return the value of reportOutputDirectory
*/
public String getReportOutputDirectory() {
return reportOutputDirectory;
}
/**
* Set the value of reportOutputDirectory.
*
* @param reportOutputDirectory new value of reportOutputDirectory
*/
public void setReportOutputDirectory(String reportOutputDirectory) {
this.reportOutputDirectory = reportOutputDirectory;
}
/**
* 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 and the CVSS score is set to 11.
* The valid range for the fail build on CVSS is 0 to 11, where anything above 10 will not cause the build to fail.
*/
private float failBuildOnCVSS = 11;
/**
* Get the value of failBuildOnCVSS.
*
* @return the value of failBuildOnCVSS
*/
public float getFailBuildOnCVSS() {
return failBuildOnCVSS;
}
/**
* Set the value of failBuildOnCVSS.
*
* @param failBuildOnCVSS new value of failBuildOnCVSS
*/
public void setFailBuildOnCVSS(float failBuildOnCVSS) {
this.failBuildOnCVSS = failBuildOnCVSS;
}
/**
* 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.
*/
private boolean autoUpdate = true;
/**
* Get the value of autoUpdate.
*
* @return the value of autoUpdate
*/
public boolean isAutoUpdate() {
return autoUpdate;
}
/**
* Set the value of autoUpdate.
*
* @param autoUpdate new value of autoUpdate
*/
public void setAutoUpdate(boolean autoUpdate) {
this.autoUpdate = autoUpdate;
}
/**
* 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. Default is HTML.
*/
private ReportGenerator.Format reportFormat = ReportGenerator.Format.HTML;
/**
* Get the value of reportFormat.
*
* @return the value of reportFormat
*/
public ReportGenerator.Format getReportFormat() {
return reportFormat;
}
/**
* Set the value of reportFormat.
*
* @param reportFormat new value of reportFormat
*/
public void setReportFormat(ReportGenerator.Format reportFormat) {
this.reportFormat = reportFormat;
}
/**
* The Proxy URL.
*/
private String proxyUrl;
/**
* Get the value of proxyUrl.
*
* @return the value of proxyUrl
*/
public String getProxyUrl() {
return proxyUrl;
}
/**
* Set the value of proxyUrl.
*
* @param proxyUrl new value of proxyUrl
*/
public void setProxyUrl(String proxyUrl) {
this.proxyUrl = proxyUrl;
}
/**
* The Proxy Port.
*/
private String proxyPort;
/**
* Get the value of proxyPort.
*
* @return the value of proxyPort
*/
public String getProxyPort() {
return proxyPort;
}
/**
* Set the value of proxyPort.
*
* @param proxyPort new value of proxyPort
*/
public void setProxyPort(String proxyPort) {
this.proxyPort = proxyPort;
}
/**
* The Proxy username.
*/
private String proxyUsername;
/**
* Get the value of proxyUsername.
*
* @return the value of proxyUsername
*/
public String getProxyUsername() {
return proxyUsername;
}
/**
* Set the value of proxyUsername.
*
* @param proxyUsername new value of proxyUsername
*/
public void setProxyUsername(String proxyUsername) {
this.proxyUsername = proxyUsername;
}
/**
* The Proxy password.
*/
private String proxyPassword;
/**
* Get the value of proxyPassword.
*
* @return the value of proxyPassword
*/
public String getProxyPassword() {
return proxyPassword;
}
/**
* Set the value of proxyPassword.
*
* @param proxyPassword new value of proxyPassword
*/
public void setProxyPassword(String proxyPassword) {
this.proxyPassword = proxyPassword;
}
/**
* The Connection Timeout.
*/
private String connectionTimeout;
/**
* Get the value of connectionTimeout.
*
* @return the value of connectionTimeout
*/
public String getConnectionTimeout() {
return connectionTimeout;
}
/**
* Set the value of connectionTimeout.
*
* @param connectionTimeout new value of connectionTimeout
*/
public void setConnectionTimeout(String connectionTimeout) {
this.connectionTimeout = connectionTimeout;
}
/**
* The file path used for verbose logging.
*/
private String logFile = null;
/**
* Get the value of logFile.
*
* @return the value of logFile
*/
public String getLogFile() {
return logFile;
}
/**
* Set the value of logFile.
*
* @param logFile new value of logFile
*/
public void setLogFile(String logFile) {
this.logFile = logFile;
}
/**
* The path to the suppression file.
*/
private String suppressionFile;
/**
* Get the value of suppressionFile.
*
* @return the value of suppressionFile
*/
public String getSuppressionFile() {
return suppressionFile;
}
/**
* Set the value of suppressionFile.
*
* @param suppressionFile new value of suppressionFile
*/
public void setSuppressionFile(String suppressionFile) {
this.suppressionFile = suppressionFile;
}
/**
* flag indicating whether or not to show a summary of findings.
*/
private boolean showSummary = true;
/**
* Get the value of showSummary.
*
* @return the value of showSummary
*/
public boolean isShowSummary() {
return showSummary;
}
/**
* Set the value of showSummary.
*
* @param showSummary new value of showSummary
*/
public void setShowSummary(boolean showSummary) {
this.showSummary = showSummary;
}
/**
* Whether or not the nexus analyzer is enabled.
*/
private boolean nexusAnalyzerEnabled = true;
/**
* Get the value of nexusAnalyzerEnabled.
*
* @return the value of nexusAnalyzerEnabled
*/
public boolean isNexusAnalyzerEnabled() {
return nexusAnalyzerEnabled;
}
/**
* Set the value of nexusAnalyzerEnabled.
*
* @param nexusAnalyzerEnabled new value of nexusAnalyzerEnabled
*/
public void setNexusAnalyzerEnabled(boolean nexusAnalyzerEnabled) {
this.nexusAnalyzerEnabled = nexusAnalyzerEnabled;
}
/**
* The URL of the Nexus server.
*/
private String nexusUrl;
/**
* Get the value of nexusUrl.
*
* @return the value of nexusUrl
*/
public String getNexusUrl() {
return nexusUrl;
}
/**
* Set the value of nexusUrl.
*
* @param nexusUrl new value of nexusUrl
*/
public void setNexusUrl(String nexusUrl) {
this.nexusUrl = nexusUrl;
}
/**
* Whether or not the defined proxy should be used when connecting to Nexus.
*/
private boolean nexusUsesProxy = true;
/**
* Get the value of nexusUsesProxy.
*
* @return the value of nexusUsesProxy
*/
public boolean isNexusUsesProxy() {
return nexusUsesProxy;
}
/**
* Set the value of nexusUsesProxy.
*
* @param nexusUsesProxy new value of nexusUsesProxy
*/
public void setNexusUsesProxy(boolean nexusUsesProxy) {
this.nexusUsesProxy = nexusUsesProxy;
}
/**
* The database driver name; such as org.h2.Driver.
*/
private String databaseDriverName;
/**
* Get the value of databaseDriverName.
*
* @return the value of databaseDriverName
*/
public String getDatabaseDriverName() {
return databaseDriverName;
}
/**
* Set the value of databaseDriverName.
*
* @param databaseDriverName new value of databaseDriverName
*/
public void setDatabaseDriverName(String databaseDriverName) {
this.databaseDriverName = databaseDriverName;
}
/**
* The path to the database driver JAR file if it is not on the class path.
*/
private String databaseDriverPath;
/**
* Get the value of databaseDriverPath.
*
* @return the value of databaseDriverPath
*/
public String getDatabaseDriverPath() {
return databaseDriverPath;
}
/**
* Set the value of databaseDriverPath.
*
* @param databaseDriverPath new value of databaseDriverPath
*/
public void setDatabaseDriverPath(String databaseDriverPath) {
this.databaseDriverPath = databaseDriverPath;
}
/**
* The database connection string.
*/
private String connectionString;
/**
* Get the value of connectionString.
*
* @return the value of connectionString
*/
public String getConnectionString() {
return connectionString;
}
/**
* Set the value of connectionString.
*
* @param connectionString new value of connectionString
*/
public void setConnectionString(String connectionString) {
this.connectionString = connectionString;
}
/**
* The user name for connecting to the database.
*/
private String databaseUser;
/**
* Get the value of databaseUser.
*
* @return the value of databaseUser
*/
public String getDatabaseUser() {
return databaseUser;
}
/**
* Set the value of databaseUser.
*
* @param databaseUser new value of databaseUser
*/
public void setDatabaseUser(String databaseUser) {
this.databaseUser = databaseUser;
}
/**
* The password to use when connecting to the database.
*/
private String databasePassword;
/**
* Get the value of databasePassword.
*
* @return the value of databasePassword
*/
public String getDatabasePassword() {
return databasePassword;
}
/**
* Set the value of databasePassword.
*
* @param databasePassword new value of databasePassword
*/
public void setDatabasePassword(String databasePassword) {
this.databasePassword = databasePassword;
}
/**
* Additional ZIP File extensions to add analyze. This should be a comma-separated list of file extensions to treat
* like ZIP files.
*/
private String zipExtensions;
/**
* Get the value of zipExtensions.
*
* @return the value of zipExtensions
*/
public String getZipExtensions() {
return zipExtensions;
}
/**
* Set the value of zipExtensions.
*
* @param zipExtensions new value of zipExtensions
*/
public void setZipExtensions(String zipExtensions) {
this.zipExtensions = zipExtensions;
}
/**
* The url for the modified NVD CVE (1.2 schema).
*/
private String cveUrl12Modified;
/**
* Get the value of cveUrl12Modified.
*
* @return the value of cveUrl12Modified
*/
public String getCveUrl12Modified() {
return cveUrl12Modified;
}
/**
* Set the value of cveUrl12Modified.
*
* @param cveUrl12Modified new value of cveUrl12Modified
*/
public void setCveUrl12Modified(String cveUrl12Modified) {
this.cveUrl12Modified = cveUrl12Modified;
}
/**
* The url for the modified NVD CVE (2.0 schema).
*/
private String cveUrl20Modified;
/**
* Get the value of cveUrl20Modified.
*
* @return the value of cveUrl20Modified
*/
public String getCveUrl20Modified() {
return cveUrl20Modified;
}
/**
* Set the value of cveUrl20Modified.
*
* @param cveUrl20Modified new value of cveUrl20Modified
*/
public void setCveUrl20Modified(String cveUrl20Modified) {
this.cveUrl20Modified = cveUrl20Modified;
}
/**
* Base Data Mirror URL for CVE 1.2.
*/
private String cveUrl12Base;
/**
* Get the value of cveUrl12Base.
*
* @return the value of cveUrl12Base
*/
public String getCveUrl12Base() {
return cveUrl12Base;
}
/**
* Set the value of cveUrl12Base.
*
* @param cveUrl12Base new value of cveUrl12Base
*/
public void setCveUrl12Base(String cveUrl12Base) {
this.cveUrl12Base = cveUrl12Base;
}
/**
* Data Mirror URL for CVE 2.0.
*/
private String cveUrl20Base;
/**
* Get the value of cveUrl20Base.
*
* @return the value of cveUrl20Base
*/
public String getCveUrl20Base() {
return cveUrl20Base;
}
/**
* Set the value of cveUrl20Base.
*
* @param cveUrl20Base new value of cveUrl20Base
*/
public void setCveUrl20Base(String cveUrl20Base) {
this.cveUrl20Base = cveUrl20Base;
}
/**
* The path to Mono for .NET assembly analysis on non-windows systems.
*/
private String pathToMono;
/**
* Get the value of pathToMono.
*
* @return the value of pathToMono
*/
public String getPathToMono() {
return pathToMono;
}
/**
* Set the value of pathToMono.
*
* @param pathToMono new value of pathToMono
*/
public void setPathToMono(String pathToMono) {
this.pathToMono = pathToMono;
}
/**
* Executes the Dependency-Check on the dependent libraries.
*
* @return the Engine used to scan the dependencies.
* @throws org.owasp.dependencycheck.data.nvdcve.DatabaseException thrown if there is an exception connecting to the
* database
*/
private Engine executeDependencyCheck() throws DatabaseException {
populateSettings();
Engine engine = null;
engine = new Engine();
engine.setDependencies(this.dependencies);
engine.analyzeDependencies();
return engine;
}
/**
* Generates the reports for a given dependency-check engine.
*
* @param engine a dependency-check engine
* @param outDirectory the directory to write the reports to
*/
private void generateExternalReports(Engine engine, File outDirectory) {
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(this.applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
try {
r.generateReports(outDirectory.getCanonicalPath(), this.reportFormat.name());
} 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);
}
}
/**
* 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();
if (dataDirectory != null) {
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
} else {
final File jarPath = new File(DependencyCheckScanAgent.class.getProtectionDomain().getCodeSource().getLocation().getPath());
final File base = jarPath.getParentFile();
final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
final File dataDir = new File(base, sub);
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
}
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
if (proxyUrl != null && !proxyUrl.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_URL, proxyUrl);
}
if (proxyPort != null && !proxyPort.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
}
if (proxyUsername != null && !proxyUsername.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUsername);
}
if (proxyPassword != null && !proxyPassword.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
}
if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
}
if (suppressionFile != null && !suppressionFile.isEmpty()) {
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
}
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);
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);
}
if (zipExtensions != null && !zipExtensions.isEmpty()) {
Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
}
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);
}
if (pathToMono != null && !pathToMono.isEmpty()) {
Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
}
}
/**
* Executes the dependency-check and generates the report.
*
* @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if there is an exception executing the
* scan.
*/
public void execute() throws ScanAgentException {
Engine engine = null;
try {
engine = executeDependencyCheck();
generateExternalReports(engine, new File(this.reportOutputDirectory));
if (this.showSummary) {
showSummary(engine.getDependencies());
}
if (this.failBuildOnCVSS <= 10) {
checkForFailure(engine.getDependencies());
}
} catch (DatabaseException ex) {
LOGGER.log(Level.SEVERE,
"Unable to connect to the dependency-check database; analysis has stopped");
LOGGER.log(Level.FINE, "", ex);
} finally {
Settings.cleanup();
if (engine != null) {
engine.cleanup();
}
}
}
/**
* 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 org.owasp.dependencycheck.exception.ScanAgentException thrown if there is an exception executing the
* scan.
*/
private void checkForFailure(List<Dependency> dependencies) throws ScanAgentException {
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 ScanAgentException(msg);
}
}
/**
* Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries.
*
* @param dependencies a list of dependency objects
*/
private void showSummary(List<Dependency> dependencies) {
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);
}
}
}

View File

@@ -0,0 +1,13 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.agent</title>
* </head>
* <body>
* The agent package holds an agent API that can be used by other applications that have information about dependencies;
* but would rather implement something in their code directly rather then spawn a process to run the entire
* dependency-check engine. This basically provides programmatic access to running a scan.
* </body>
* </html>
*/
package org.owasp.dependencycheck.agent;

View File

@@ -17,33 +17,12 @@
*/
package org.owasp.dependencycheck.analyzer;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public abstract class AbstractAnalyzer implements Analyzer {
/**
* Utility method to help in the creation of the extensions set. This constructs a new Set that can be used in a
* final static declaration.<br/><br/>
*
* This implementation was copied from
* http://stackoverflow.com/questions/2041778/initialize-java-hashset-values-by-construction
*
* @param strings a list of strings to add to the set.
* @return a Set of strings.
*/
protected static Set<String> newHashSet(String... strings) {
final Set<String> set = new HashSet<String>();
Collections.addAll(set, strings);
return set;
}
/**
* The initialize method does nothing for this Analyzer.
*

View File

@@ -0,0 +1,229 @@
/*
* 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.util.Collections;
import java.util.HashSet;
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.dependency.Dependency;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
/**
* The base FileTypeAnalyzer that all analyzers that have specific file types they analyze should extend.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implements FileTypeAnalyzer {
//<editor-fold defaultstate="collapsed" desc="Constructor">
/**
* Base constructor that all children must call. This checks the configuration to determine if the analyzer is
* enabled.
*/
public AbstractFileTypeAnalyzer() {
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);
}
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Field definitions">
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(AbstractFileTypeAnalyzer.class.getName());
/**
* Whether the file type analyzer detected any files it needs to analyze.
*/
private boolean filesMatched = false;
/**
* Get the value of filesMatched. A flag indicating whether the scan included any file types this analyzer supports.
*
* @return the value of filesMatched
*/
protected boolean isFilesMatched() {
return filesMatched;
}
/**
* Set the value of filesMatched. A flag indicating whether the scan included any file types this analyzer supports.
*
* @param filesMatched new value of filesMatched
*/
protected void setFilesMatched(boolean filesMatched) {
this.filesMatched = filesMatched;
}
/**
* A flag indicating whether or not the analyzer is enabled.
*/
private boolean enabled = true;
/**
* Get the value of enabled.
*
* @return the value of enabled
*/
public boolean isEnabled() {
return enabled;
}
/**
* Set the value of enabled.
*
* @param enabled new value of enabled
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Abstract methods children must implement">
/**
* <p>
* Returns a list of supported file extensions. An example would be an analyzer that inspected java jar files. The
* getSupportedExtensions function would return a set with a single element "jar".</p>
*
* <p>
* <b>Note:</b> when implementing this the extensions returned MUST be lowercase.</p>
*
* @return The file extensions supported by this analyzer.
*
* <p>
* If the analyzer returns null it will not cause additional files to be analyzed but will be executed against every
* file loaded</p>
*/
protected abstract Set<String> getSupportedExtensions();
/**
* Initializes the file type analyzer.
*
* @throws Exception thrown if there is an exception during initialization
*/
protected abstract void initializeFileTypeAnalyzer() throws Exception;
/**
* 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.
*
* @param dependency the dependency to analyze
* @param engine the engine scanning
* @throws AnalysisException thrown if there is an analysis exception
*/
protected abstract void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException;
/**
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @return the key for the analyzer's enabled property
*/
protected abstract String getAnalyzerEnabledSettingKey();
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Final implementations for the Analyzer interface">
/**
* Initializes the analyzer.
*
* @throws Exception thrown if there is an exception during initialization
*/
@Override
public final void initialize() throws Exception {
if (filesMatched) {
initializeFileTypeAnalyzer();
} else {
enabled = false;
}
}
/**
* 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.
*
* @param dependency the dependency to analyze
* @param engine the engine scanning
* @throws AnalysisException thrown if there is an analysis exception
*/
@Override
public final void analyze(Dependency dependency, Engine engine) throws AnalysisException {
if (enabled) {
analyzeFileType(dependency, engine);
}
}
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support.
* @return whether or not the specified file extension is supported by this analyzer.
*/
@Override
public final boolean supportsExtension(String extension) {
if (!enabled) {
return false;
}
final Set<String> ext = getSupportedExtensions();
if (ext == null) {
final String msg = String.format("The '%s' analyzer is misconfigured and does not have any file extensions;"
+ " it will be disabled", getName());
LOGGER.log(Level.SEVERE, msg);
return false;
} else {
final boolean match = ext.contains(extension);
if (match) {
filesMatched = match;
}
return match;
}
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Static utility methods">
/**
* <p>
* Utility method to help in the creation of the extensions set. This constructs a new Set that can be used in a
* final static declaration.</p>
*
* <p>
* This implementation was copied from
* http://stackoverflow.com/questions/2041778/initialize-java-hashset-values-by-construction</p>
*
* @param strings a list of strings to add to the set.
* @return a Set of strings.
*/
protected static Set<String> newHashSet(String... strings) {
final Set<String> set = new HashSet<String>();
Collections.addAll(set, strings);
return set;
}
//</editor-fold>
}

View File

@@ -18,13 +18,21 @@
package org.owasp.dependencycheck.analyzer;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.suppression.SuppressionParseException;
import org.owasp.dependencycheck.suppression.SuppressionParser;
import org.owasp.dependencycheck.suppression.SuppressionRule;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.Settings;
/**
@@ -34,6 +42,11 @@ import org.owasp.dependencycheck.utils.Settings;
*/
public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
/**
* The Logger for use throughout the class
*/
private static final Logger LOGGER = Logger.getLogger(AbstractSuppressionAnalyzer.class.getName());
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
* Returns a list of file EXTENSIONS supported by this analyzer.
@@ -44,17 +57,6 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
return null;
}
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support.
* @return whether or not the specified file extension is supported by this analyzer.
*/
@Override
public boolean supportsExtension(String extension) {
return true;
}
//</editor-fold>
/**
* The initialize method loads the suppression XML file.
@@ -66,6 +68,7 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
super.initialize();
loadSuppressionData();
}
/**
* The list of suppression rules
*/
@@ -95,18 +98,75 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
* @throws SuppressionParseException thrown if the XML cannot be parsed.
*/
private void loadSuppressionData() throws SuppressionParseException {
final File file = Settings.getFile(Settings.KEYS.SUPPRESSION_FILE);
if (file != null) {
final SuppressionParser parser = new SuppressionParser();
try {
rules = parser.parseSuppressionRules(file);
} catch (SuppressionParseException ex) {
final String msg = String.format("Unable to parse suppression xml file '%s'", file.getPath());
Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING, ex.getMessage());
Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.FINE, null, ex);
throw ex;
final String suppressionFilePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE);
if (suppressionFilePath == null) {
return;
}
File file = null;
boolean deleteTempFile = false;
try {
final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
if (uriRx.matcher(suppressionFilePath).matches()) {
deleteTempFile = true;
file = FileUtils.getTempFile("suppression", "xml");
final URL url = new URL(suppressionFilePath);
try {
Downloader.fetchFile(url, file, false);
} catch (DownloadFailedException ex) {
Downloader.fetchFile(url, file, true);
}
} else {
file = new File(suppressionFilePath);
if (!file.exists()) {
final InputStream suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath);
if (suppressionsFromClasspath != null) {
deleteTempFile = true;
file = FileUtils.getTempFile("suppression", "xml");
try {
org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file);
} catch (IOException ex) {
throwSuppressionParseException("Unable to locate suppressions file in classpath", ex);
}
}
}
}
if (file != null) {
final SuppressionParser parser = new SuppressionParser();
try {
rules = parser.parseSuppressionRules(file);
LOGGER.log(Level.FINE, rules.size() + " suppression rules were loaded.");
} catch (SuppressionParseException ex) {
final String msg = String.format("Unable to parse suppression xml file '%s'", file.getPath());
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.WARNING, ex.getMessage());
LOGGER.log(Level.FINE, "", ex);
throw ex;
}
}
} catch (DownloadFailedException ex) {
throwSuppressionParseException("Unable to fetch the configured suppression file", ex);
} catch (MalformedURLException ex) {
throwSuppressionParseException("Configured suppression file has an invalid URL", ex);
} catch (IOException ex) {
throwSuppressionParseException("Unable to create temp file for suppressions", ex);
} finally {
if (deleteTempFile && file != null) {
FileUtils.delete(file);
}
}
}
/**
* Utility method to throw parse exceptions.
*
* @param message the exception message
* @param exception the cause of the exception
* @throws SuppressionParseException throws the generated SuppressionParseException
*/
private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException {
LOGGER.log(Level.WARNING, message);
LOGGER.log(Level.FINE, "", exception);
throw new SuppressionParseException(message, exception);
}
}

View File

@@ -17,8 +17,8 @@
*/
package org.owasp.dependencycheck.analyzer;
import java.util.Set;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
/**
@@ -41,22 +41,6 @@ public interface Analyzer {
*/
void analyze(Dependency dependency, Engine engine) throws AnalysisException;
/**
* <p>
* Returns a list of supported file extensions. An example would be an analyzer that inspected java jar files. The
* getSupportedExtensions function would return a set with a single element "jar".</p>
*
* <p>
* <b>Note:</b> when implementing this the extensions returned MUST be lowercase.</p>
*
* @return The file extensions supported by this analyzer.
*
* <p>
* If the analyzer returns null it will not cause additional files to be analyzed but will be executed against every
* file loaded</p>
*/
Set<String> getSupportedExtensions();
/**
* Returns the name of the analyzer.
*
@@ -64,14 +48,6 @@ public interface Analyzer {
*/
String getName();
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support.
* @return whether or not the specified file extension is supported by this analyzer.
*/
boolean supportsExtension(String extension);
/**
* Returns the phase that the analyzer is intended to run in.
*

View File

@@ -21,15 +21,13 @@ import java.util.Iterator;
import java.util.ServiceLoader;
/**
* The Analyzer Service Loader. This class loads all services that implement
* org.owasp.dependencycheck.analyzer.Analyzer.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class AnalyzerService {
public class AnalyzerService {
/**
* The analyzer service singleton.
*/
private static AnalyzerService service;
/**
* The service loader for analyzers.
*/
@@ -37,21 +35,11 @@ public final class AnalyzerService {
/**
* Creates a new instance of AnalyzerService.
*/
private AnalyzerService() {
loader = ServiceLoader.load(Analyzer.class);
}
/**
* Retrieve the singleton instance of AnalyzerService.
*
* @return a singleton AnalyzerService.
* @param classLoader the ClassLoader to use when dynamically loading Analyzer and Update services
*/
public static synchronized AnalyzerService getInstance() {
if (service == null) {
service = new AnalyzerService();
}
return service;
public AnalyzerService(ClassLoader classLoader) {
loader = ServiceLoader.load(Analyzer.class, classLoader);
}
/**

View File

@@ -25,6 +25,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -38,9 +39,11 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.compressors.CompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipUtils;
import org.h2.store.fs.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.Settings;
/**
@@ -50,8 +53,12 @@ import org.owasp.dependencycheck.utils.Settings;
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(ArchiveAnalyzer.class.getName());
/**
* The buffer size to use when extracting files from the archive.
*/
@@ -72,6 +79,7 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
* Tracks the current scan/extraction depth for nested archives.
*/
private int scanDepth = 0;
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
* The name of the analyzer.
@@ -82,15 +90,30 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL;
/**
* The set of file extensions supported by this analyzer.
* The set of things we can handle with Zip methods
*/
private static final Set<String> EXTENSIONS = newHashSet("zip", "ear", "war", "tar", "gz", "tgz");
private static final Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "jar", "sar", "apk", "nupkg");
/**
* The set of file extensions supported by this analyzer. Note for developers, any additions to this list will need
* to be explicitly handled in extractFiles().
*/
private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz");
static {
final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
if (additionalZipExt != null) {
final HashSet ext = new HashSet<String>(Arrays.asList(additionalZipExt));
ZIPPABLES.addAll(ext);
}
EXTENSIONS.addAll(ZIPPABLES);
}
/**
* Returns a list of file EXTENSIONS supported by this analyzer.
*
* @return a list of file EXTENSIONS supported by this analyzer.
*/
@Override
public Set<String> getSupportedExtensions() {
return EXTENSIONS;
}
@@ -100,44 +123,40 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support.
* @return whether or not the specified file extension is supported by this analyzer.
*/
public boolean supportsExtension(String extension) {
return EXTENSIONS.contains(extension);
}
/**
* Returns the phase that the analyzer is intended to run in.
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
//</editor-fold>
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
*
* @return the analyzer's enabled property setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_ARCHIVE_ENABLED;
}
/**
* The initialize method does nothing for this Analyzer.
*
* @throws Exception is thrown if there is an exception deleting or creating temporary files
*/
@Override
public void initialize() throws Exception {
public void initializeFileTypeAnalyzer() throws Exception {
final File baseDir = Settings.getTempDirectory();
if (!baseDir.exists()) {
if (!baseDir.mkdirs()) {
final String msg = String.format("Unable to make a temporary folder '%s'", baseDir.getPath());
throw new AnalysisException(msg);
}
}
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
@@ -150,14 +169,18 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
}
/**
* The close method does nothing for this Analyzer.
* The close method deletes any temporary files and directories created during analysis.
*
* @throws Exception thrown if there is an exception deleting temporary files
*/
@Override
public void close() throws Exception {
if (tempFileLocation != null && tempFileLocation.exists()) {
FileUtils.deleteRecursive(tempFileLocation.getAbsolutePath(), true);
LOGGER.log(Level.FINE, "Attempting to delete temporary files");
final boolean success = FileUtils.delete(tempFileLocation);
if (!success) {
LOGGER.log(Level.WARNING, "Failed to delete some temporary files, see the log for more details");
}
}
}
@@ -170,7 +193,7 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
* @throws AnalysisException thrown if there is an analysis exception
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
final File f = new File(dependency.getActualFilePath());
final File tmpDir = getNextTempDirectory();
extractFiles(f, tmpDir, engine);
@@ -246,35 +269,35 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
try {
fis = new FileInputStream(archive);
} catch (FileNotFoundException ex) {
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.INFO, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new AnalysisException("Archive file was not found.", ex);
}
final String archiveExt = org.owasp.dependencycheck.utils.FileUtils.getFileExtension(archive.getName()).toLowerCase();
final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase();
try {
if ("zip".equals(archiveExt) || "war".equals(archiveExt) || "ear".equals(archiveExt)) {
if (ZIPPABLES.contains(archiveExt)) {
extractArchive(new ZipArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
} else if ("tar".equals(archiveExt)) {
extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
} else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) {
final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName());
final String uncompressedExt = org.owasp.dependencycheck.utils.FileUtils.getFileExtension(uncompressedName).toLowerCase();
final String uncompressedExt = FileUtils.getFileExtension(uncompressedName).toLowerCase();
if (engine.supportsExtension(uncompressedExt)) {
decompressFile(new GzipCompressorInputStream(new BufferedInputStream(fis)), new File(destination, uncompressedName));
}
}
} catch (ArchiveExtractionException ex) {
final String msg = String.format("Exception extracting archive '%s'.", archive.getName());
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, null, ex);
} catch (IOException ex) {
final String msg = String.format("Exception reading archive '%s'.", archive.getName());
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, null, ex);
} finally {
try {
fis.close();
} catch (IOException ex) {
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}
@@ -301,7 +324,7 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
}
} else {
final File file = new File(destination, entry.getName());
final String ext = org.owasp.dependencycheck.utils.FileUtils.getFileExtension(file.getName());
final String ext = FileUtils.getFileExtension(file.getName());
if (engine.supportsExtension(ext)) {
BufferedOutputStream bos = null;
FileOutputStream fos;
@@ -322,13 +345,11 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
}
bos.flush();
} catch (FileNotFoundException ex) {
Logger.getLogger(ArchiveAnalyzer.class
.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
final String msg = String.format("Unable to find file '%s'.", file.getName());
throw new AnalysisException(msg, ex);
} catch (IOException ex) {
Logger.getLogger(ArchiveAnalyzer.class
.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
throw new AnalysisException(msg, ex);
} finally {
@@ -336,8 +357,7 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
try {
bos.close();
} catch (IOException ex) {
Logger.getLogger(ArchiveAnalyzer.class
.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}
@@ -353,7 +373,7 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
try {
input.close();
} catch (IOException ex) {
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}
@@ -376,17 +396,17 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
out.write(buffer, 0, n);
}
} catch (FileNotFoundException ex) {
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new ArchiveExtractionException(ex);
} catch (IOException ex) {
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new ArchiveExtractionException(ex);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ex) {
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}

View File

@@ -0,0 +1,318 @@
/*
* 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) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.utils.Settings;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
/**
* Analyzer for getting company, product, and version information from a .NET assembly.
*
* @author colezlaw
*
*/
public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The analyzer name
*/
private static final String ANALYZER_NAME = "Assembly Analyzer";
/**
* The analysis phase
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
/**
* The list of supported extensions
*/
private static final Set<String> SUPPORTED_EXTENSIONS = newHashSet("dll", "exe");
/**
* The temp value for GrokAssembly.exe
*/
private File grokAssemblyExe = null;
/**
* The DocumentBuilder for parsing the XML
*/
private DocumentBuilder builder;
/**
* Logger
*/
private static final Logger LOGGER = Logger.getLogger(AssemblyAnalyzer.class.getName());
/**
* Builds the beginnings of a List for ProcessBuilder
*
* @return the list of arguments to begin populating the ProcessBuilder
*/
private List<String> buildArgumentList() {
// Use file.separator as a wild guess as to whether this is Windows
final List<String> args = new ArrayList<String>();
if (!"\\".equals(System.getProperty("file.separator"))) {
if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) {
args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH));
} else {
args.add("mono");
}
}
args.add(grokAssemblyExe.getPath());
return args;
}
/**
* Performs the analysis on a single Dependency.
*
* @param dependency the dependency to analyze
* @param engine the engine to perform the analysis under
* @throws AnalysisException if anything goes sideways
*/
@Override
public void analyzeFileType(Dependency dependency, Engine engine)
throws AnalysisException {
if (grokAssemblyExe == null) {
LOGGER.warning("GrokAssembly didn't get deployed");
return;
}
final List<String> args = buildArgumentList();
args.add(dependency.getActualFilePath());
final ProcessBuilder pb = new ProcessBuilder(args);
BufferedReader rdr = null;
try {
final Process proc = pb.start();
// Try evacuating the error stream
rdr = new BufferedReader(new InputStreamReader(proc.getErrorStream(), "UTF-8"));
String line = null;
while (rdr.ready() && (line = rdr.readLine()) != null) {
LOGGER.log(Level.WARNING, "Error from GrokAssembly: {0}", line);
}
int rc = 0;
final Document doc = builder.parse(proc.getInputStream());
final XPath xpath = XPathFactory.newInstance().newXPath();
// First, see if there was an error
final String error = xpath.evaluate("/assembly/error", doc);
if (error != null && !"".equals(error)) {
throw new AnalysisException(error);
}
final String version = xpath.evaluate("/assembly/version", doc);
if (version != null) {
dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version",
version, Confidence.HIGHEST));
}
final String vendor = xpath.evaluate("/assembly/company", doc);
if (vendor != null) {
dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor",
vendor, Confidence.HIGH));
}
final String product = xpath.evaluate("/assembly/product", doc);
if (product != null) {
dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product",
product, Confidence.HIGH));
}
try {
rc = proc.waitFor();
} catch (InterruptedException ie) {
return;
}
if (rc == 3) {
LOGGER.log(Level.INFO, "{0} is not a valid assembly", dependency.getActualFilePath());
return;
} else if (rc != 0) {
LOGGER.log(Level.WARNING, "Return code {0} from GrokAssembly", rc);
}
} catch (IOException ioe) {
throw new AnalysisException(ioe);
} catch (SAXException saxe) {
throw new AnalysisException("Couldn't parse GrokAssembly result", saxe);
} catch (XPathExpressionException xpe) {
// This shouldn't happen
throw new AnalysisException(xpe);
} finally {
if (rdr != null) {
try {
rdr.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, "ignore", ex);
}
}
}
}
/**
* Initialize the analyzer. In this case, extract GrokAssembly.exe to a temporary location.
*
* @throws Exception if anything goes wrong
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
final File tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory());
FileOutputStream fos = null;
InputStream is = null;
try {
fos = new FileOutputStream(tempFile);
is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe");
final byte[] buff = new byte[4096];
int bread = -1;
while ((bread = is.read(buff)) >= 0) {
fos.write(buff, 0, bread);
}
grokAssemblyExe = tempFile;
// Set the temp file to get deleted when we're done
grokAssemblyExe.deleteOnExit();
LOGGER.log(Level.FINE, "Extracted GrokAssembly.exe to {0}", grokAssemblyExe.getPath());
} catch (IOException ioe) {
LOGGER.log(Level.WARNING, "Could not extract GrokAssembly.exe: {0}", ioe.getMessage());
throw new AnalysisException("Could not extract GrokAssembly.exe", ioe);
} finally {
if (fos != null) {
try {
fos.close();
} catch (Throwable e) {
LOGGER.fine("Error closing output stream");
}
}
if (is != null) {
try {
is.close();
} catch (Throwable e) {
LOGGER.fine("Error closing input stream");
}
}
}
// Now, need to see if GrokAssembly actually runs from this location.
final List<String> args = buildArgumentList();
BufferedReader rdr = null;
try {
final ProcessBuilder pb = new ProcessBuilder(args);
final Process p = pb.start();
// Try evacuating the error stream
rdr = new BufferedReader(new InputStreamReader(p.getErrorStream(), "UTF-8"));
while (rdr.ready() && rdr.readLine() != null) {
// We expect this to complain
}
final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream());
final XPath xpath = XPathFactory.newInstance().newXPath();
final String error = xpath.evaluate("/assembly/error", doc);
if (p.waitFor() != 1 || error == null || "".equals(error)) {
LOGGER.warning("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details.");
LOGGER.fine("GrokAssembly.exe is not working properly");
grokAssemblyExe = null;
throw new AnalysisException("Could not execute .NET AssemblyAnalyzer");
}
} catch (Throwable e) {
if (e instanceof AnalysisException) {
throw (AnalysisException) e;
} else {
LOGGER.warning("An error occured with the .NET AssemblyAnalyzer; "
+ "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details.");
LOGGER.log(Level.FINE, "Could not execute GrokAssembly {0}", e.getMessage());
throw new AnalysisException("An error occured with the .NET AssemblyAnalyzer", e);
}
} finally {
if (rdr != null) {
try {
rdr.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, "ignore", ex);
}
}
}
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
@Override
public void close() throws Exception {
super.close();
try {
if (grokAssemblyExe != null && !grokAssemblyExe.delete()) {
grokAssemblyExe.deleteOnExit();
}
} catch (SecurityException se) {
LOGGER.fine("Can't delete temporary GrokAssembly.exe");
}
}
/**
* Gets the set of extensions supported by this analyzer.
*
* @return the list of supported extensions
*/
@Override
public Set<String> getSupportedExtensions() {
return SUPPORTED_EXTENSIONS;
}
/**
* Gets this analyzer's name.
*
* @return the analyzer name
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns the phase this analyzer runs under.
*
* @return the phase this runs under
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
*
* @return the analyzer's enabled property setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED;
}
}

View File

@@ -33,6 +33,7 @@ import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex;
import org.owasp.dependencycheck.data.cpe.Fields;
import org.owasp.dependencycheck.data.cpe.IndexEntry;
@@ -56,7 +57,10 @@ import org.owasp.dependencycheck.utils.DependencyVersionUtil;
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class CPEAnalyzer implements Analyzer {
/**
* The Logger.
*/
private static final Logger LOGGER = Logger.getLogger(CPEAnalyzer.class.getName());
/**
* The maximum number of query results to return.
*/
@@ -86,6 +90,36 @@ public class CPEAnalyzer implements Analyzer {
*/
private CveDB cve;
/**
* Returns the name of this analyzer.
*
* @return the name of this analyzer.
*/
@Override
public String getName() {
return "CPE Analyzer";
}
/**
* Returns the analysis phase that this analyzer should run in.
*
* @return the analysis phase that this analyzer should run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return AnalysisPhase.IDENTIFIER_ANALYSIS;
}
/**
* Creates the CPE Lucene Index.
*
* @throws Exception is thrown if there is an issue opening the index.
*/
@Override
public void initialize() throws Exception {
this.open();
}
/**
* Opens the data source.
*
@@ -94,15 +128,15 @@ public class CPEAnalyzer implements Analyzer {
* by another process.
*/
public void open() throws IOException, DatabaseException {
Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.FINE, "Opening the CVE Database");
LOGGER.log(Level.FINE, "Opening the CVE Database");
cve = new CveDB();
cve.open();
Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.FINE, "Creating the Lucene CPE Index");
LOGGER.log(Level.FINE, "Creating the Lucene CPE Index");
cpe = CpeMemoryIndex.getInstance();
try {
cpe.open(cve);
} catch (IndexException ex) {
Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.FINE, "IndexException", ex);
LOGGER.log(Level.FINE, "IndexException", ex);
throw new DatabaseException(ex);
}
}
@@ -460,57 +494,6 @@ public class CPEAnalyzer implements Analyzer {
}
}
/**
* Returns true because this analyzer supports all dependency types.
*
* @return true.
*/
@Override
public Set<String> getSupportedExtensions() {
return null;
}
/**
* Returns the name of this analyzer.
*
* @return the name of this analyzer.
*/
@Override
public String getName() {
return "CPE Analyzer";
}
/**
* Returns true because this analyzer supports all dependency types.
*
* @param extension the file extension of the dependency being analyzed.
* @return true.
*/
@Override
public boolean supportsExtension(String extension) {
return true;
}
/**
* Returns the analysis phase that this analyzer should run in.
*
* @return the analysis phase that this analyzer should run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return AnalysisPhase.IDENTIFIER_ANALYSIS;
}
/**
* Opens the CPE Lucene Index.
*
* @throws Exception is thrown if there is an issue opening the index.
*/
@Override
public void initialize() throws Exception {
this.open();
}
/**
* Retrieves a list of CPE values from the CveDB based on the vendor and product passed in. The list is then
* validated to find only CPEs that are valid for the given dependency. It is possible that the CPE identified is a

View File

@@ -17,6 +17,7 @@
*/
package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.suppression.SuppressionRule;
@@ -29,7 +30,7 @@ import org.owasp.dependencycheck.suppression.SuppressionRule;
*/
public class CpeSuppressionAnalyzer extends AbstractSuppressionAnalyzer {
//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
* The name of the analyzer.
*/

View File

@@ -27,6 +27,7 @@ import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.utils.DependencyVersion;
@@ -45,6 +46,11 @@ import org.owasp.dependencycheck.utils.LogUtils;
*/
public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Analyzer {
/**
* The Logger.
*/
private static final Logger LOGGER = Logger.getLogger(DependencyBundlingAnalyzer.class.getName());
//<editor-fold defaultstate="collapsed" desc="Constants and Member Variables">
/**
* A pattern for obtaining the first part of a filename.
@@ -56,10 +62,6 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
private boolean analyzed = false;
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
* The set of file extensions supported by this analyzer.
*/
private static final Set<String> EXTENSIONS = null;
/**
* The name of the analyzer.
*/
@@ -69,15 +71,6 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_FINDING_ANALYSIS;
/**
* Returns a list of file EXTENSIONS supported by this analyzer.
*
* @return a list of file EXTENSIONS supported by this analyzer.
*/
public Set<String> getSupportedExtensions() {
return EXTENSIONS;
}
/**
* Returns the name of the analyzer.
*
@@ -87,16 +80,6 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
return ANALYZER_NAME;
}
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support
* @return whether or not the specified file extension is supported by this analyzer.
*/
public boolean supportsExtension(String extension) {
return true;
}
/**
* Returns the phase that the analyzer is intended to run in.
*
@@ -128,18 +111,18 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
while (subIterator.hasNext()) {
final Dependency nextDependency = subIterator.next();
if (isShadedJar(dependency, nextDependency)) {
if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
dependenciesToRemove.add(dependency);
} else {
dependenciesToRemove.add(nextDependency);
}
} else if (hashesMatch(dependency, nextDependency)) {
if (hashesMatch(dependency, nextDependency)) {
if (isCore(dependency, nextDependency)) {
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
} else {
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
}
} else if (isShadedJar(dependency, nextDependency)) {
if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
dependenciesToRemove.add(dependency);
} else {
dependenciesToRemove.add(nextDependency);
}
} else if (cpeIdentifiersMatch(dependency, nextDependency)
&& hasSameBasePath(dependency, nextDependency)
&& fileNameMatch(dependency, nextDependency)) {
@@ -292,7 +275,7 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
if (LogUtils.isVerboseLoggingEnabled()) {
final String msg = String.format("IdentifiersMatch=%s (%s, %s)", matches, dependency1.getFileName(), dependency2.getFileName());
Logger.getLogger(DependencyBundlingAnalyzer.class.getName()).log(Level.FINE, msg);
LOGGER.log(Level.FINE, msg);
}
return matches;
}
@@ -363,13 +346,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
* be shorter:
* axis2-saaj-1.4.1.jar
* axis2-1.4.1.jar <-----
* axis2-kernal-1.4.1.jar
* axis2-kernel-1.4.1.jar
*/
returnVal = leftName.length() <= rightName.length();
}
if (LogUtils.isVerboseLoggingEnabled()) {
final String msg = String.format("IsCore=%s (%s, %s)", returnVal, left.getFileName(), right.getFileName());
Logger.getLogger(DependencyBundlingAnalyzer.class.getName()).log(Level.FINE, msg);
LOGGER.log(Level.FINE, msg);
}
return returnVal;
}

View File

@@ -30,6 +30,7 @@ import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
@@ -41,11 +42,11 @@ import org.owasp.dependencycheck.dependency.VulnerableSoftware;
*/
public class FalsePositiveAnalyzer extends AbstractAnalyzer {
//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
/**
* The set of file extensions supported by this analyzer.
* The Logger.
*/
private static final Set<String> EXTENSIONS = null;
private static final Logger LOGGER = Logger.getLogger(FalsePositiveAnalyzer.class.getName());
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
* The name of the analyzer.
*/
@@ -55,15 +56,6 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_IDENTIFIER_ANALYSIS;
/**
* Returns a list of file EXTENSIONS supported by this analyzer.
*
* @return a list of file EXTENSIONS supported by this analyzer.
*/
public Set<String> getSupportedExtensions() {
return EXTENSIONS;
}
/**
* Returns the name of the analyzer.
*
@@ -73,16 +65,6 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
return ANALYZER_NAME;
}
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support
* @return whether or not the specified file extension is supported by this analyzer.
*/
public boolean supportsExtension(String extension) {
return true;
}
/**
* Returns the phase that the analyzer is intended to run in.
*
@@ -154,8 +136,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
final String nextVersion = nextCpe.getVersion();
if (currentVersion == null && nextVersion == null) {
//how did we get here?
Logger.getLogger(FalsePositiveAnalyzer.class
.getName()).log(Level.FINE, "currentVersion and nextVersion are both null?");
LOGGER.log(Level.FINE, "currentVersion and nextVersion are both null?");
} else if (currentVersion == null && nextVersion != null) {
dependency.getIdentifiers().remove(currentId);
} else if (nextVersion == null && currentVersion != null) {
@@ -178,7 +159,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
* Regex to identify core java libraries and a few other commonly misidentified ones.
*/
public static final Pattern CORE_JAVA = Pattern.compile("^cpe:/a:(sun|oracle|ibm):(j2[ems]e|"
+ "java(_platfrom_micro_edition|_runtime_environment|_se|virtual_machine|se_development_kit|fx)?|"
+ "java(_platform_micro_edition|_runtime_environment|_se|virtual_machine|se_development_kit|fx)?|"
+ "jdk|jre|jsf|jsse)($|:.*)");
/**
* Regex to identify core java library files. This is currently incomplete.
@@ -201,7 +182,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
itr.remove();
}
//replacecd with the regex above.
//replaced with the regex above.
// if (("cpe:/a:sun:java".equals(i.getValue())
// || "cpe:/a:oracle:java".equals(i.getValue())
// || "cpe:/a:ibm:java".equals(i.getValue())
@@ -239,7 +220,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
try {
cpe.parseName(value);
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(FalsePositiveAnalyzer.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
return null;
}
return cpe;
@@ -264,7 +245,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
//Set<Evidence> artifactId = dependency.getVendorEvidence().getEvidence("pom", "artifactid");
while (itr.hasNext()) {
final Identifier i = itr.next();
//TODO move this startswith expression to a configuration file?
//TODO move this startsWith expression to a configuration file?
if ("cpe".equals(i.getType())) {
if ((i.getValue().matches(".*c\\+\\+.*")
|| i.getValue().startsWith("cpe:/a:jquery:jquery")
@@ -281,6 +262,12 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
} else if (i.getValue().startsWith("cpe:/a:apache:maven")
&& !dependency.getFileName().toLowerCase().matches("maven-core-[\\d\\.]+\\.jar")) {
itr.remove();
} else if (i.getValue().startsWith("cpe:/a:m-core:m-core")
&& !dependency.getEvidenceUsed().containsUsedString("m-core")) {
itr.remove();
} else if (i.getValue().startsWith("cpe:/a:jboss:jboss")
&& !dependency.getFileName().toLowerCase().matches("jboss-[\\d\\.]+(GA)?\\.jar")) {
itr.remove();
}
}
}
@@ -353,8 +340,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
newCpe4,
String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe4, "UTF-8")));
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(FalsePositiveAnalyzer.class
.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
}
}
}

View File

@@ -18,8 +18,8 @@
package org.owasp.dependencycheck.analyzer;
import java.io.File;
import java.util.Set;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.DependencyVersion;
@@ -33,7 +33,7 @@ import org.owasp.dependencycheck.utils.DependencyVersionUtil;
*/
public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
* The name of the analyzer.
*/
@@ -42,19 +42,6 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
/**
* The set of file extensions supported by this analyzer.
*/
private static final Set<String> EXTENSIONS = null;
/**
* Returns a list of file EXTENSIONS supported by this analyzer.
*
* @return a list of file EXTENSIONS supported by this analyzer.
*/
public Set<String> getSupportedExtensions() {
return EXTENSIONS;
}
/**
* Returns the name of the analyzer.
@@ -65,16 +52,6 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
return ANALYZER_NAME;
}
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support.
* @return whether or not the specified file extension is supported by this analyzer.
*/
public boolean supportsExtension(String extension) {
return true;
}
/**
* Returns the phase that the analyzer is intended to run in.
*

View File

@@ -0,0 +1,34 @@
/*
* 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;
/**
* An Analyzer that scans specific file types.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public interface FileTypeAnalyzer extends Analyzer {
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support.
* @return whether or not the specified file extension is supported by this analyzer.
*/
boolean supportsExtension(String extension);
}

View File

@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
@@ -31,7 +32,7 @@ import org.owasp.dependencycheck.dependency.Evidence;
*/
public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
* The name of the analyzer.
*/
@@ -40,44 +41,23 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_IDENTIFIER_ANALYSIS;
/**
* The set of file extensions supported by this analyzer.
*/
private static final Set<String> EXTENSIONS = null;
/**
* Returns a list of file EXTENSIONS supported by this analyzer.
*
* @return a list of file EXTENSIONS supported by this analyzer.
*/
public Set<String> getSupportedExtensions() {
return EXTENSIONS;
}
/**
* Returns the name of the analyzer.
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support.
* @return whether or not the specified file extension is supported by this analyzer.
*/
public boolean supportsExtension(String extension) {
return true;
}
/**
* Returns the phase that the analyzer is intended to run in.
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}

View File

@@ -25,6 +25,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
@@ -53,9 +54,9 @@ import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;
import org.h2.store.fs.FileUtils;
import org.jsoup.Jsoup;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
@@ -64,6 +65,7 @@ import org.owasp.dependencycheck.jaxb.pom.generated.License;
import org.owasp.dependencycheck.jaxb.pom.generated.Model;
import org.owasp.dependencycheck.jaxb.pom.generated.Organization;
import org.owasp.dependencycheck.jaxb.pom.generated.Parent;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.NonClosingStream;
import org.owasp.dependencycheck.utils.Settings;
import org.xml.sax.InputSource;
@@ -77,9 +79,13 @@ import org.xml.sax.XMLReader;
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
public class JarAnalyzer extends AbstractFileTypeAnalyzer {
//<editor-fold defaultstate="collapsed" desc="Constants and Member Variables">
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(JarAnalyzer.class.getName());
/**
* The buffer size to use when extracting files from the archive.
*/
@@ -109,9 +115,15 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
"buildjdk",
"ant-version",
"antversion",
"dynamicimportpackage",
"dynamicimport-package",
"dynamic-importpackage",
"dynamic-import-package",
"import-package",
"ignore-package",
"export-package",
"importpackage",
"ignorepackage",
"exportpackage",
"sealed",
"manifest-version",
@@ -123,7 +135,10 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
"tool",
"bundle-manifestversion",
"bundlemanifestversion",
"include-resource");
"include-resource",
"embed-dependency",
"ipojo-components",
"ipojo-extension");
/**
* item in some manifest, should be considered medium confidence.
*/
@@ -158,10 +173,11 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
final JAXBContext jaxbContext = JAXBContext.newInstance("org.owasp.dependencycheck.jaxb.pom.generated");
pomUnmarshaller = jaxbContext.createUnmarshaller();
} catch (JAXBException ex) { //guess we will just have a null pointer exception later...
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.SEVERE, "Unable to load parser. See the log for more details.");
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, "Unable to load parser. See the log for more details.");
LOGGER.log(Level.FINE, null, ex);
}
}
//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
/**
* The name of the analyzer.
@@ -181,6 +197,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
*
* @return a list of file EXTENSIONS supported by this analyzer.
*/
@Override
public Set<String> getSupportedExtensions() {
return EXTENSIONS;
}
@@ -190,20 +207,11 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support.
* @return whether or not the specified file extension is supported by this analyzer.
*/
public boolean supportsExtension(String extension) {
return EXTENSIONS.contains(extension);
}
/**
* Returns the phase that the analyzer is intended to run in.
*
@@ -214,6 +222,16 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
}
//</editor-fold>
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
*
* @return the analyzer's enabled property setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_JAR_ENABLED;
}
/**
* Loads a specified JAR file and collects information from the manifest and checksums to identify the correct CPE
* information.
@@ -223,7 +241,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
* @throws AnalysisException is thrown if there is an error reading the JAR file.
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
try {
final ArrayList<ClassNameInformation> classNames = collectClassNames(dependency);
final String fileName = dependency.getFileName().toLowerCase();
@@ -260,10 +278,9 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
jar = new JarFile(dependency.getActualFilePath());
} catch (IOException ex) {
final String msg = String.format("Unable to read JarFile '%s'.", dependency.getActualFilePath());
final AnalysisException ax = new AnalysisException(msg, ex);
dependency.getAnalysisExceptions().add(ax);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
//final AnalysisException ax = new AnalysisException(msg, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "", ex);
return false;
}
List<String> pomEntries;
@@ -271,10 +288,9 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
pomEntries = retrievePomListing(jar);
} catch (IOException ex) {
final String msg = String.format("Unable to read Jar file entries in '%s'.", dependency.getActualFilePath());
final AnalysisException ax = new AnalysisException(msg, ex);
dependency.getAnalysisExceptions().add(ax);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.INFO, msg, ex);
//final AnalysisException ax = new AnalysisException(msg, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, msg, ex);
return false;
}
if (pomEntries.isEmpty()) {
@@ -285,7 +301,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
try {
pomProperties = retrievePomProperties(path, jar);
} catch (IOException ex) {
Logger.getLogger(JarAnalyzer.class.getName()).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);
}
Model pom = null;
try {
@@ -313,7 +329,9 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
foundSomething |= setPomEvidence(dependency, pom, pomProperties, classes);
}
} catch (AnalysisException ex) {
dependency.addAnalysisException(ex);
final String msg = String.format("An error occured while analyzing '%s'.", dependency.getActualFilePath());
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "", ex);
}
}
return foundSomething;
@@ -346,7 +364,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
*
* @param jar the JarFile to search
* @return a list of pom.xml entries
* @throws IOException thrown if there is an exception reading a JarEntryf
* @throws IOException thrown if there is an exception reading a JarEntry
*/
private List<String> retrievePomListing(final JarFile jar) throws IOException {
final List<String> pomEntries = new ArrayList<String>();
@@ -390,13 +408,13 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
bos.flush();
dependency.setActualFilePath(file.getAbsolutePath());
} catch (IOException ex) {
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.SEVERE, null, ex);
final String msg = String.format("An error occurred reading '%s' from '%s'.", path, dependency.getFilePath());
LOGGER.warning(msg);
LOGGER.log(Level.SEVERE, "", ex);
} finally {
try {
input.close();
} catch (IOException ex) {
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.SEVERE, null, ex);
}
closeStream(bos);
closeStream(fos);
closeStream(input);
}
Model model = null;
FileInputStream fis = null;
@@ -408,31 +426,55 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
model = readPom(source);
} catch (FileNotFoundException ex) {
final String msg = String.format("Unable to parse pom '%s' in jar '%s' (File Not Found)", path, jar.getName());
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "", ex);
throw new AnalysisException(ex);
} catch (UnsupportedEncodingException ex) {
final String msg = String.format("Unable to parse pom '%s' in jar '%s' (IO Exception)", path, jar.getName());
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "", ex);
throw new AnalysisException(ex);
} catch (AnalysisException ex) {
final String msg = String.format("Unable to parse pom '%s' in jar '%s'", path, jar.getName());
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "", ex);
throw ex;
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINEST, null, ex);
}
}
closeStream(fis);
}
return model;
}
/**
* Silently closes an input stream ignoring errors.
*
* @param stream an input stream to close
*/
private void closeStream(InputStream stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, null, ex);
}
}
}
/**
* Silently closes an output stream ignoring errors.
*
* @param stream an output stream to close
*/
private void closeStream(OutputStream stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, null, ex);
}
}
}
/**
* Retrieves the specified POM from a jar file and converts it to a Model.
*
@@ -454,21 +496,18 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
model = readPom(source);
} catch (SecurityException ex) {
final String msg = String.format("Unable to parse pom '%s' in jar '%s'; invalid signature", path, jar.getName());
Logger
.getLogger(JarAnalyzer.class
.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class
.getName()).log(Level.FINE, null, ex);
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' in jar '%s' (IO Exception)", path, jar.getName());
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
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' in jar '%s'", path, jar.getName());
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "", ex);
throw new AnalysisException(ex);
}
}
@@ -575,43 +614,12 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
foundSomething = true;
final String description = interpolateString(pom.getDescription(), pomProperties);
if (description != null && !description.isEmpty()) {
addDescription(dependency, description, "pom", "description");
addMatchingValues(classes, description, dependency.getVendorEvidence());
addMatchingValues(classes, description, dependency.getProductEvidence());
}
}
//license
if (pom.getLicenses() != null) {
String license = null;
for (License lic : pom.getLicenses().getLicense()) {
String tmp = null;
if (lic.getName() != null) {
tmp = interpolateString(lic.getName(), pomProperties);
}
if (lic.getUrl() != null) {
if (tmp == null) {
tmp = interpolateString(lic.getUrl(), pomProperties);
} else {
tmp += ": " + interpolateString(lic.getUrl(), pomProperties);
}
}
if (tmp == null) {
continue;
}
if (HTML_DETECTION_PATTERN.matcher(tmp).find()) {
tmp = Jsoup.parse(tmp).text();
}
if (license == null) {
license = tmp;
} else {
license += "\n" + tmp;
}
}
if (license != null) {
dependency.setLicense(license);
final String trimmedDescription = addDescription(dependency, description, "pom", "description");
addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence());
addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence());
}
}
extractLicense(pom, pomProperties, dependency);
return foundSomething;
}
@@ -682,10 +690,9 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
&& !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar")
&& !dependency.getFileName().toLowerCase().endsWith("-src.jar")
&& !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) {
Logger.getLogger(JarAnalyzer.class
.getName()).log(Level.INFO,
String.format("Jar file '%s' does not contain a manifest.",
dependency.getFileName()));
LOGGER.log(Level.INFO,
String.format("Jar file '%s' does not contain a manifest.",
dependency.getFileName()));
}
return false;
}
@@ -767,7 +774,16 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
} else {
versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
}
} else if ("build-id".equals(key)) {
int pos = value.indexOf('(');
if (pos >= 0) {
value = value.substring(0, pos - 1);
}
pos = value.indexOf('[');
if (pos >= 0) {
value = value.substring(0, pos - 1);
}
versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
} else if (key.contains("title")) {
productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
addMatchingValues(classInformation, value, productEvidence);
@@ -816,14 +832,18 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
}
/**
* Adds a description to the given dependency.
* Adds a description to the given dependency. If the description contains one of the following strings beyond 100
* characters, then the description used will be trimmed to that position:
* <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses "</li></ul>
*
* @param dependency a dependency
* @param description the description
* @param source the source of the evidence
* @param key the "name" of the evidence
* @return if the description is trimmed, the trimmed version is returned; otherwise the original description is
* returned
*/
private void addDescription(Dependency dependency, String description, String source, String key) {
private String addDescription(Dependency dependency, String description, String source, String key) {
if (dependency.getDescription() == null) {
dependency.setDescription(description);
}
@@ -835,29 +855,42 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
}
dependency.setDescription(desc);
if (desc.length() > 100) {
desc = desc.replaceAll("\\s\\s+", " ");
final int posSuchAs = desc.toLowerCase().indexOf("such as ", 100);
final int posLike = desc.toLowerCase().indexOf("like ", 100);
final int posWillUse = desc.toLowerCase().indexOf("will use ", 100);
final int posUses = desc.toLowerCase().indexOf(" uses ", 100);
int pos = -1;
if (posLike > 0 && posSuchAs > 0) {
pos = posLike > posSuchAs ? posLike : posSuchAs;
} else if (posLike > 0) {
pos = posLike;
} else if (posSuchAs > 0) {
pos = posSuchAs;
pos = Math.max(pos, posSuchAs);
if (pos >= 0 && posLike >= 0) {
pos = Math.min(pos, posLike);
} else {
pos = Math.max(pos, posLike);
}
String descToUse = desc;
if (pos >= 0 && posWillUse >= 0) {
pos = Math.min(pos, posWillUse);
} else {
pos = Math.max(pos, posWillUse);
}
if (pos >= 0 && posUses >= 0) {
pos = Math.min(pos, posUses);
} else {
pos = Math.max(pos, posUses);
}
if (pos > 0) {
final StringBuilder sb = new StringBuilder(pos + 3);
sb.append(desc.substring(0, pos));
sb.append("...");
descToUse = sb.toString();
desc = sb.toString();
}
dependency.getProductEvidence().addEvidence(source, key, descToUse, Confidence.LOW);
dependency.getVendorEvidence().addEvidence(source, key, descToUse, Confidence.LOW);
dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.LOW);
dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.LOW);
} else {
dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.MEDIUM);
dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.MEDIUM);
}
return desc;
}
/**
@@ -880,19 +913,13 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
private File tempFileLocation = null;
/**
* The initialize method does nothing for this Analyzer.
* Initializes the JarAnalyzer.
*
* @throws Exception is thrown if there is an exception creating a temporary directory
*/
@Override
public void initialize() throws Exception {
public void initializeFileTypeAnalyzer() throws Exception {
final File baseDir = Settings.getTempDirectory();
if (!baseDir.exists()) {
if (!baseDir.mkdirs()) {
final String msg = String.format("Unable to make a temporary folder '%s'", baseDir.getPath());
throw new AnalysisException(msg);
}
}
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
@@ -910,7 +937,12 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
@Override
public void close() {
if (tempFileLocation != null && tempFileLocation.exists()) {
FileUtils.deleteRecursive(tempFileLocation.getAbsolutePath(), true);
LOGGER.log(Level.FINE, "Attempting to delete temporary files");
final boolean success = FileUtils.delete(tempFileLocation);
if (!success) {
LOGGER.log(Level.WARNING,
"Failed to delete some temporary files, see the log for more details");
}
}
}
@@ -979,11 +1011,9 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
* @return true or false depending on if it is believed the entry is an "import" entry
*/
private boolean isImportPackage(String key, String value) {
final Pattern packageRx = Pattern.compile("^((([a-zA-Z_#\\$0-9]\\.)+)\\s*\\;\\s*)+$");
if (packageRx.matcher(value).matches()) {
return (key.contains("import") || key.contains("include"));
}
return false;
final Pattern packageRx = Pattern.compile("^([a-zA-Z0-9_#\\$\\*\\.]+\\s*[,;]\\s*)+([a-zA-Z0-9_#\\$\\*\\.]+\\s*)?$");
final boolean matches = packageRx.matcher(value).matches();
return matches && (key.contains("import") || key.contains("include") || value.length() > 10);
}
/**
@@ -1010,17 +1040,14 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
}
} catch (IOException ex) {
final String msg = String.format("Unable to open jar file '%s'.", dependency.getFileName());
Logger
.getLogger(JarAnalyzer.class
.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class
.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, null, ex);
} finally {
if (jar != null) {
try {
jar.close();
} catch (IOException ex) {
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}
@@ -1195,7 +1222,17 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
addDescription(dependency, description, "pom", "description");
}
}
extractLicense(pom, pomProperties, dependency);
}
/**
* Extracts the license information from the pom and adds it to the dependency.
*
* @param pom the pom object
* @param pomProperties the properties, used for string interpolation
* @param dependency the dependency to add license information too
*/
private void extractLicense(Model pom, Properties pomProperties, Dependency dependency) {
//license
if (pom.getLicenses() != null) {
String license = null;

View File

@@ -13,24 +13,38 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.Settings;
/**
*
* Used to load a JAR file and collect information that can be used to determine the associated CPE.
* Used to analyze a JavaScript file to gather information to aid in identification of a CPE identifier.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class JavaScriptAnalyzer extends AbstractAnalyzer implements Analyzer {
public class JavaScriptAnalyzer extends AbstractFileTypeAnalyzer {
//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(JavaScriptAnalyzer.class.getName());
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
* The name of the analyzer.
*/
@@ -49,6 +63,7 @@ public class JavaScriptAnalyzer extends AbstractAnalyzer implements Analyzer {
*
* @return a list of file EXTENSIONS supported by this analyzer.
*/
@Override
public Set<String> getSupportedExtensions() {
return EXTENSIONS;
}
@@ -58,61 +73,69 @@ public class JavaScriptAnalyzer extends AbstractAnalyzer implements Analyzer {
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support.
* @return whether or not the specified file extension is supported by this analyzer.
*/
public boolean supportsExtension(String extension) {
return EXTENSIONS.contains(extension);
}
/**
* Returns the phase that the analyzer is intended to run in.
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
//</editor-fold>
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
*
* @return the analyzer's enabled property setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_JAVASCRIPT_ENABLED;
}
/**
* Loads a specified JAR file and collects information from the manifest and checksums to identify the correct CPE
* information.
* Loads a specified JavaScript file and collects information from the copyright information contained within.
*
* @param dependency the dependency to analyze.
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR file.
* @throws AnalysisException is thrown if there is an error reading the JavaScript file.
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
final Pattern extractComments = Pattern.compile("(/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/)|(//.*)");
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
BufferedReader fin = null;
try {
// /\*([^\*][^/]|[\r\n\f])+?\*/
final Pattern extractComments = Pattern.compile("(/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/)|(//.*)", Pattern.MULTILINE);
File file = dependency.getActualFile();
fin = new BufferedReader(new FileReader(file));
StringBuilder sb = new StringBuilder(2000);
String text;
while ((text = fin.readLine()) != null) {
sb.append(text);
}
} catch (FileNotFoundException ex) {
final String msg = String.format("Dependency file not found: '%s'", dependency.getActualFilePath());
throw new AnalysisException(msg, ex);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, null, ex);
} finally {
if (fin != null) {
try {
fin.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, null, ex);
}
}
}
}
/**
* The initialize method does nothing for this Analyzer.
*
* @throws Exception thrown if there is an exception
*/
@Override
public void initialize() throws Exception {
//do nothing
}
protected void initializeFileTypeAnalyzer() throws Exception {
/**
* The close method does nothing for this Analyzer.
*
* @throws Exception thrown if there is an exception
*/
@Override
public void close() throws Exception {
//do nothing
}
}

View File

@@ -25,6 +25,7 @@ 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.nexus.MavenArtifact;
import org.owasp.dependencycheck.data.nexus.NexusSearch;
import org.owasp.dependencycheck.dependency.Confidence;
@@ -45,20 +46,20 @@ import org.owasp.dependencycheck.utils.Settings;
*
* @author colezlaw
*/
public class NexusAnalyzer extends AbstractAnalyzer {
public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(NexusAnalyzer.class.getName());
/**
* The name of the analyzer
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "Nexus Analyzer";
/**
* The phase in which the analyzer runs
* The phase in which the analyzer runs.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
@@ -67,11 +68,6 @@ public class NexusAnalyzer extends AbstractAnalyzer {
*/
private static final Set<String> SUPPORTED_EXTENSIONS = newHashSet("jar");
/**
* Whether this is actually enabled. Will get set during initialization.
*/
private boolean enabled = false;
/**
* The Nexus Search to be set up for this analyzer.
*/
@@ -83,20 +79,23 @@ public class NexusAnalyzer extends AbstractAnalyzer {
* @throws Exception if there's an error during initialization
*/
@Override
public void initialize() throws Exception {
enabled = Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED);
public void initializeFileTypeAnalyzer() throws Exception {
LOGGER.fine("Initializing Nexus Analyzer");
LOGGER.fine(String.format("Nexus Analyzer enabled: %s", enabled));
if (enabled) {
LOGGER.fine(String.format("Nexus Analyzer enabled: %s", isEnabled()));
if (isEnabled()) {
final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
LOGGER.fine(String.format("Nexus Analyzer URL: %s", searchUrl));
try {
searcher = new NexusSearch(new URL(searchUrl));
if (!searcher.preflightRequest()) {
LOGGER.warning("There was an issue getting Nexus status. Disabling analyzer.");
setEnabled(false);
}
} catch (MalformedURLException mue) {
// I know that initialize can throw an exception, but we'll
// just disable the analyzer if the URL isn't valid
LOGGER.warning(String.format("Property %s not a valid URL. Nexus Analyzer disabled", searchUrl));
enabled = false;
setEnabled(false);
}
}
}
@@ -111,6 +110,16 @@ public class NexusAnalyzer extends AbstractAnalyzer {
return ANALYZER_NAME;
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
*
* @return the analyzer's enabled property setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_NEXUS_ENABLED;
}
/**
* Returns the analysis phase under which the analyzer runs.
*
@@ -131,17 +140,6 @@ public class NexusAnalyzer extends AbstractAnalyzer {
return SUPPORTED_EXTENSIONS;
}
/**
* Determines whether the incoming extension is supported.
*
* @param extension the extension to check for support
* @return whether the extension is supported
*/
@Override
public boolean supportsExtension(String extension) {
return SUPPORTED_EXTENSIONS.contains(extension);
}
/**
* Performs the analysis.
*
@@ -150,12 +148,7 @@ public class NexusAnalyzer extends AbstractAnalyzer {
* @throws AnalysisException when there's an exception during analysis
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
// Make a quick exit if this analyzer is disabled
if (!enabled) {
return;
}
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
try {
final MavenArtifact ma = searcher.searchSha1(dependency.getSha1sum());
if (ma.getGroupId() != null && !"".equals(ma.getGroupId())) {
@@ -175,7 +168,7 @@ public class NexusAnalyzer extends AbstractAnalyzer {
LOGGER.info(String.format("invalid sha-1 hash on %s", dependency.getFileName()));
} catch (FileNotFoundException fnfe) {
//dependency.addAnalysisException(new AnalysisException("Artifact not found on repository"));
LOGGER.fine(String.format("Artificat not found in repository '%s'", dependency.getFileName()));
LOGGER.fine(String.format("Artifact not found in repository '%s'", dependency.getFileName()));
LOGGER.log(Level.FINE, fnfe.getMessage(), fnfe);
} catch (IOException ioe) {
//dependency.addAnalysisException(new AnalysisException("Could not connect to repository", ioe));
@@ -183,5 +176,3 @@ public class NexusAnalyzer extends AbstractAnalyzer {
}
}
}
// vim: cc=120:sw=4:ts=4:sts=4

View File

@@ -0,0 +1,156 @@
/*
* 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.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
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.nuget.NugetPackage;
import org.owasp.dependencycheck.data.nuget.NuspecParseException;
import org.owasp.dependencycheck.data.nuget.NuspecParser;
import org.owasp.dependencycheck.data.nuget.XPathNuspecParser;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.Settings;
/**
* Analyzer which will parse a Nuspec file to gather module information.
*
* @author colezlaw
*/
public class NuspecAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(NuspecAnalyzer.class.getName());
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "Nuspec Analyzer";
/**
* The phase in which the 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("nuspec");
/**
* Initializes the analyzer once before any analysis is performed.
*
* @throws Exception if there's an error during initialization
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
}
/**
* 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 reference the analyzer's enabled property.
*
* @return the analyzer's enabled property setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_NUSPEC_ENABLED;
}
/**
* Returns the analysis phase under which the analyzer runs.
*
* @return the phase under which this 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 {
LOGGER.log(Level.FINE, "Checking Nuspec file {0}", dependency.toString());
try {
final NuspecParser parser = new XPathNuspecParser();
NugetPackage np = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(dependency.getActualFilePath());
np = parser.parse(fis);
} catch (NuspecParseException ex) {
throw new AnalysisException(ex);
} catch (FileNotFoundException ex) {
throw new AnalysisException(ex);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
LOGGER.fine("Error closing input stream");
}
}
}
if (np.getOwners() != null) {
dependency.getVendorEvidence().addEvidence("nuspec", "owners", np.getOwners(), Confidence.HIGHEST);
}
dependency.getVendorEvidence().addEvidence("nuspec", "authors", np.getAuthors(), Confidence.HIGH);
dependency.getVersionEvidence().addEvidence("nuspec", "version", np.getVersion(), Confidence.HIGHEST);
dependency.getProductEvidence().addEvidence("nuspec", "id", np.getId(), Confidence.HIGHEST);
if (np.getTitle() != null) {
dependency.getProductEvidence().addEvidence("nuspec", "title", np.getTitle(), Confidence.MEDIUM);
}
} catch (Throwable e) {
throw new AnalysisException(e);
}
}
}

View File

@@ -20,8 +20,8 @@ package org.owasp.dependencycheck.analyzer;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.dependency.Dependency;
@@ -61,6 +61,7 @@ public class NvdCveAnalyzer implements Analyzer {
/**
* Closes the data source.
*/
@Override
public void close() {
cveDB.close();
cveDB = null;
@@ -95,6 +96,7 @@ public class NvdCveAnalyzer implements Analyzer {
* @param engine The analysis engine
* @throws AnalysisException is thrown if there is an issue analyzing the dependency
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
for (Identifier id : dependency.getIdentifiers()) {
if ("cpe".equals(id.getType())) {
@@ -107,15 +109,17 @@ public class NvdCveAnalyzer implements Analyzer {
}
}
}
}
/**
* Returns true because this analyzer supports all dependency types.
*
* @return true.
*/
public Set<String> getSupportedExtensions() {
return null;
for (Identifier id : dependency.getSuppressedIdentifiers()) {
if ("cpe".equals(id.getType())) {
try {
final String value = id.getValue();
final List<Vulnerability> vulns = cveDB.getVulnerabilities(value);
dependency.getSuppressedVulnerabilities().addAll(vulns);
} catch (DatabaseException ex) {
throw new AnalysisException(ex);
}
}
}
}
/**
@@ -123,34 +127,27 @@ public class NvdCveAnalyzer implements Analyzer {
*
* @return the name of this analyzer.
*/
@Override
public String getName() {
return "NVD CVE Analyzer";
}
/**
* Returns true because this analyzer supports all dependency types.
*
* @param extension the file extension of the dependency being analyzed.
* @return true.
*/
public boolean supportsExtension(String extension) {
return true;
}
/**
* Returns the analysis phase that this analyzer should run in.
*
* @return the analysis phase that this analyzer should run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return AnalysisPhase.FINDING_ANALYSIS;
}
/**
* Opens the NVD CVE Lucene Index.
* Opens the database used to gather NVD CVE data.
*
* @throws Exception is thrown if there is an issue opening the index.
*/
@Override
public void initialize() throws Exception {
this.open();
}

View File

@@ -17,6 +17,7 @@
*/
package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.suppression.SuppressionRule;

View File

@@ -15,7 +15,7 @@
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
package org.owasp.dependencycheck.analyzer.exception;
/**
* An exception thrown when the analysis of a dependency fails.

View File

@@ -15,7 +15,7 @@
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
package org.owasp.dependencycheck.analyzer.exception;
/**
* An exception thrown when files in an archive cannot be extracted.

View File

@@ -0,0 +1,12 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.analyzer.exception</title>
* </head>
* <body>
* <p>
* A collection of exception classes used within the analyzers.</p>
* </body>
* </html>
*/
package org.owasp.dependencycheck.analyzer.exception;

View File

@@ -18,10 +18,9 @@
package org.owasp.dependencycheck.data.cpe;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.lucene.analysis.Analyzer;
@@ -45,6 +44,8 @@ import org.owasp.dependencycheck.data.lucene.FieldAnalyzer;
import org.owasp.dependencycheck.data.lucene.LuceneUtils;
import org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.utils.Pair;
/**
* An in memory lucene index that contains the vendor/product combinations from the CPE (application) identifiers within
@@ -53,7 +54,10 @@ import org.owasp.dependencycheck.data.nvdcve.CveDB;
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class CpeMemoryIndex {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(CpeMemoryIndex.class.getName());
/**
* singleton instance.
*/
@@ -196,7 +200,7 @@ public final class CpeMemoryIndex {
try {
indexReader.close();
} catch (IOException ex) {
Logger.getLogger(CpeMemoryIndex.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
indexReader = null;
}
@@ -210,7 +214,7 @@ public final class CpeMemoryIndex {
}
/**
* Builds the lucene index based off of the data within the CveDB.
* Builds the CPE Lucene Index based off of the data within the CveDB.
*
* @param cve the data base containing the CPE data
* @throws IndexException thrown if there is an issue creating the index
@@ -222,16 +226,13 @@ public final class CpeMemoryIndex {
analyzer = createIndexingAnalyzer();
final IndexWriterConfig conf = new IndexWriterConfig(LuceneUtils.CURRENT_VERSION, analyzer);
indexWriter = new IndexWriter(index, conf);
final ResultSet rs = cve.getVendorProductList();
if (rs == null) {
throw new IndexException("No data exists");
}
try {
while (rs.next()) {
saveEntry(rs.getString(1), rs.getString(2), indexWriter);
final Set<Pair<String, String>> data = cve.getVendorProductList();
for (Pair<String, String> pair : data) {
saveEntry(pair.getLeft(), pair.getRight(), indexWriter);
}
} catch (SQLException ex) {
Logger.getLogger(CpeMemoryIndex.class.getName()).log(Level.FINE, null, ex);
} catch (DatabaseException ex) {
LOGGER.log(Level.FINE, null, ex);
throw new IndexException("Error reading CPE data", ex);
}
} catch (CorruptIndexException ex) {

View File

@@ -29,7 +29,10 @@ import java.util.logging.Logger;
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class CweDB {
/**
* The Logger.
*/
private static final Logger LOGGER = Logger.getLogger(CweDB.class.getName());
/**
* Empty private constructor as this is a utility class.
*/
@@ -54,17 +57,17 @@ public final class CweDB {
oin = new ObjectInputStream(input);
return (HashMap<String, String>) oin.readObject();
} catch (ClassNotFoundException ex) {
Logger.getLogger(CweDB.class.getName()).log(Level.WARNING, "Unable to load CWE data. This should not be an issue.");
Logger.getLogger(CweDB.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, "Unable to load CWE data. This should not be an issue.");
LOGGER.log(Level.FINE, null, ex);
} catch (IOException ex) {
Logger.getLogger(CweDB.class.getName()).log(Level.WARNING, "Unable to load CWE data due to an IO Error. This should not be an issue.");
Logger.getLogger(CweDB.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, "Unable to load CWE data due to an IO Error. This should not be an issue.");
LOGGER.log(Level.FINE, null, ex);
} finally {
if (oin != null) {
try {
oin.close();
} catch (IOException ex) {
Logger.getLogger(CweDB.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}

View File

@@ -36,7 +36,10 @@ import org.owasp.dependencycheck.utils.UrlStringUtils;
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class UrlTokenizingFilter extends AbstractTokenizingFilter {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(UrlTokenizingFilter.class.getName());
/**
* Constructs a new VersionTokenizingFilter.
*
@@ -67,7 +70,7 @@ public final class UrlTokenizingFilter extends AbstractTokenizingFilter {
final List<String> data = UrlStringUtils.extractImportantUrlData(part);
tokens.addAll(data);
} catch (MalformedURLException ex) {
Logger.getLogger(UrlTokenizingFilter.class.getName()).log(Level.INFO, "error parsing " + part, ex);
LOGGER.log(Level.FINE, "error parsing " + part, ex);
tokens.add(part);
}
} else {

View File

@@ -19,13 +19,17 @@ package org.owasp.dependencycheck.data.nexus;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.URLConnectionFactory;
import org.w3c.dom.Document;
/**
@@ -40,10 +44,16 @@ public class NexusSearch {
*/
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(NexusSearch.class.getName());
private static final Logger LOGGER = Logger.getLogger(NexusSearch.class
.getName());
/**
* Creates a NexusSearch for the given repository URL.
@@ -53,6 +63,18 @@ public class NexusSearch {
*/
public NexusSearch(URL rootURL) {
this.rootURL = rootURL;
try {
if (null != Settings.getString(Settings.KEYS.PROXY_URL)
&& Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY)) {
useProxy = true;
LOGGER.fine("Using proxy");
} else {
useProxy = false;
LOGGER.fine("Not using proxy");
}
} catch (InvalidSettingException ise) {
useProxy = false;
}
}
/**
@@ -61,7 +83,7 @@ public class NexusSearch {
*
* @param sha1 The SHA-1 hash string for which to search
* @return the populated Maven coordinates
* @throws IOException if it's unable to connect to the specified repositor or if the specified artifact is not
* @throws IOException if it's unable to connect to the specified repository or if the specified artifact is not
* found.
*/
public MavenArtifact searchSha1(String sha1) throws IOException {
@@ -69,11 +91,18 @@ public class NexusSearch {
throw new IllegalArgumentException("Invalid SHA1 format");
}
final URL url = new URL(rootURL, String.format("identify/sha1/%s", sha1.toLowerCase()));
final URL url = new URL(rootURL, String.format("identify/sha1/%s",
sha1.toLowerCase()));
LOGGER.fine(String.format("Searching Nexus url %s", url.toString()));
final URLConnection conn = url.openConnection();
// 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
@@ -81,23 +110,68 @@ public class NexusSearch {
conn.addRequestProperty("Accept", "application/xml");
conn.connect();
if (conn.getResponseCode() == 200) {
try {
final DocumentBuilder builder = DocumentBuilderFactory
.newInstance().newDocumentBuilder();
final Document doc = builder.parse(conn.getInputStream());
final XPath xpath = XPathFactory.newInstance().newXPath();
final String groupId = xpath
.evaluate(
"/org.sonatype.nexus.rest.model.NexusArtifact/groupId",
doc);
final String artifactId = xpath.evaluate(
"/org.sonatype.nexus.rest.model.NexusArtifact/artifactId",
doc);
final String version = xpath
.evaluate(
"/org.sonatype.nexus.rest.model.NexusArtifact/version",
doc);
final String link = xpath
.evaluate(
"/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink",
doc);
return new MavenArtifact(groupId, artifactId, version, link);
} catch (Throwable e) {
// Anything else is jacked-up XML stuff that we really can't recover
// from well
throw new IOException(e.getMessage(), e);
}
} else if (conn.getResponseCode() == 404) {
throw new FileNotFoundException("Artifact not found in Nexus");
} else {
final String msg = String.format("Could not connect to Nexus received response code: %d %s",
conn.getResponseCode(), conn.getResponseMessage());
LOGGER.fine(msg);
throw new IOException(msg);
}
}
/**
* Do a preflight request to see if the repository is actually working.
*
* @return whether the repository is listening and returns the /status URL correctly
*/
public boolean preflightRequest() {
try {
final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(new URL(rootURL, "status"), useProxy);
conn.addRequestProperty("Accept", "application/xml");
conn.connect();
if (conn.getResponseCode() != 200) {
LOGGER.log(Level.WARNING, "Expected 200 result from Nexus, got {0}", conn.getResponseCode());
return false;
}
final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document doc = builder.parse(conn.getInputStream());
final XPath xpath = XPathFactory.newInstance().newXPath();
final String groupId = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/groupId", doc);
final String artifactId = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/artifactId", doc);
final String version = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/version", doc);
final String link = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink", doc);
return new MavenArtifact(groupId, artifactId, version, link);
} catch (FileNotFoundException fnfe) {
// This is what we get when the SHA1 they sent doesn't exist in Nexus. This
// is useful upstream for recovery, so we just re-throw it
throw fnfe;
} catch (Exception e) {
// Anything else is jacked-up XML stuff that we really can't recover from well
throw new IOException(e.getMessage(), e);
if (!"status".equals(doc.getDocumentElement().getNodeName())) {
LOGGER.log(Level.WARNING, "Expected root node name of status, got {0}", doc.getDocumentElement().getNodeName());
return false;
}
} catch (Throwable e) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,186 @@
/*
* 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.nuget;
/**
* Represents the contents of a Nuspec manifest.
*
* @author colezlaw
*/
public class NugetPackage {
/**
* The id.
*/
private String id;
/**
* The version.
*/
private String version;
/**
* The title.
*/
private String title;
/**
* The authors.
*/
private String authors;
/**
* The owners.
*/
private String owners;
/**
* The licenseUrl.
*/
private String licenseUrl;
/**
* Creates an empty NugetPackage.
*/
public NugetPackage() {
}
/**
* Sets the id.
* @param id the id
*/
public void setId(String id) {
this.id = id;
}
/**
* Gets the id.
* @return the id
*/
public String getId() {
return id;
}
/**
* Sets the version.
* @param version the version
*/
public void setVersion(String version) {
this.version = version;
}
/**
* Gets the version.
* @return the version
*/
public String getVersion() {
return version;
}
/**
* Sets the title.
* @param title the title
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Gets the title.
* @return the title
*/
public String getTitle() {
return title;
}
/**
* Sets the authors.
* @param authors the authors
*/
public void setAuthors(String authors) {
this.authors = authors;
}
/**
* Gets the authors.
* @return the authors
*/
public String getAuthors() {
return authors;
}
/**
* Sets the owners.
* @param owners the owners
*/
public void setOwners(String owners) {
this.owners = owners;
}
/**
* Gets the owners.
* @return the owners
*/
public String getOwners() {
return owners;
}
/**
* Sets the licenseUrl.
* @param licenseUrl the licenseUrl
*/
public void setLicenseUrl(String licenseUrl) {
this.licenseUrl = licenseUrl;
}
/**
* Gets the licenseUrl.
* @return the licenseUrl
*/
public String getLicenseUrl() {
return licenseUrl;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other == null || other.getClass() != this.getClass()) {
return false;
}
final NugetPackage o = (NugetPackage) other;
return o.getId().equals(id)
&& o.getVersion().equals(version)
&& o.getTitle().equals(title)
&& o.getAuthors().equals(authors)
&& o.getOwners().equals(owners)
&& o.getLicenseUrl().equals(licenseUrl);
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + (null == id ? 0 : id.hashCode());
hash = 31 * hash + (null == version ? 0 : version.hashCode());
hash = 31 * hash + (null == title ? 0 : title.hashCode());
hash = 31 * hash + (null == authors ? 0 : authors.hashCode());
hash = 31 * hash + (null == owners ? 0 : owners.hashCode());
hash = 31 * hash + (null == licenseUrl ? 0 : licenseUrl.hashCode());
return hash;
}
}

View File

@@ -0,0 +1,67 @@
/*
* 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.nuget;
/**
* Exception during the parsing of a Nuspec file.
*
* @author colezlaw
*/
public class NuspecParseException extends Exception {
/**
* The serialVersionUID
*/
private static final long serialVersionUID = 1;
/**
* Constructs a new exception with <code>null</code> as its detail message.
*
* The cause is not initialized, and may subsequently be initialized by a call to
* {@link java.lang.Throwable#initCause(java.lang.Throwable)}.
*/
public NuspecParseException() {
super();
}
/**
* Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently
* be initialized by a call to {@link java.lang.Throwable#initCause(java.lang.Throwable)}.
*
* @param message the detail message. The detail message is saved for later retrieval by the
* {@link java.lang.Throwable#getMessage()} method.
*/
public NuspecParseException(String message) {
super(message);
}
/**
* Constructs a new exception with the specified detail message and cause.
*
* Note that the detail message associated with <code>cause</code> is <em>not</em>
* automatically incorporated in this exception's detail message.
*
* @param message the detail message (which is saved for later retrieval by the
* {@link java.lang.Throwable#getMessage()} method.
* @param cause the cause (which is saved for later retrieval by the {@link java.lang.Throwable#getCause()} method).
* (A <code>null</code> value is permitted, and indicates that the cause is nonexistent or unknown).
*/
public NuspecParseException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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.nuget;
import java.io.InputStream;
/**
* Interface defining methods for parsing a Nuspec file.
*
* @author colezlaw
*
*/
public interface NuspecParser {
/**
* Parse an input stream and return the resulting {@link NugetPackage}.
*
* @param stream the input stream to parse
* @return the populated bean
* @throws NuspecParseException when an exception occurs
*/
NugetPackage parse(InputStream stream) throws NuspecParseException;
}

View File

@@ -0,0 +1,81 @@
/*
* 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.nuget;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
/**
* Parse a Nuspec file using XPath.
*
* @author colezlaw
*/
public class XPathNuspecParser implements NuspecParser {
/**
* Gets the string value of a node or null if it's not present
*
* @param n the node to test
* @return the string content of the node, or null if the node itself is null
*/
private String getOrNull(Node n) {
if (n != null) {
return n.getTextContent();
} else {
return null;
}
}
/**
* Parse an input stream and return the resulting {@link NugetPackage}.
*
* @param stream the input stream to parse
* @return the populated bean
* @throws NuspecParseException when an exception occurs
*/
@Override
public NugetPackage parse(InputStream stream) throws NuspecParseException {
try {
final Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(stream);
final XPath xpath = XPathFactory.newInstance().newXPath();
final NugetPackage nuspec = new NugetPackage();
if (xpath.evaluate("/package/metadata/id", d, XPathConstants.NODE) == null
|| xpath.evaluate("/package/metadata/version", d, XPathConstants.NODE) == null
|| xpath.evaluate("/package/metadata/authors", d, XPathConstants.NODE) == null
|| xpath.evaluate("/package/metadata/description", d, XPathConstants.NODE) == null) {
throw new NuspecParseException("Invalid Nuspec format");
}
nuspec.setId(xpath.evaluate("/package/metadata/id", d));
nuspec.setVersion(xpath.evaluate("/package/metadata/version", d));
nuspec.setAuthors(xpath.evaluate("/package/metadata/authors", d));
nuspec.setOwners(getOrNull((Node) xpath.evaluate("/package/metadata/owners", d, XPathConstants.NODE)));
nuspec.setLicenseUrl(getOrNull((Node) xpath.evaluate("/package/metadata/licenseUrl", d, XPathConstants.NODE)));
nuspec.setTitle(getOrNull((Node) xpath.evaluate("/package/metadata/title", d, XPathConstants.NODE)));
return nuspec;
} catch (Throwable e) {
throw new NuspecParseException("Unable to parse nuspec", e);
}
}
}

View File

@@ -0,0 +1,15 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.data.nuget</title>
* </head>
* <body>
* <p>
* Contains classes related to parsing Nuget related files</p>
* <p>
* These are used to abstract away Nuget-related handling from Dependency Check
* so they can be used elsewhere.</p>
* </body>
* </html>
*/
package org.owasp.dependencycheck.data.nuget;

View File

@@ -24,6 +24,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -41,7 +42,10 @@ import org.owasp.dependencycheck.utils.Settings;
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class ConnectionFactory {
/**
* The Logger.
*/
private static final Logger LOGGER = Logger.getLogger(ConnectionFactory.class.getName());
/**
* The version of the current DB Schema.
*/
@@ -50,6 +54,22 @@ public final class ConnectionFactory {
* Resource location for SQL file used to create the database schema.
*/
public static final String DB_STRUCTURE_RESOURCE = "data/initialize.sql";
/**
* The database driver used to connect to the database.
*/
private static Driver driver = null;
/**
* The database connection string.
*/
private static String connectionString = null;
/**
* The username to connect to the database.
*/
private static String userName = null;
/**
* The password for the database.
*/
private static String password = null;
/**
* Private constructor for this factory class; no instance is ever needed.
@@ -58,66 +78,140 @@ public final class ConnectionFactory {
}
/**
* Constructs a new database connection object per the database configuration. This will load the appropriate
* database driver, via the DriverManager, if configured.
* Initializes the connection factory. Ensuring that the appropriate drivers are loaded and that a connection can be
* made successfully.
*
* @return a database connection object
* @throws DatabaseException thrown if there is an exception loading the database connection
* @throws DatabaseException thrown if we are unable to connect to the database
*/
public static Connection getConnection() throws DatabaseException {
public static synchronized void initialize() throws DatabaseException {
//this only needs to be called once.
if (connectionString != null) {
return;
}
Connection conn = null;
try {
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading database connection");
final String connStr = getConnectionString();
final String user = Settings.getString(Settings.KEYS.DB_USER, "dcuser");
//yes, yes - hard-coded password - only if there isn't one in the properties file.
final String pass = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!");
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Connection String: {0}", connStr);
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Database User: {0}", user);
boolean createTables = false;
if (connStr.startsWith("jdbc:h2:file:")) { //H2
createTables = needToCreateDatabaseStructure();
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Need to create DB Structure: {0}", createTables);
}
//load the driver if necessary
final String driverName = Settings.getString(Settings.KEYS.DB_DRIVER_NAME, "");
if (!driverName.isEmpty()) { //likely need to load the correct driver
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading driver: {0}", driverName);
LOGGER.log(Level.FINE, "Loading driver: {0}", driverName);
final String driverPath = Settings.getString(Settings.KEYS.DB_DRIVER_PATH, "");
if (!driverPath.isEmpty()) { //ugh, driver is not on classpath?
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading driver from: {0}", driverPath);
DriverLoader.load(driverName, driverPath);
try {
if (!driverPath.isEmpty()) {
LOGGER.log(Level.FINE, "Loading driver from: {0}", driverPath);
driver = DriverLoader.load(driverName, driverPath);
} else {
driver = DriverLoader.load(driverName);
}
} catch (DriverLoadException ex) {
LOGGER.log(Level.FINE, "Unable to load database driver", ex);
throw new DatabaseException("Unable to load database driver");
}
}
userName = Settings.getString(Settings.KEYS.DB_USER, "dcuser");
//yes, yes - hard-coded password - only if there isn't one in the properties file.
password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!");
try {
connectionString = getConnectionString();
} catch (IOException ex) {
LOGGER.log(Level.FINE,
"Unable to retrieve the database connection string", ex);
throw new DatabaseException("Unable to retrieve the database connection string");
}
boolean shouldCreateSchema = false;
try {
if (connectionString.startsWith("jdbc:h2:file:")) { //H2
shouldCreateSchema = !dbSchemaExists();
LOGGER.log(Level.FINE, "Need to create DB Structure: {0}", shouldCreateSchema);
}
} catch (IOException ioex) {
LOGGER.log(Level.FINE, "Unable to verify database exists", ioex);
throw new DatabaseException("Unable to verify database exists");
}
LOGGER.log(Level.FINE, "Loading database connection");
LOGGER.log(Level.FINE, "Connection String: {0}", connectionString);
LOGGER.log(Level.FINE, "Database User: {0}", userName);
try {
conn = DriverManager.getConnection(connectionString, userName, password);
} catch (SQLException ex) {
if (ex.getMessage().contains("java.net.UnknownHostException") && connectionString.contains("AUTO_SERVER=TRUE;")) {
connectionString = connectionString.replace("AUTO_SERVER=TRUE;", "");
try {
conn = DriverManager.getConnection(connectionString, userName, password);
Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
LOGGER.log(Level.FINE,
"Unable to start the database in server mode; reverting to single user mode");
} catch (SQLException sqlex) {
LOGGER.log(Level.FINE, "Unable to connect to the database", ex);
throw new DatabaseException("Unable to connect to the database");
}
} else {
DriverLoader.load(driverName);
LOGGER.log(Level.FINE, "Unable to connect to the database", ex);
throw new DatabaseException("Unable to connect to the database");
}
}
//JDBC4 drivers don't need this call.
//Class.forName("org.h2.Driver");
conn = DriverManager.getConnection(connStr, user, pass);
if (createTables) {
if (shouldCreateSchema) {
try {
createTables(conn);
} catch (DatabaseException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
} catch (DatabaseException dex) {
LOGGER.log(Level.FINE, null, dex);
throw new DatabaseException("Unable to create the database structure");
}
} else {
try {
ensureSchemaVersion(conn);
} catch (DatabaseException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
} catch (DatabaseException dex) {
LOGGER.log(Level.FINE, null, dex);
throw new DatabaseException("Database schema does not match this version of dependency-check");
}
}
} catch (IOException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
throw new DatabaseException("Unable to load database");
} catch (DriverLoadException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
throw new DatabaseException("Unable to load database driver");
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException ex) {
LOGGER.log(Level.FINE, "An error occurred closing the connection", ex);
}
}
}
}
/**
* Cleans up resources and unloads any registered database drivers. This needs to be called to ensure the driver is
* unregistered prior to the finalize method being called as during shutdown the class loader used to load the
* driver may be unloaded prior to the driver being de-registered.
*/
public static synchronized void cleanup() {
if (driver != null) {
try {
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
LOGGER.log(Level.FINE, "An error occurred unloading the database driver", ex);
} catch (Throwable unexpected) {
LOGGER.log(Level.FINE,
"An unexpected throwable occurred unloading the database driver", unexpected);
}
driver = null;
}
connectionString = null;
userName = null;
password = null;
}
/**
* Constructs a new database connection object per the database configuration.
*
* @return a database connection object
* @throws DatabaseException thrown if there is an exception loading the database connection
*/
public static Connection getConnection() throws DatabaseException {
initialize();
Connection conn = null;
try {
conn = DriverManager.getConnection(connectionString, userName, password);
} catch (SQLException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new DatabaseException("Unable to connect to the database");
}
return conn;
@@ -135,7 +229,7 @@ public final class ConnectionFactory {
if (connStr.contains("%s")) {
final String directory = getDataDirectory().getCanonicalPath();
final File dataFile = new File(directory, "cve." + DB_SCHEMA_VERSION);
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, String.format("File path for H2 file: '%s'", dataFile.toString()));
LOGGER.log(Level.FINE, String.format("File path for H2 file: '%s'", dataFile.toString()));
return String.format(connStr, dataFile.getAbsolutePath());
}
return connStr;
@@ -164,11 +258,11 @@ public final class ConnectionFactory {
* @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
*/
private static boolean needToCreateDatabaseStructure() throws IOException {
private static boolean dbSchemaExists() throws IOException {
final File dir = getDataDirectory();
final String name = String.format("cve.%s.h2.db", DB_SCHEMA_VERSION);
final File file = new File(dir, name);
return !file.exists();
return file.exists();
}
/**
@@ -178,7 +272,7 @@ public final class ConnectionFactory {
* @throws DatabaseException thrown if there is a Database Exception
*/
private static void createTables(Connection conn) throws DatabaseException {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "Creating database structure");
LOGGER.log(Level.FINE, "Creating database structure");
InputStream is;
InputStreamReader reader;
BufferedReader in = null;
@@ -196,7 +290,7 @@ public final class ConnectionFactory {
statement = conn.createStatement();
statement.execute(sb.toString());
} catch (SQLException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new DatabaseException("Unable to create database statement", ex);
} finally {
DBUtils.closeStatement(statement);
@@ -208,7 +302,7 @@ public final class ConnectionFactory {
try {
in.close();
} catch (IOException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}
@@ -235,7 +329,7 @@ public final class ConnectionFactory {
throw new DatabaseException("Database schema is missing");
}
} catch (SQLException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new DatabaseException("Unable to check the database schema version");
} finally {
DBUtils.closeResultSet(rs);

View File

@@ -38,6 +38,7 @@ import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.utils.DBUtils;
import org.owasp.dependencycheck.utils.DependencyVersion;
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
import org.owasp.dependencycheck.utils.Pair;
/**
* The database holding information about the NVD CVE data.
@@ -45,7 +46,10 @@ import org.owasp.dependencycheck.utils.DependencyVersionUtil;
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class CveDB {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(CveDB.class.getName());
/**
* Database connection
*/
@@ -94,8 +98,12 @@ public class CveDB {
conn.close();
} catch (SQLException ex) {
final String msg = "There was an error attempting to close the CveDB, see the log for more details.";
Logger.getLogger(DBUtils.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(DBUtils.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, msg);
LOGGER.log(Level.FINE, null, ex);
} catch (Throwable ex) {
final String msg = "There was an exception attempting to close the CveDB, see the log for more details.";
LOGGER.log(Level.SEVERE, msg);
LOGGER.log(Level.FINE, null, ex);
}
conn = null;
}
@@ -128,7 +136,9 @@ public class CveDB {
* @throws Throwable thrown if there is a problem
*/
@Override
@SuppressWarnings("FinalizeDeclaration")
protected void finalize() throws Throwable {
LOGGER.log(Level.FINE, "Entering finalize");
close();
super.finalize();
}
@@ -277,8 +287,8 @@ public class CveDB {
}
} catch (SQLException ex) {
final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
Logger.getLogger(CveDB.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, msg);
LOGGER.log(Level.FINE, null, ex);
} finally {
DBUtils.closeResultSet(rs);
DBUtils.closeStatement(ps);
@@ -289,19 +299,27 @@ public class CveDB {
/**
* Returns the entire list of vendor/product combinations.
*
* @return the entire list of vendor/product combinations.
* @return the entire list of vendor/product combinations
* @throws DatabaseException thrown when there is an error retrieving the data from the DB
*/
public ResultSet getVendorProductList() {
public Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
final HashSet data = new HashSet<Pair<String, String>>();
ResultSet rs = null;
PreparedStatement ps = null;
try {
final PreparedStatement ps = getConnection().prepareStatement(SELECT_VENDOR_PRODUCT_LIST);
ps = getConnection().prepareStatement(SELECT_VENDOR_PRODUCT_LIST);
rs = ps.executeQuery();
while (rs.next()) {
data.add(new Pair(rs.getString(1), rs.getString(2)));
}
} catch (SQLException ex) {
final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
Logger.getLogger(CveDB.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, null, ex);
} // can't close the statement in the PS as the resultset is returned, closing PS would close the resultset
return rs;
throw new DatabaseException(msg, ex);
} finally {
DBUtils.closeResultSet(rs);
DBUtils.closeStatement(ps);
}
return data;
}
/**
@@ -321,8 +339,8 @@ public class CveDB {
}
} catch (SQLException ex) {
final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
Logger.getLogger(CveDB.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, msg);
LOGGER.log(Level.FINE, null, ex);
} finally {
DBUtils.closeStatement(ps);
DBUtils.closeResultSet(rs);
@@ -343,8 +361,8 @@ public class CveDB {
updateProperty = getConnection().prepareStatement(UPDATE_PROPERTY);
insertProperty = getConnection().prepareStatement(INSERT_PROPERTY);
} catch (SQLException ex) {
Logger.getLogger(CveDB.class.getName()).log(Level.WARNING, "Unable to save properties to the database");
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Unable to save properties to the database", ex);
LOGGER.log(Level.WARNING, "Unable to save properties to the database");
LOGGER.log(Level.FINE, "Unable to save properties to the database", ex);
return;
}
for (Entry<Object, Object> entry : props.entrySet()) {
@@ -359,8 +377,8 @@ public class CveDB {
}
} catch (SQLException ex) {
final String msg = String.format("Unable to save property '%s' with a value of '%s' to the database", key, value);
Logger.getLogger(CveDB.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, null, ex);
}
}
} finally {
@@ -382,8 +400,8 @@ public class CveDB {
try {
updateProperty = getConnection().prepareStatement(UPDATE_PROPERTY);
} catch (SQLException ex) {
Logger.getLogger(CveDB.class.getName()).log(Level.WARNING, "Unable to save properties to the database");
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Unable to save properties to the database", ex);
LOGGER.log(Level.WARNING, "Unable to save properties to the database");
LOGGER.log(Level.FINE, "Unable to save properties to the database", ex);
return;
}
try {
@@ -393,8 +411,8 @@ public class CveDB {
try {
insertProperty = getConnection().prepareStatement(INSERT_PROPERTY);
} catch (SQLException ex) {
Logger.getLogger(CveDB.class.getName()).log(Level.WARNING, "Unable to save properties to the database");
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Unable to save properties to the database", ex);
LOGGER.log(Level.WARNING, "Unable to save properties to the database");
LOGGER.log(Level.FINE, "Unable to save properties to the database", ex);
return;
}
insertProperty.setString(1, key);
@@ -403,8 +421,8 @@ public class CveDB {
}
} catch (SQLException ex) {
final String msg = String.format("Unable to save property '%s' with a value of '%s' to the database", key, value);
Logger.getLogger(CveDB.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, null, ex);
}
} finally {
DBUtils.closeStatement(updateProperty);
@@ -425,7 +443,7 @@ public class CveDB {
try {
cpe.parseName(cpeStr);
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(CveDB.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
final DependencyVersion detectedVersion = parseDependencyVersion(cpe);
final List<Vulnerability> vulnerabilities = new ArrayList<Vulnerability>();
@@ -663,7 +681,7 @@ public class CveDB {
} catch (SQLException ex) {
final String msg = String.format("Error updating '%s'", vuln.getName());
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new DatabaseException(msg, ex);
} finally {
DBUtils.closeStatement(selectVulnerabilityId);
@@ -692,8 +710,8 @@ public class CveDB {
}
} catch (SQLException ex) {
final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
Logger.getLogger(CveDB.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, msg);
LOGGER.log(Level.FINE, null, ex);
} finally {
DBUtils.closeStatement(ps);
}
@@ -748,7 +766,7 @@ public class CveDB {
cpe.parseName(cpeStr);
} catch (UnsupportedEncodingException ex) {
//never going to happen.
Logger.getLogger(CveDB.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
return parseDependencyVersion(cpe);
}

View File

@@ -17,7 +17,6 @@
*/
package org.owasp.dependencycheck.data.nvdcve;
import com.hazelcast.logging.Logger;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -26,6 +25,7 @@ import java.util.Map.Entry;
import java.util.Properties;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.data.update.NvdCveInfo;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
@@ -36,6 +36,10 @@ import org.owasp.dependencycheck.data.update.exception.UpdateException;
*/
public class DatabaseProperties {
/**
* The Logger.
*/
private static final Logger LOGGER = Logger.getLogger(DatabaseProperties.class.getName());
/**
* Modified key word, used as a key to store information about the modified file (i.e. the containing the last 8
* days of updates)..
@@ -150,8 +154,8 @@ public class DatabaseProperties {
final DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
final String formatted = format.format(date);
map.put(key, formatted);
} catch (Throwable ex) { //deliberatly being broad in this catch clause
Logger.getLogger(DatabaseProperties.class.getName()).log(Level.FINE, "Unable to parse timestamp from DB", ex);
} catch (Throwable ex) { //deliberately being broad in this catch clause
LOGGER.log(Level.FINE, "Unable to parse timestamp from DB", ex);
map.put(key, entry.getValue());
}
} else {

View File

@@ -37,6 +37,11 @@ import java.util.logging.Logger;
*/
public final class DriverLoader {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(DriverLoader.class.getName());
/**
* Private constructor for a utility class.
*/
@@ -47,26 +52,28 @@ public final class DriverLoader {
* Loads the specified class using the system class loader and registers the driver with the driver manager.
*
* @param className the fully qualified name of the desired class
* @return the loaded Driver
* @throws DriverLoadException thrown if the driver cannot be loaded
*/
public static void load(String className) throws DriverLoadException {
public static Driver load(String className) throws DriverLoadException {
final ClassLoader loader = DriverLoader.class.getClassLoader(); //ClassLoader.getSystemClassLoader();
load(className, loader);
return load(className, loader);
}
/**
* Loads the specified class by registering the supplied paths to the class loader and then registers the driver
* with the driver manager. The pathToDriver argument is added to the class loader so that an external driver can be
* loaded. Note, the pathTodriver can contain a semi-colon separated list of paths so any dependencies can be added
* loaded. Note, the pathToDriver can contain a semi-colon separated list of paths so any dependencies can be added
* as needed. If a path in the pathToDriver argument is a directory all files in the directory are added to the
* class path.
*
* @param className the fully qualified name of the desired class
* @param pathToDriver the path to the JAR file containing the driver; note, this can be a semi-colon separated list
* of paths
* @return the loaded Driver
* @throws DriverLoadException thrown if the driver cannot be loaded
*/
public static void load(String className, String pathToDriver) throws DriverLoadException {
public static Driver load(String className, String pathToDriver) throws DriverLoadException {
final URLClassLoader parent = (URLClassLoader) ClassLoader.getSystemClassLoader();
final ArrayList<URL> urls = new ArrayList<URL>();
final String[] paths = pathToDriver.split(File.pathSeparator);
@@ -81,7 +88,7 @@ public final class DriverLoader {
} catch (MalformedURLException ex) {
final String msg = String.format("Unable to load database driver '%s'; invalid path provided '%s'",
className, f.getAbsoluteFile());
Logger.getLogger(DriverLoader.class.getName()).log(Level.FINE, msg, ex);
LOGGER.log(Level.FINE, msg, ex);
throw new DriverLoadException(msg, ex);
}
}
@@ -91,7 +98,7 @@ public final class DriverLoader {
} catch (MalformedURLException ex) {
final String msg = String.format("Unable to load database driver '%s'; invalid path provided '%s'",
className, file.getAbsoluteFile());
Logger.getLogger(DriverLoader.class.getName()).log(Level.FINE, msg, ex);
LOGGER.log(Level.FINE, msg, ex);
throw new DriverLoadException(msg, ex);
}
}
@@ -103,7 +110,7 @@ public final class DriverLoader {
}
});
load(className, loader);
return load(className, loader);
}
/**
@@ -111,30 +118,33 @@ public final class DriverLoader {
*
* @param className the fully qualified name of the desired class
* @param loader the class loader to use when loading the driver
* @return the loaded Driver
* @throws DriverLoadException thrown if the driver cannot be loaded
*/
private static void load(String className, ClassLoader loader) throws DriverLoadException {
private static Driver load(String className, ClassLoader loader) throws DriverLoadException {
try {
final Class c = Class.forName(className, true, loader);
//final Class c = loader.loadClass(className);
final Driver driver = (Driver) c.newInstance();
final Driver shim = new DriverShim(driver);
//using the DriverShim to get around the fact that the DriverManager won't register a driver not in the base class path
DriverManager.registerDriver(new DriverShim(driver));
DriverManager.registerDriver(shim);
return shim;
} catch (ClassNotFoundException ex) {
final String msg = String.format("Unable to load database driver '%s'", className);
Logger.getLogger(DriverLoader.class.getName()).log(Level.FINE, msg, ex);
LOGGER.log(Level.FINE, msg, ex);
throw new DriverLoadException(msg, ex);
} catch (InstantiationException ex) {
final String msg = String.format("Unable to load database driver '%s'", className);
Logger.getLogger(DriverLoader.class.getName()).log(Level.FINE, msg, ex);
LOGGER.log(Level.FINE, msg, ex);
throw new DriverLoadException(msg, ex);
} catch (IllegalAccessException ex) {
final String msg = String.format("Unable to load database driver '%s'", className);
Logger.getLogger(DriverLoader.class.getName()).log(Level.FINE, msg, ex);
LOGGER.log(Level.FINE, msg, ex);
throw new DriverLoadException(msg, ex);
} catch (SQLException ex) {
final String msg = String.format("Unable to load database driver '%s'", className);
Logger.getLogger(DriverLoader.class.getName()).log(Level.FINE, msg, ex);
LOGGER.log(Level.FINE, msg, ex);
throw new DriverLoadException(msg, ex);
}
}

View File

@@ -17,12 +17,15 @@
*/
package org.owasp.dependencycheck.data.nvdcve;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
@@ -36,6 +39,10 @@ import java.util.logging.Logger;
*/
class DriverShim implements Driver {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(DriverShim.class.getName());
/**
* The database driver being wrapped.
*/
@@ -64,6 +71,20 @@ class DriverShim implements Driver {
return this.driver.acceptsURL(url);
}
/**
* Wraps the call to the underlying driver's connect method.
*
* @param url the URL of the database
* @param info a collection of string/value pairs
* @return a Connection object
* @throws SQLException thrown if there is an error connecting to the database
* @see java.sql.Driver#connect(java.lang.String, java.util.Properties)
*/
@Override
public Connection connect(String url, Properties info) throws SQLException {
return this.driver.connect(url, info);
}
/**
* Returns the wrapped driver's major version number.
*
@@ -87,28 +108,33 @@ class DriverShim implements Driver {
}
/**
* Returns whether or not the wrapped driver is jdbcCompliant.
* Wraps the call to the underlying driver's getParentLogger method.
*
* @return true if the wrapped driver is JDBC compliant; otherwise false
* @see java.sql.Driver#jdbcCompliant()
* @return the parent's Logger
* @throws SQLFeatureNotSupportedException thrown if the feature is not supported
* @see java.sql.Driver#getParentLogger()
*/
@Override
public boolean jdbcCompliant() {
return this.driver.jdbcCompliant();
}
/**
* Wraps the call to the underlying driver's connect method.
*
* @param url the URL of the database
* @param info a collection of string/value pairs
* @return a Connection object
* @throws SQLException thrown if there is an error connecting to the database
* @see java.sql.Driver#connect(java.lang.String, java.util.Properties)
*/
@Override
public Connection connect(String url, Properties info) throws SQLException {
return this.driver.connect(url, info);
//@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
//return driver.getParentLogger();
Method m = null;
try {
m = driver.getClass().getMethod("getParentLogger");
} catch (Throwable e) {
throw new SQLFeatureNotSupportedException();
}
if (m != null) {
try {
return (Logger) m.invoke(m);
} catch (IllegalAccessException ex) {
LOGGER.log(Level.FINER, null, ex);
} catch (IllegalArgumentException ex) {
LOGGER.log(Level.FINER, null, ex);
} catch (InvocationTargetException ex) {
LOGGER.log(Level.FINER, null, ex);
}
}
throw new SQLFeatureNotSupportedException();
}
/**
@@ -126,15 +152,14 @@ class DriverShim implements Driver {
}
/**
* Wraps the call to the underlying driver's getParentLogger method.
* Returns whether or not the wrapped driver is jdbcCompliant.
*
* @return the parent's Logger
* @throws SQLFeatureNotSupportedException thrown if the feature is not supported
* @see java.sql.Driver#getParentLogger()
* @return true if the wrapped driver is JDBC compliant; otherwise false
* @see java.sql.Driver#jdbcCompliant()
*/
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return this.driver.getParentLogger();
public boolean jdbcCompliant() {
return this.driver.jdbcCompliant();
}
/**

View File

@@ -30,6 +30,11 @@ import org.owasp.dependencycheck.utils.DownloadFailedException;
*/
public class NvdCveUpdater implements CachedWebDataSource {
/**
* The logger
*/
private static final Logger LOGGER = Logger.getLogger(NvdCveUpdater.class.getName());
/**
* <p>
* Downloads the latest NVD CVE XML file from the web and imports it into the current CVE Database.</p>
@@ -44,13 +49,13 @@ public class NvdCveUpdater implements CachedWebDataSource {
task.update();
}
} catch (MalformedURLException ex) {
Logger.getLogger(NvdCveUpdater.class.getName()).log(Level.WARNING,
LOGGER.log(Level.WARNING,
"NVD CVE properties files contain an invalid URL, unable to update the data to use the most current data.");
Logger.getLogger(NvdCveUpdater.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
} catch (DownloadFailedException ex) {
Logger.getLogger(NvdCveUpdater.class.getName()).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.");
Logger.getLogger(NvdCveUpdater.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
}
}
}

View File

@@ -47,6 +47,10 @@ import org.owasp.dependencycheck.utils.Settings;
*/
public class StandardUpdate {
/**
* Static logger.
*/
private static final Logger LOGGER = Logger.getLogger(StandardUpdate.class.getName());
/**
* The max thread pool size to use when downloading files.
*/
@@ -104,7 +108,7 @@ public class StandardUpdate {
return;
}
if (maxUpdates > 3) {
Logger.getLogger(StandardUpdate.class.getName()).log(Level.INFO,
LOGGER.log(Level.INFO,
"NVD CVE requires several updates; this could take a couple of minutes.");
}
if (maxUpdates > 0) {
@@ -118,7 +122,7 @@ public class StandardUpdate {
final Set<Future<Future<ProcessTask>>> downloadFutures = new HashSet<Future<Future<ProcessTask>>>(maxUpdates);
for (NvdCveInfo cve : updateable) {
if (cve.getNeedsUpdate()) {
final CallableDownloadTask call = new CallableDownloadTask(cve, processExecutor, cveDB);
final CallableDownloadTask call = new CallableDownloadTask(cve, processExecutor, cveDB, Settings.getInstance());
downloadFutures.add(downloadExecutors.submit(call));
}
}
@@ -134,20 +138,20 @@ public class StandardUpdate {
downloadExecutors.shutdownNow();
processExecutor.shutdownNow();
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, "Thread was interupted during download", ex);
throw new UpdateException("The download was interupted", ex);
LOGGER.log(Level.FINE, "Thread was interrupted during download", ex);
throw new UpdateException("The download was interrupted", ex);
} catch (ExecutionException ex) {
downloadExecutors.shutdownNow();
processExecutor.shutdownNow();
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, "Thread was interupted during download execution", ex);
throw new UpdateException("The execution of the download was interupted", ex);
LOGGER.log(Level.FINE, "Thread was interrupted during download execution", ex);
throw new UpdateException("The execution of the download was interrupted", ex);
}
if (task == null) {
downloadExecutors.shutdownNow();
processExecutor.shutdownNow();
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, "Thread was interupted during download");
throw new UpdateException("The download was interupted; unable to complete the update");
LOGGER.log(Level.FINE, "Thread was interrupted during download");
throw new UpdateException("The download was interrupted; unable to complete the update");
} else {
processFutures.add(task);
}
@@ -161,11 +165,11 @@ public class StandardUpdate {
}
} catch (InterruptedException ex) {
processExecutor.shutdownNow();
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, "Thread was interupted during processing", ex);
LOGGER.log(Level.FINE, "Thread was interrupted during processing", ex);
throw new UpdateException(ex);
} catch (ExecutionException ex) {
processExecutor.shutdownNow();
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, "Execution Exception during process", ex);
LOGGER.log(Level.FINE, "Execution Exception during process", ex);
throw new UpdateException(ex);
} finally {
processExecutor.shutdown();
@@ -197,10 +201,10 @@ public class StandardUpdate {
updates = retrieveCurrentTimestampsFromWeb();
} catch (InvalidDataException ex) {
final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page";
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, msg, ex);
LOGGER.log(Level.FINE, msg, ex);
throw new DownloadFailedException(msg, ex);
} catch (InvalidSettingException ex) {
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, "Invalid setting found when retrieving timestamps", ex);
LOGGER.log(Level.FINE, "Invalid setting found when retrieving timestamps", ex);
throw new DownloadFailedException("Invalid settings", ex);
}
@@ -233,9 +237,7 @@ public class StandardUpdate {
} catch (NumberFormatException ex) {
final String msg = String.format("Error parsing '%s' '%s' from nvdcve.lastupdated",
DatabaseProperties.LAST_UPDATED_BASE, entry.getId());
Logger
.getLogger(StandardUpdate.class
.getName()).log(Level.FINE, msg, ex);
LOGGER.log(Level.FINE, msg, ex);
}
if (currentTimestamp == entry.getTimestamp()) {
entry.setNeedsUpdate(false);
@@ -245,11 +247,8 @@ public class StandardUpdate {
}
} catch (NumberFormatException ex) {
final String msg = "An invalid schema version or timestamp exists in the data.properties file.";
Logger
.getLogger(StandardUpdate.class
.getName()).log(Level.WARNING, msg);
Logger.getLogger(StandardUpdate.class
.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "", ex);
}
}
return updates;
@@ -292,8 +291,8 @@ public class StandardUpdate {
if (cveDB != null) {
try {
cveDB.close();
} catch (Exception ignore) {
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINEST, "Error closing the cveDB", ignore);
} catch (Throwable ignore) {
LOGGER.log(Level.FINEST, "Error closing the cveDB", ignore);
}
}
}
@@ -312,7 +311,7 @@ public class StandardUpdate {
cveDB.open();
} catch (DatabaseException ex) {
closeDataStores();
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, "Database Exception opening databases", ex);
LOGGER.log(Level.FINE, "Database Exception opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
}
}

View File

@@ -21,37 +21,25 @@ import java.util.Iterator;
import java.util.ServiceLoader;
/**
* The CachedWebDataSource Service Loader. This class loads all services that implement
* org.owasp.dependencycheck.data.update.CachedWebDataSource.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class UpdateService {
public class UpdateService {
/**
* the singleton reference to the service.
*/
private static UpdateService service;
/**
* the service loader for CachedWebDataSource.
*/
private final ServiceLoader<CachedWebDataSource> loader;
/**
* Creates a new instance of UpdateService
*/
private UpdateService() {
loader = ServiceLoader.load(CachedWebDataSource.class);
}
/**
* Retrieve the singleton instance of UpdateService.
* Creates a new instance of UpdateService.
*
* @return a singleton UpdateService.
* @param classLoader the ClassLoader to use when dynamically loading Analyzer and Update services
*/
public static synchronized UpdateService getInstance() {
if (service == null) {
service = new UpdateService();
}
return service;
public UpdateService(ClassLoader classLoader) {
loader = ServiceLoader.load(CachedWebDataSource.class, classLoader);
}
/**

View File

@@ -27,8 +27,10 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.update.NvdCveInfo;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.Settings;
/**
* A callable object to download two files.
@@ -37,26 +39,35 @@ import org.owasp.dependencycheck.utils.Downloader;
*/
public class CallableDownloadTask implements Callable<Future<ProcessTask>> {
/**
* The Logger.
*/
private static final Logger LOGGER = Logger.getLogger(CallableDownloadTask.class.getName());
/**
* Simple constructor for the callable download task.
*
* @param nvdCveInfo the NVD CVE info
* @param processor the processor service to submit the downloaded files to
* @param cveDB the CVE DB to use to store the vulnerability data
* @param settings a reference to the global settings object; this is necessary so that when the thread is started
* the dependencies have a correct reference to the global settings.
* @throws UpdateException thrown if temporary files could not be created
*/
public CallableDownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB) {
public CallableDownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB, Settings settings) throws UpdateException {
this.nvdCveInfo = nvdCveInfo;
this.processorService = processor;
this.cveDB = cveDB;
this.settings = settings;
final File file1;
final File file2;
try {
file1 = File.createTempFile("cve" + nvdCveInfo.getId() + "_", ".xml");
file2 = File.createTempFile("cve_1_2_" + nvdCveInfo.getId() + "_", ".xml");
file1 = File.createTempFile("cve" + nvdCveInfo.getId() + "_", ".xml", Settings.getTempDirectory());
file2 = File.createTempFile("cve_1_2_" + nvdCveInfo.getId() + "_", ".xml", Settings.getTempDirectory());
} catch (IOException ex) {
return;
throw new UpdateException("Unable to create temporary files", ex);
}
this.first = file1;
this.second = file2;
@@ -74,6 +85,10 @@ public class CallableDownloadTask implements Callable<Future<ProcessTask>> {
* The NVD CVE Meta Data.
*/
private NvdCveInfo nvdCveInfo;
/**
* A reference to the global settings object.
*/
private Settings settings;
/**
* Get the value of nvdCveInfo.
@@ -162,30 +177,33 @@ public class CallableDownloadTask implements Callable<Future<ProcessTask>> {
@Override
public Future<ProcessTask> call() throws Exception {
try {
Settings.setInstance(settings);
final URL url1 = new URL(nvdCveInfo.getUrl());
final URL url2 = new URL(nvdCveInfo.getOldSchemaVersionUrl());
String msg = String.format("Download Started for NVD CVE - %s", nvdCveInfo.getId());
Logger.getLogger(CallableDownloadTask.class.getName()).log(Level.INFO, msg);
LOGGER.log(Level.INFO, msg);
try {
Downloader.fetchFile(url1, first);
Downloader.fetchFile(url2, second);
} catch (DownloadFailedException ex) {
msg = String.format("Download Failed for NVD CVE - %s%nSome CVEs may not be reported.", nvdCveInfo.getId());
Logger.getLogger(CallableDownloadTask.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(CallableDownloadTask.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, null, ex);
return null;
}
msg = String.format("Download Complete for NVD CVE - %s", nvdCveInfo.getId());
Logger.getLogger(CallableDownloadTask.class.getName()).log(Level.INFO, msg);
LOGGER.log(Level.INFO, msg);
final ProcessTask task = new ProcessTask(cveDB, this);
final ProcessTask task = new ProcessTask(cveDB, this, settings);
return this.processorService.submit(task);
} catch (Throwable ex) {
final String msg = String.format("An exception occurred downloading NVD CVE - %s%nSome CVEs may not be reported.", nvdCveInfo.getId());
Logger.getLogger(CallableDownloadTask.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(CallableDownloadTask.class.getName()).log(Level.FINE, "Download Task Failed", ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "Download Task Failed", ex);
} finally {
Settings.cleanup();
}
return null;
}

View File

@@ -32,11 +32,11 @@ import javax.xml.parsers.SAXParserFactory;
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.StandardUpdate;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
import org.owasp.dependencycheck.data.update.xml.NvdCve12Handler;
import org.owasp.dependencycheck.data.update.xml.NvdCve20Handler;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.utils.Settings;
import org.xml.sax.SAXException;
/**
@@ -46,6 +46,10 @@ import org.xml.sax.SAXException;
*/
public class ProcessTask implements Callable<ProcessTask> {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(ProcessTask.class.getName());
/**
* A field to store any update exceptions that occur during the "call".
*/
@@ -80,17 +84,24 @@ public class ProcessTask implements Callable<ProcessTask> {
* A reference to the properties.
*/
private final DatabaseProperties properties;
/**
* A reference to the global settings object.
*/
private Settings settings;
/**
* Constructs a new ProcessTask used to process an NVD CVE update.
*
* @param cveDB the data store object
* @param filePair the download task that contains the URL references to download
* @param settings a reference to the global settings object; this is necessary so that when the thread is started
* the dependencies have a correct reference to the global settings.
*/
public ProcessTask(final CveDB cveDB, final CallableDownloadTask filePair) {
public ProcessTask(final CveDB cveDB, final CallableDownloadTask filePair, Settings settings) {
this.cveDB = cveDB;
this.filePair = filePair;
this.properties = cveDB.getDatabaseProperties();
this.settings = settings;
}
/**
@@ -103,9 +114,12 @@ public class ProcessTask implements Callable<ProcessTask> {
@Override
public ProcessTask call() throws Exception {
try {
Settings.setInstance(settings);
processFiles();
} catch (UpdateException ex) {
this.exception = ex;
} finally {
Settings.cleanup();
}
return this;
}
@@ -145,7 +159,7 @@ public class ProcessTask implements Callable<ProcessTask> {
*/
private void processFiles() throws UpdateException {
String msg = String.format("Processing Started for NVD CVE - %s", filePair.getNvdCveInfo().getId());
Logger.getLogger(StandardUpdate.class.getName()).log(Level.INFO, msg);
LOGGER.log(Level.INFO, msg);
try {
importXML(filePair.getFirst(), filePair.getSecond());
cveDB.commit();
@@ -168,6 +182,6 @@ public class ProcessTask implements Callable<ProcessTask> {
filePair.cleanup();
}
msg = String.format("Processing Complete for NVD CVE - %s", filePair.getNvdCveInfo().getId());
Logger.getLogger(StandardUpdate.class.getName()).log(Level.INFO, msg);
LOGGER.log(Level.INFO, msg);
}
}

View File

@@ -40,6 +40,10 @@ import org.xml.sax.helpers.DefaultHandler;
*/
public class NvdCve20Handler extends DefaultHandler {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(NvdCve20Handler.class.getName());
/**
* the current supported schema version.
*/
@@ -168,8 +172,8 @@ public class NvdCve20Handler extends DefaultHandler {
final float score = Float.parseFloat(nodeText.toString());
vulnerability.setCvssScore(score);
} catch (NumberFormatException ex) {
Logger.getLogger(NvdCve20Handler.class.getName()).log(Level.SEVERE, "Error parsing CVSS Score.");
Logger.getLogger(NvdCve20Handler.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, "Error parsing CVSS Score.");
LOGGER.log(Level.FINE, null, ex);
}
nodeText = null;
} else if (current.isCVSSAccessVectorNode()) {

View File

@@ -20,8 +20,6 @@ package org.owasp.dependencycheck.dependency;
import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -39,6 +37,10 @@ import org.owasp.dependencycheck.utils.FileUtils;
*/
public class Dependency implements Comparable<Dependency> {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(Dependency.class.getName());
/**
* The actual file path of the dependency on disk.
*/
@@ -89,6 +91,8 @@ public class Dependency implements Comparable<Dependency> {
versionEvidence = new EvidenceCollection();
identifiers = new TreeSet<Identifier>();
vulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
suppressedIdentifiers = new TreeSet<Identifier>();
suppressedVulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
}
/**
@@ -108,16 +112,26 @@ public class Dependency implements Comparable<Dependency> {
/**
* Returns the file name of the dependency.
*
* @return the file name of the dependency.
* @return the file name of the dependency
*/
public String getFileName() {
return this.fileName;
}
/**
* Returns the file name of the dependency with the backslash escaped for use in JavaScript. This is a complete hack
* as I could not get the replace to work in the template itself.
*
* @return the file name of the dependency with the backslash escaped for use in JavaScript
*/
public String getFileNameForJavaScript() {
return this.fileName.replace("\\", "\\\\");
}
/**
* Sets the file name of the dependency.
*
* @param fileName the file name of the dependency.
* @param fileName the file name of the dependency
*/
public void setFileName(String fileName) {
this.fileName = fileName;
@@ -126,7 +140,7 @@ public class Dependency implements Comparable<Dependency> {
/**
* Sets the actual file path of the dependency on disk.
*
* @param actualFilePath the file path of the dependency.
* @param actualFilePath the file path of the dependency
*/
public void setActualFilePath(String actualFilePath) {
this.actualFilePath = actualFilePath;
@@ -139,16 +153,25 @@ public class Dependency implements Comparable<Dependency> {
/**
* Gets the file path of the dependency.
*
* @return the file path of the dependency.
* @return the file path of the dependency
*/
public String getActualFilePath() {
return this.actualFilePath;
}
/**
* Gets a reference to the File object.
*
* @return the File object
*/
public File getActualFile() {
return new File(this.actualFilePath);
}
/**
* Sets the file path of the dependency.
*
* @param filePath the file path of the dependency.
* @param filePath the file path of the dependency
*/
public void setFilePath(String filePath) {
this.filePath = filePath;
@@ -161,7 +184,7 @@ public class Dependency implements Comparable<Dependency> {
* <b>NOTE:</b> This may not be the actual path of the file on disk. The actual path of the file on disk can be
* obtained via the getActualFilePath().</p>
*
* @return the file path of the dependency.
* @return the file path of the dependency
*/
public String getFilePath() {
return this.filePath;
@@ -170,7 +193,7 @@ public class Dependency implements Comparable<Dependency> {
/**
* Sets the file name of the dependency.
*
* @param fileExtension the file name of the dependency.
* @param fileExtension the file name of the dependency
*/
public void setFileExtension(String fileExtension) {
this.fileExtension = fileExtension;
@@ -179,7 +202,7 @@ public class Dependency implements Comparable<Dependency> {
/**
* Gets the file extension of the dependency.
*
* @return the file extension of the dependency.
* @return the file extension of the dependency
*/
public String getFileExtension() {
return this.fileExtension;
@@ -224,7 +247,7 @@ public class Dependency implements Comparable<Dependency> {
/**
* Returns a List of Identifiers.
*
* @return an ArrayList of Identifiers.
* @return an ArrayList of Identifiers
*/
public Set<Identifier> getIdentifiers() {
return this.identifiers;
@@ -233,7 +256,7 @@ public class Dependency implements Comparable<Dependency> {
/**
* Sets a List of Identifiers.
*
* @param identifiers A list of Identifiers.
* @param identifiers A list of Identifiers
*/
public void setIdentifiers(Set<Identifier> identifiers) {
this.identifiers = identifiers;
@@ -273,6 +296,69 @@ public class Dependency implements Comparable<Dependency> {
public void addIdentifier(Identifier identifier) {
this.identifiers.add(identifier);
}
/**
* A set of identifiers that have been suppressed.
*/
private Set<Identifier> suppressedIdentifiers;
/**
* Get the value of suppressedIdentifiers.
*
* @return the value of suppressedIdentifiers
*/
public Set<Identifier> getSuppressedIdentifiers() {
return suppressedIdentifiers;
}
/**
* Set the value of suppressedIdentifiers.
*
* @param suppressedIdentifiers new value of suppressedIdentifiers
*/
public void setSuppressedIdentifiers(Set<Identifier> suppressedIdentifiers) {
this.suppressedIdentifiers = suppressedIdentifiers;
}
/**
* Adds an identifier to the list of suppressed identifiers.
*
* @param identifier an identifier that was suppressed.
*/
public void addSuppressedIdentifier(Identifier identifier) {
this.suppressedIdentifiers.add(identifier);
}
/**
* A set of vulnerabilities that have been suppressed.
*/
private SortedSet<Vulnerability> suppressedVulnerabilities;
/**
* Get the value of suppressedVulnerabilities.
*
* @return the value of suppressedVulnerabilities
*/
public SortedSet<Vulnerability> getSuppressedVulnerabilities() {
return suppressedVulnerabilities;
}
/**
* Set the value of suppressedVulnerabilities.
*
* @param suppressedVulnerabilities new value of suppressedVulnerabilities
*/
public void setSuppressedVulnerabilities(SortedSet<Vulnerability> suppressedVulnerabilities) {
this.suppressedVulnerabilities = suppressedVulnerabilities;
}
/**
* Adds a vulnerability to the set of suppressed vulnerabilities.
*
* @param vulnerability the vulnerability that was suppressed
*/
public void addSuppressedVulnerability(Vulnerability vulnerability) {
this.suppressedVulnerabilities.add(vulnerability);
}
/**
* Returns the evidence used to identify this dependency.
@@ -318,37 +404,6 @@ public class Dependency implements Comparable<Dependency> {
public EvidenceCollection getVersionEvidence() {
return this.versionEvidence;
}
/**
* A list of exceptions that occurred during analysis of this dependency.
*/
private List<Exception> analysisExceptions = new ArrayList<Exception>();
/**
* Get the value of analysisExceptions.
*
* @return the value of analysisExceptions
*/
public List<Exception> getAnalysisExceptions() {
return analysisExceptions;
}
/**
* Set the value of analysisExceptions.
*
* @param analysisExceptions new value of analysisExceptions
*/
public void setAnalysisExceptions(List<Exception> analysisExceptions) {
this.analysisExceptions = analysisExceptions;
}
/**
* Adds an exception to the analysis exceptions collection.
*
* @param ex an exception.
*/
public void addAnalysisException(Exception ex) {
this.analysisExceptions.add(ex);
}
/**
* The description of the JAR file.
*/
@@ -429,12 +484,12 @@ public class Dependency implements Comparable<Dependency> {
sha1 = Checksum.getSHA1Checksum(file);
} catch (IOException ex) {
final String msg = String.format("Unable to read '%s' to determine hashes.", file.getName());
Logger.getLogger(Dependency.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(Dependency.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, null, ex);
} catch (NoSuchAlgorithmException ex) {
final String msg = "Unable to use MD5 of SHA1 checksums.";
Logger.getLogger(Dependency.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(Dependency.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, null, ex);
}
this.setMd5sum(md5);
this.setSha1sum(sha1);
@@ -535,10 +590,6 @@ public class Dependency implements Comparable<Dependency> {
if (this.versionEvidence != other.versionEvidence && (this.versionEvidence == null || !this.versionEvidence.equals(other.versionEvidence))) {
return false;
}
if (this.analysisExceptions != other.analysisExceptions
&& (this.analysisExceptions == null || !this.analysisExceptions.equals(other.analysisExceptions))) {
return false;
}
if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) {
return false;
}
@@ -573,7 +624,6 @@ public class Dependency implements Comparable<Dependency> {
hash = 47 * hash + (this.vendorEvidence != null ? this.vendorEvidence.hashCode() : 0);
hash = 47 * hash + (this.productEvidence != null ? this.productEvidence.hashCode() : 0);
hash = 47 * hash + (this.versionEvidence != null ? this.versionEvidence.hashCode() : 0);
hash = 47 * hash + (this.analysisExceptions != null ? this.analysisExceptions.hashCode() : 0);
hash = 47 * hash + (this.description != null ? this.description.hashCode() : 0);
hash = 47 * hash + (this.license != null ? this.license.hashCode() : 0);
hash = 47 * hash + (this.vulnerabilities != null ? this.vulnerabilities.hashCode() : 0);

View File

@@ -38,6 +38,10 @@ import org.owasp.dependencycheck.utils.UrlStringUtils;
*/
public class EvidenceCollection implements Iterable<Evidence> {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(EvidenceCollection.class.getName());
/**
* Used to iterate over highest confidence evidence contained in the collection.
*/
@@ -360,7 +364,7 @@ public class EvidenceCollection implements Iterable<Evidence> {
final List<String> data = UrlStringUtils.extractImportantUrlData(part);
sb.append(' ').append(StringUtils.join(data, ' '));
} catch (MalformedURLException ex) {
Logger.getLogger(EvidenceCollection.class.getName()).log(Level.INFO, "error parsing " + part, ex);
LOGGER.log(Level.FINE, "error parsing " + part, ex);
sb.append(' ').append(part);
}
} else {

View File

@@ -31,6 +31,10 @@ import org.owasp.dependencycheck.data.cpe.IndexEntry;
*/
public class VulnerableSoftware extends IndexEntry implements Serializable, Comparable<VulnerableSoftware> {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(VulnerableSoftware.class.getName());
/**
* The serial version UID.
*/
@@ -46,8 +50,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
parseName(cpe);
} catch (UnsupportedEncodingException ex) {
final String msg = String.format("Character encoding is unsupported for CPE '%s'.", cpe);
Logger.getLogger(VulnerableSoftware.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(VulnerableSoftware.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, null, ex);
setName(cpe);
}
}
@@ -184,13 +188,21 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
if (subMax > 0) {
for (int x = 0; result == 0 && x < subMax; x++) {
if (isPositiveInteger(subLeft[x]) && isPositiveInteger(subRight[x])) {
final int iLeft = Integer.parseInt(subLeft[x]);
final int iRight = Integer.parseInt(subRight[x]);
if (iLeft != iRight) {
if (iLeft > iRight) {
result = 2;
} else {
result = -2;
try {
result = Long.valueOf(subLeft[x]).compareTo(Long.valueOf(subRight[x]));
// final long iLeft = Long.parseLong(subLeft[x]);
// final long iRight = Long.parseLong(subRight[x]);
// if (iLeft != iRight) {
// if (iLeft > iRight) {
// result = 2;
// } else {
// result = -2;
// }
// }
} catch (NumberFormatException ex) {
//ignore the exception - they obviously aren't numbers
if (!subLeft[x].equalsIgnoreCase(subRight[x])) {
result = subLeft[x].compareToIgnoreCase(subRight[x]);
}
}
} else {

View File

@@ -0,0 +1,68 @@
/*
* 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.exception;
import java.io.IOException;
/**
* An exception used when using @{link DependencyCheckScanAgent} to conduct a scan and the scan fails.
*
* @author Steve Springett <steve.springett@owasp.org>
*/
public class ScanAgentException extends IOException {
/**
* The serial version uid.
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new ScanAgentException.
*/
public ScanAgentException() {
super();
}
/**
* Creates a new ScanAgentException.
*
* @param msg a message for the exception.
*/
public ScanAgentException(String msg) {
super(msg);
}
/**
* Creates a new NoDataException.
*
* @param ex the cause of the exception.
*/
public ScanAgentException(Throwable ex) {
super(ex);
}
/**
* Creates a new ScanAgentException.
*
* @param msg a message for the exception.
* @param ex the cause of the exception.
*/
public ScanAgentException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -56,16 +56,16 @@ public class MavenNamespaceFilter extends XMLFilterImpl {
* @param uri the uri
* @param localName the localName
* @param qName the qualified name
* @param atts the attributes
* @param attributes the attributes
* @throws SAXException thrown if there is a SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
super.startElement(NAMESPACE, localName, qName, atts);
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(NAMESPACE, localName, qName, attributes);
}
/**
* Indicatees the start of the document.
* Indicates the start of the document.
*
* @param uri the uri
* @param localName the localName

View File

@@ -0,0 +1,74 @@
/*
* 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.reporting;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang.StringEscapeUtils;
/**
* An extremely simple wrapper around various escape utils to perform URL and HTML encoding within the reports. This
* class was created to simplify the velocity configuration and avoid using the "built-in" escape tool.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class EscapeTool {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(EscapeTool.class.getName());
/**
* URL Encodes the provided text.
*
* @param text the text to encode
* @return the URL encoded text
*/
public String url(String text) {
try {
return URLEncoder.encode(text, "UTF-8");
} catch (UnsupportedEncodingException ex) {
LOGGER.log(Level.WARNING, "UTF-8 is not supported?");
LOGGER.log(Level.INFO, null, ex);
}
return "";
}
/**
* HTML Encodes the provided text.
*
* @param text the text to encode
* @return the HTML encoded text
*/
public String html(String text) {
return StringEscapeUtils.escapeHtml(text);
}
/**
* XML Encodes the provided text.
*
* @param text the text to encode
* @return the XML encoded text
*/
public String xml(String text) {
return StringEscapeUtils.escapeXml(text);
}
}

View File

@@ -26,15 +26,16 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.apache.velocity.tools.ToolManager;
import org.apache.velocity.tools.config.EasyFactoryConfiguration;
import org.owasp.dependencycheck.analyzer.Analyzer;
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.dependency.Dependency;
@@ -48,6 +49,11 @@ import org.owasp.dependencycheck.utils.Settings;
*/
public class ReportGenerator {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(ReportGenerator.class.getName());
/**
* An enumeration of the report formats.
*/
@@ -93,10 +99,20 @@ public class ReportGenerator {
engine.init();
final DateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy 'at' HH:mm:ss z");
final DateFormat dateFormatXML = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
final Date d = new Date();
final String scanDate = dateFormat.format(d);
final String scanDateXML = dateFormatXML.format(d);
final EscapeTool enc = new EscapeTool();
context.put("applicationName", applicationName);
context.put("dependencies", dependencies);
context.put("analyzers", analyzers);
context.put("properties", properties);
context.put("scanDate", scanDate);
context.put("scanDateXML", scanDateXML);
context.put("enc", enc);
context.put("version", Settings.getString("application.version", "Unknown"));
}
@@ -106,28 +122,19 @@ public class ReportGenerator {
* @return a velocity engine.
*/
private VelocityEngine createVelocityEngine() {
final VelocityEngine ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, VelocityLoggerRedirect.class.getName());
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
return ve;
final VelocityEngine engine = new VelocityEngine();
// Logging redirection for Velocity - Required by Jenkins and other server applications
engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, VelocityLoggerRedirect.class.getName());
return engine;
}
/**
* Creates a new Velocity Context initialized with escape and date tools.
* Creates a new Velocity Context.
*
* @return a Velocity Context.
*/
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RV_RETURN_VALUE_IGNORED_INFERRED",
justification = "No plan to fix this style issue")
private Context createContext() {
final ToolManager manager = new ToolManager();
final Context c = manager.createContext();
final EasyFactoryConfiguration config = new EasyFactoryConfiguration();
config.addDefaultTools();
config.toolbox("application").tool("esc", "org.apache.velocity.tools.generic.EscapeTool").tool("org.apache.velocity.tools.generic.DateTool");
manager.configure(config);
return c;
return new VelocityContext();
}
/**
@@ -140,13 +147,13 @@ public class ReportGenerator {
*/
public void generateReports(String outputDir, Format format) throws IOException, Exception {
if (format == Format.XML || format == Format.ALL) {
generateReport("XmlReport", outputDir + File.separator + "DependencyCheck-Report.xml");
generateReport("XmlReport", outputDir + File.separator + "dependency-check-report.xml");
}
if (format == Format.HTML || format == Format.ALL) {
generateReport("HtmlReport", outputDir + File.separator + "DependencyCheck-Report.html");
generateReport("HtmlReport", outputDir + File.separator + "dependency-check-report.html");
}
if (format == Format.VULN || format == Format.ALL) {
generateReport("VulnerabilityReport", outputDir + File.separator + "DependencyCheck-Vulnerability.html");
generateReport("VulnerabilityReport", outputDir + File.separator + "dependency-check-vulnerability.html");
}
}
@@ -196,8 +203,8 @@ public class ReportGenerator {
input = new FileInputStream(f);
} catch (FileNotFoundException ex) {
final String msg = "Unable to generate the report, the report template file could not be found.";
Logger.getLogger(ReportGenerator.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(ReportGenerator.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, msg);
LOGGER.log(Level.FINE, null, ex);
}
} else {
templatePath = "templates/" + templateName + ".vsl";
@@ -232,20 +239,20 @@ public class ReportGenerator {
try {
writer.close();
} catch (IOException ex) {
Logger.getLogger(ReportGenerator.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException ex) {
Logger.getLogger(ReportGenerator.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
try {
reader.close();
} catch (IOException ex) {
Logger.getLogger(ReportGenerator.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}

View File

@@ -19,7 +19,6 @@ package org.owasp.dependencycheck.reporting;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.log.LogChute;
@@ -37,6 +36,11 @@ import org.apache.velocity.runtime.log.LogChute;
*/
public class VelocityLoggerRedirect implements LogChute {
/**
* The Logger.
*/
private static final Logger LOGGER = Logger.getLogger(VelocityLoggerRedirect.class.getName());
/**
* This will be invoked once by the LogManager.
*
@@ -54,7 +58,7 @@ public class VelocityLoggerRedirect implements LogChute {
* @param message the message to be logged
*/
public void log(int level, String message) {
Logger.getLogger(Velocity.class.getName()).log(getLevel(level), message);
LOGGER.log(getLevel(level), message);
}
/**
@@ -66,7 +70,7 @@ public class VelocityLoggerRedirect implements LogChute {
* @param t a throwable to log
*/
public void log(int level, String message, Throwable t) {
Logger.getLogger(Velocity.class.getName()).log(getLevel(level), message, t);
LOGGER.log(getLevel(level), message, t);
}
/**

View File

@@ -30,6 +30,11 @@ import org.xml.sax.SAXParseException;
*/
public class SuppressionErrorHandler implements ErrorHandler {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(SuppressionErrorHandler.class.getName());
/**
* Builds a prettier exception message.
*
@@ -65,7 +70,7 @@ public class SuppressionErrorHandler implements ErrorHandler {
*/
@Override
public void warning(SAXParseException ex) throws SAXException {
Logger.getLogger(SuppressionErrorHandler.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
}
/**

View File

@@ -164,7 +164,7 @@ public class SuppressionHandler extends DefaultHandler {
pt.setRegex(Boolean.parseBoolean(regex));
}
final String caseSensitive = currentAttributes.getValue("caseSensitive");
if (regex != null) {
if (caseSensitive != null) {
pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
}
}

View File

@@ -41,6 +41,10 @@ import org.xml.sax.XMLReader;
*/
public class SuppressionParser {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(SuppressionParser.class.getName());
/**
* JAXP Schema Language. Source: http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
*/
@@ -85,16 +89,16 @@ public class SuppressionParser {
return handler.getSuppressionRules();
} catch (ParserConfigurationException ex) {
Logger.getLogger(SuppressionParser.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new SuppressionParseException(ex);
} catch (SAXException ex) {
Logger.getLogger(SuppressionParser.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new SuppressionParseException(ex);
} catch (FileNotFoundException ex) {
Logger.getLogger(SuppressionParser.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new SuppressionParseException(ex);
} catch (IOException ex) {
Logger.getLogger(SuppressionParser.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new SuppressionParseException(ex);
}
}

View File

@@ -254,6 +254,7 @@ public class SuppressionRule {
final Identifier i = itr.next();
for (PropertyType c : this.cpe) {
if (cpeMatches(c, i)) {
dependency.addSuppressedIdentifier(i);
itr.remove();
break;
}
@@ -292,6 +293,7 @@ public class SuppressionRule {
}
}
if (remove) {
dependency.addSuppressedVulnerability(v);
itr.remove();
}
}

View File

@@ -20,7 +20,11 @@ import java.util.logging.Logger;
*
*/
public final class Checksum {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(Checksum.class.getName());
/**
* Private constructor for a utility class.
*/
@@ -57,7 +61,7 @@ public final class Checksum {
try {
fis.close();
} catch (IOException ex) {
Logger.getLogger(Checksum.class.getName()).log(Level.FINEST, "Error closing file '" + file.getName() + "'.", ex);
LOGGER.log(Level.FINEST, "Error closing file '" + file.getName() + "'.", ex);
}
}
}

View File

@@ -23,7 +23,6 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
/**
@@ -32,6 +31,11 @@ import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
*/
public final class DBUtils {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(DBUtils.class.getName());
/**
* Private constructor for a utility class.
*/
@@ -70,8 +74,7 @@ public final class DBUtils {
try {
statement.close();
} catch (SQLException ex) {
Logger.getLogger(CveDB.class
.getName()).log(Level.FINEST, statement.toString(), ex);
LOGGER.log(Level.FINEST, statement.toString(), ex);
}
}
}
@@ -86,8 +89,7 @@ public final class DBUtils {
try {
rs.close();
} catch (SQLException ex) {
Logger.getLogger(CveDB.class
.getName()).log(Level.FINEST, rs.toString(), ex);
LOGGER.log(Level.FINEST, rs.toString(), ex);
}
}
}

View File

@@ -47,10 +47,10 @@ public class DependencyVersion implements Iterable, Comparable<DependencyVersion
/**
* Constructor for a DependencyVersion that will parse a version string.
* <b>Note</b>, this should only be used when the version passed in is already known to be a well formated version
* <b>Note</b>, this should only be used when the version passed in is already known to be a well formatted version
* number. Otherwise, DependencyVersionUtil.parseVersion() should be used instead.
*
* @param version the well formated version number to parse
* @param version the well formatted version number to parse
*/
public DependencyVersion(String version) {
parseVersion(version);

View File

@@ -22,12 +22,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.logging.Level;
@@ -42,6 +37,11 @@ import java.util.zip.InflaterInputStream;
*/
public final class Downloader {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(Downloader.class.getName());
/**
* Private constructor for utility class.
*/
@@ -51,68 +51,101 @@ public final class Downloader {
/**
* Retrieves a file from a given URL and saves it to the outputPath.
*
* @param url the URL of the file to download.
* @param outputPath the path to the save the file to.
* @throws DownloadFailedException is thrown if there is an error downloading the file.
* @param url the URL of the file to download
* @param outputPath the path to the save the file to
* @throws DownloadFailedException is thrown if there is an error downloading the file
*/
public static void fetchFile(URL url, File outputPath) throws DownloadFailedException {
HttpURLConnection conn = null;
try {
conn = Downloader.getConnection(url);
conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
conn.connect();
} catch (IOException ex) {
try {
if (conn != null) {
conn.disconnect();
}
} finally {
conn = null;
}
throw new DownloadFailedException("Error downloading file.", ex);
}
final String encoding = conn.getContentEncoding();
fetchFile(url, outputPath, true);
}
BufferedOutputStream writer = null;
InputStream reader = null;
try {
if (encoding != null && "gzip".equalsIgnoreCase(encoding)) {
reader = new GZIPInputStream(conn.getInputStream());
} else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) {
reader = new InflaterInputStream(conn.getInputStream());
/**
* Retrieves a file from a given URL and saves it to the outputPath.
*
* @param url the URL of the file to download
* @param outputPath the path to the save the file to
* @param useProxy whether to use the configured proxy when downloading files
* @throws DownloadFailedException is thrown if there is an error downloading the file
*/
public static void fetchFile(URL url, File outputPath, boolean useProxy) throws DownloadFailedException {
if ("file".equalsIgnoreCase(url.getProtocol())) {
File file;
try {
file = new File(url.toURI());
} catch (URISyntaxException ex) {
final String msg = String.format("Download failed, unable to locate '%s'", url.toString());
throw new DownloadFailedException(msg);
}
if (file.exists()) {
try {
org.apache.commons.io.FileUtils.copyFile(file, outputPath);
} catch (IOException ex) {
final String msg = String.format("Download failed, unable to copy '%s'", url.toString());
throw new DownloadFailedException(msg);
}
} else {
reader = conn.getInputStream();
}
writer = new BufferedOutputStream(new FileOutputStream(outputPath));
final byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = reader.read(buffer)) > 0) {
writer.write(buffer, 0, bytesRead);
}
} catch (Exception ex) {
throw new DownloadFailedException("Error saving downloaded file.", ex);
} finally {
if (writer != null) {
try {
writer.close();
} catch (Exception ex) {
Logger.getLogger(Downloader.class.getName()).log(Level.FINEST,
"Error closing the writer in Downloader.", ex);
}
}
if (reader != null) {
try {
reader.close();
} catch (Exception ex) {
Logger.getLogger(Downloader.class.getName()).log(Level.FINEST,
"Error closing the reader in Downloader.", ex);
}
final String msg = String.format("Download failed, file does not exist '%s'", url.toString());
throw new DownloadFailedException(msg);
}
} else {
HttpURLConnection conn = null;
try {
conn.disconnect();
conn = URLConnectionFactory.createHttpURLConnection(url, useProxy);
conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
conn.connect();
} catch (IOException ex) {
try {
if (conn != null) {
conn.disconnect();
}
} finally {
conn = null;
}
throw new DownloadFailedException("Error downloading file.", ex);
}
final String encoding = conn.getContentEncoding();
BufferedOutputStream writer = null;
InputStream reader = null;
try {
if (encoding != null && "gzip".equalsIgnoreCase(encoding)) {
reader = new GZIPInputStream(conn.getInputStream());
} else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) {
reader = new InflaterInputStream(conn.getInputStream());
} else {
reader = conn.getInputStream();
}
writer = new BufferedOutputStream(new FileOutputStream(outputPath));
final byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = reader.read(buffer)) > 0) {
writer.write(buffer, 0, bytesRead);
}
} catch (Throwable ex) {
throw new DownloadFailedException("Error saving downloaded file.", ex);
} finally {
conn = null;
if (writer != null) {
try {
writer.close();
} catch (Throwable ex) {
LOGGER.log(Level.FINEST,
"Error closing the writer in Downloader.", ex);
}
}
if (reader != null) {
try {
reader.close();
} catch (Throwable ex) {
LOGGER.log(Level.FINEST,
"Error closing the reader in Downloader.", ex);
}
}
try {
conn.disconnect();
} finally {
conn = null;
}
}
}
}
@@ -127,20 +160,11 @@ public final class Downloader {
*/
public static long getLastModified(URL url) throws DownloadFailedException {
long timestamp = 0;
//TODO add the FPR protocol?
//TODO add the FTP protocol?
if ("file".equalsIgnoreCase(url.getProtocol())) {
File lastModifiedFile;
try {
// if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
// String filePath = url.toString();
// if (filePath.matches("file://[a-zA-Z]:.*")) {
// f = new File(filePath.substring(7));
// } else {
// f = new File(url.toURI());
// }
// } else {
lastModifiedFile = new File(url.toURI());
// }
} catch (URISyntaxException ex) {
final String msg = String.format("Unable to locate '%s'; is the cve.url-2.0.modified property set correctly?", url.toString());
throw new DownloadFailedException(msg);
@@ -149,11 +173,13 @@ public final class Downloader {
} else {
HttpURLConnection conn = null;
try {
conn = Downloader.getConnection(url);
conn = URLConnectionFactory.createHttpURLConnection(url);
conn.setRequestMethod("HEAD");
conn.connect();
timestamp = conn.getLastModified();
} catch (Exception ex) {
} catch (URLConnectionFailureException ex) {
throw new DownloadFailedException("Error creating URL Connection for HTTP HEAD request.", ex);
} catch (IOException ex) {
throw new DownloadFailedException("Error making HTTP HEAD request.", ex);
} finally {
if (conn != null) {
@@ -167,56 +193,4 @@ public final class Downloader {
}
return timestamp;
}
/**
* Utility method to get an HttpURLConnection. If the app is configured to use a proxy this method will retrieve the
* proxy settings and use them when setting up the connection.
*
* @param url the url to connect to
* @return an HttpURLConnection
* @throws DownloadFailedException thrown if there is an exception
*/
private static HttpURLConnection getConnection(URL url) throws DownloadFailedException {
HttpURLConnection conn = null;
Proxy proxy = null;
final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_URL);
try {
if (proxyUrl != null) {
final int proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT);
final SocketAddress addr = new InetSocketAddress(proxyUrl, proxyPort);
final String username = Settings.getString(Settings.KEYS.PROXY_USERNAME);
final String password = Settings.getString(Settings.KEYS.PROXY_PASSWORD);
if (username != null && password != null) {
final Authenticator auth = new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
if (getRequestorType().equals(RequestorType.PROXY)) {
return new PasswordAuthentication(username, password.toCharArray());
}
return super.getPasswordAuthentication();
}
};
Authenticator.setDefault(auth);
}
proxy = new Proxy(Proxy.Type.HTTP, addr);
conn = (HttpURLConnection) url.openConnection(proxy);
} else {
conn = (HttpURLConnection) url.openConnection();
}
final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 60000);
conn.setConnectTimeout(timeout);
} catch (IOException ex) {
if (conn != null) {
try {
conn.disconnect();
} finally {
conn = null;
}
}
throw new DownloadFailedException("Error getting connection.", ex);
}
return conn;
}
}

View File

@@ -26,6 +26,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
@@ -39,6 +40,20 @@ import org.owasp.dependencycheck.Engine;
*/
public final class FileUtils {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(FileUtils.class.getName());
/**
* Bit bucket for non-Windows systems
*/
private static final String BIT_BUCKET_UNIX = "/dev/null";
/**
* Bit bucket for Windows systems (yes, only one 'L')
*/
private static final String BIT_BUCKET_WIN = "NUL";
/**
* The buffer size to use when extracting files from the archive.
*/
@@ -69,23 +84,35 @@ public final class FileUtils {
* Deletes a file. If the File is a directory it will recursively delete the contents.
*
* @param file the File to delete
* @throws IOException is thrown if the file could not be deleted
* @return true if the file was deleted successfully, otherwise false
*/
public static void delete(File file) throws IOException {
if (file.isDirectory()) {
for (File c : file.listFiles()) {
delete(c);
}
}
public static boolean delete(File file) {
boolean success = true;
if (!org.apache.commons.io.FileUtils.deleteQuietly(file)) {
throw new FileNotFoundException("Failed to delete file: " + file);
success = false;
final String msg = String.format("Failed to delete file: %s; attempting to delete on exit.", file.getPath());
LOGGER.log(Level.FINE, msg);
file.deleteOnExit();
}
/* else {
//delete on exit was a bad idea. if for some reason the file can't be deleted
// this will cause a newly constructed file to be deleted and a subsequent run may fail.
// still not sure why a file fails to be deleted, but can be overwritten... odd.
file.deleteOnExit();
}*/
return success;
}
/**
* Generates a new temporary file name that is guaranteed to be unique.
*
* @param prefix the prefix for the file name to generate
* @param extension the extension of the generated file name
* @return a temporary File
* @throws java.io.IOException thrown if the temporary folder could not be created
*/
public static File getTempFile(String prefix, String extension) throws IOException {
final File dir = Settings.getTempDirectory();
final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension);
final File tempFile = new File(dir, tempFileName);
if (tempFile.exists()) {
return getTempFile(prefix, extension);
}
return tempFile;
}
/**
@@ -160,7 +187,7 @@ public final class FileUtils {
try {
fis = new FileInputStream(archive);
} catch (FileNotFoundException ex) {
Logger.getLogger(FileUtils.class.getName()).log(Level.INFO, null, ex);
LOGGER.log(Level.FINE, null, ex);
throw new ExtractionException("Archive file was not found.", ex);
}
zis = new ZipInputStream(new BufferedInputStream(fis));
@@ -189,11 +216,11 @@ public final class FileUtils {
}
bos.flush();
} catch (FileNotFoundException ex) {
Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
final String msg = String.format("Unable to find file '%s'.", file.getName());
throw new ExtractionException(msg, ex);
} catch (IOException ex) {
Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.FINE, null, ex);
final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
throw new ExtractionException(msg, ex);
} finally {
@@ -201,7 +228,7 @@ public final class FileUtils {
try {
bos.close();
} catch (IOException ex) {
Logger.getLogger(FileUtils.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}
@@ -210,14 +237,27 @@ public final class FileUtils {
}
} catch (IOException ex) {
final String msg = String.format("Exception reading archive '%s'.", archive.getName());
Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, msg, ex);
LOGGER.log(Level.FINE, msg, ex);
throw new ExtractionException(msg, ex);
} finally {
try {
zis.close();
} catch (IOException ex) {
Logger.getLogger(FileUtils.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}
/**
* Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for Windows
*
* @return a String containing the bit bucket
*/
public static String getBitBucket() {
if (System.getProperty("os.name").startsWith("Windows")) {
return BIT_BUCKET_WIN;
} else {
return BIT_BUCKET_UNIX;
}
}
}

View File

@@ -32,6 +32,11 @@ import java.util.logging.SimpleFormatter;
*/
public final class LogUtils {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(LogUtils.class.getName());
/**
* Private constructor for a utility class.
*/
@@ -59,15 +64,15 @@ public final class LogUtils {
logger.setLevel(Level.FINE);
}
} catch (IOException ex) {
Logger.getLogger(LogUtils.class.getName()).log(Level.FINE, "IO Error preparing the logger", ex);
LOGGER.log(Level.FINE, "IO Error preparing the logger", ex);
} catch (SecurityException ex) {
Logger.getLogger(LogUtils.class.getName()).log(Level.FINE, "Error preparing the logger", ex);
LOGGER.log(Level.FINE, "Error preparing the logger", ex);
} finally {
if (in != null) {
try {
in.close();
} catch (Exception ex) {
Logger.getLogger(LogUtils.class.getName()).log(Level.FINEST, "Error closing resource stream", ex);
} catch (Throwable ex) {
LOGGER.log(Level.FINEST, "Error closing resource stream", ex);
}
}
}

View File

@@ -0,0 +1,127 @@
/*
* 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;
/**
* A generic pair of elements.
*
* @param <L> the type for the left element in the pair
* @param <R> the type for the right element in the pair
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class Pair<L, R> {
/**
* Constructs a new empty pair.
*/
public Pair() {
}
/**
* Constructs a new Pair with the given left and right values.
*
* @param left the value for the left pair
* @param right the value for the right pair
*/
public Pair(L left, R right) {
this.left = left;
this.right = right;
}
/**
* The left element of the pair.
*/
private L left = null;
/**
* Get the value of left.
*
* @return the value of left
*/
public L getLeft() {
return left;
}
/**
* Set the value of left.
*
* @param left new value of left
*/
public void setLeft(L left) {
this.left = left;
}
/**
* The right element of the pair.
*/
private R right = null;
/**
* Get the value of right.
*
* @return the value of right
*/
public R getRight() {
return right;
}
/**
* Set the value of right.
*
* @param right new value of right
*/
public void setRight(R right) {
this.right = right;
}
/**
* Generates the hash code using the hash codes from the contained objects.
*
* @return the hash code of the Pair
*/
@Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + (this.left != null ? this.left.hashCode() : 0);
hash = 53 * hash + (this.right != null ? this.right.hashCode() : 0);
return hash;
}
/**
* Determines the equality of this and the provided object.
*
* @param obj the {@link Object} to check for equality to this
* @return true if this and the provided {@link Object} are equal; otherwise false
*/
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Pair<?, ?> other = (Pair<?, ?>) obj;
if (this.left != other.left && (this.left == null || !this.left.equals(other.left))) {
return false;
}
if (this.right != other.right && (this.right == null || !this.right.equals(other.right))) {
return false;
}
return true;
}
}

View File

@@ -22,8 +22,11 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -35,6 +38,7 @@ import java.util.logging.Logger;
*/
public final class Settings {
//<editor-fold defaultstate="collapsed" desc="KEYS used to access settings">
/**
* The collection of keys used within the properties file.
*/
@@ -137,6 +141,26 @@ public final class Settings {
* The key for a list of suppression files.
*/
public static final String SUPPRESSION_FILE = "suppression.file";
/**
* The properties key for whether the Jar Analyzer is enabled.
*/
public static final String ANALYZER_JAR_ENABLED = "analyzer.jar.enabled";
/**
* The properties key for whether the Archive analyzer is enabled.
*/
public static final String ANALYZER_ARCHIVE_ENABLED = "analyzer.archive.enabled";
/**
* The properties key for whether the .NET Assembly analyzer is enabled.
*/
public static final String ANALYZER_ASSEMBLY_ENABLED = "analyzer.assembly.enabled";
/**
* The properties key for whether the .NET Nuspec analyzer is enabled.
*/
public static final String ANALYZER_NUSPEC_ENABLED = "analyzer.nuspec.enabled";
/**
* The properties key for whether the JavaScript analyzer is enabled.
*/
public static final String ANALYZER_JAVASCRIPT_ENABLED = "analyzer.javascript.enabled";
/**
* The properties key for whether the Nexus analyzer is enabled.
*/
@@ -145,15 +169,45 @@ public final class Settings {
* The properties key for the Nexus search URL.
*/
public static final String ANALYZER_NEXUS_URL = "analyzer.nexus.url";
/**
* The properties key for using the proxy to reach Nexus.
*/
public static final String ANALYZER_NEXUS_PROXY = "analyzer.nexus.proxy";
/**
* The path to mono, if available.
*/
public static final String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path";
/**
* The additional configured zip file extensions, if available.
*/
public static final String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip";
/**
* The properties key for whether Test Scope dependencies should be skipped.
*/
public static final String SKIP_TEST_SCOPE = "skip.test.scope";
/**
* The properties key for whether Runtime Scope dependencies should be skipped.
*/
public static final String SKIP_RUNTIME_SCOPE = "skip.runtime.scope";
/**
* The properties key for whether Provided Scope dependencies should be skipped.
*/
public static final String SKIP_PROVIDED_SCOPE = "skip.provided.scope";
}
//</editor-fold>
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(Settings.class.getName());
/**
* The properties file location.
*/
private static final String PROPERTIES_FILE = "dependencycheck.properties";
/**
* The singleton instance variable.
* Thread local settings.
*/
private static final Settings INSTANCE = new Settings();
private static ThreadLocal<Settings> localSettings = new ThreadLocal();
/**
* The properties.
*/
@@ -169,17 +223,94 @@ public final class Settings {
in = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
props.load(in);
} catch (IOException ex) {
Logger.getLogger(Settings.class.getName()).log(Level.SEVERE, "Unable to load default settings.");
Logger.getLogger(Settings.class.getName()).log(Level.FINE, null, ex);
LOGGER.log(Level.SEVERE, "Unable to load default settings.");
LOGGER.log(Level.FINE, null, ex);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ex) {
Logger.getLogger(Settings.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
}
}
logProperties("Properties loaded", props);
}
/**
* Initializes the thread local settings object. Note, to use the settings object you must call this method.
* However, you must also call Settings.cleanup() to properly release resources.
*/
public static void initialize() {
localSettings.set(new Settings());
}
/**
* Cleans up resources to prevent memory leaks.
*/
public static void cleanup() {
if (tempDirectory != null && tempDirectory.exists()) {
FileUtils.delete(tempDirectory);
}
try {
localSettings.remove();
} catch (Throwable ex) {
LOGGER.log(Level.FINE, "Error cleaning up Settings", ex);
}
}
/**
* Gets the underlying instance of the Settings object.
*
* @return the Settings object
*/
public static Settings getInstance() {
return localSettings.get();
}
/**
* Sets the instance of the Settings object to use in this thread.
*
* @param instance the instance of the settings object to use in this thread
*/
public static void setInstance(Settings instance) {
localSettings.set(instance);
}
/**
* Logs the properties. This will not log any properties that contain 'password' in the key.
*
* @param header the header to print with the log message
* @param properties the properties to log
*/
private static void logProperties(String header, Properties properties) {
if (LOGGER.isLoggable(Level.FINE)) {
final StringWriter sw = new StringWriter();
PrintWriter pw = null;
try {
pw = new PrintWriter(sw);
pw.format("%s:%n%n", header);
final Enumeration e = properties.propertyNames();
while (e.hasMoreElements()) {
final String key = (String) e.nextElement();
if (key.contains("password")) {
pw.format("%s='*****'%n", key);
} else {
final String value = properties.getProperty(key);
if (value != null) {
pw.format("%s='%s'%n", key, value);
}
}
}
pw.flush();
LOGGER.fine(sw.toString());
} finally {
if (pw != null) {
pw.close();
}
}
}
}
/**
@@ -189,7 +320,10 @@ public final class Settings {
* @param value the value for the property
*/
public static void setString(String key, String value) {
INSTANCE.props.setProperty(key, value);
localSettings.get().props.setProperty(key, value);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(String.format("Setting: %s='%s'", key, value));
}
}
/**
@@ -200,9 +334,12 @@ public final class Settings {
*/
public static void setBoolean(String key, boolean value) {
if (value) {
INSTANCE.props.setProperty(key, Boolean.TRUE.toString());
localSettings.get().props.setProperty(key, Boolean.TRUE.toString());
} else {
INSTANCE.props.setProperty(key, Boolean.FALSE.toString());
localSettings.get().props.setProperty(key, Boolean.FALSE.toString());
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(String.format("Setting: %s='%b'", key, value));
}
}
@@ -243,7 +380,8 @@ public final class Settings {
* @throws IOException is thrown when there is an exception loading/merging the properties
*/
public static void mergeProperties(InputStream stream) throws IOException {
INSTANCE.props.load(stream);
localSettings.get().props.load(stream);
logProperties("Properties updated via merge", localSettings.get().props);
}
/**
@@ -276,16 +414,16 @@ public final class Settings {
*/
public static File getDataFile(String key) {
final String file = getString(key);
Logger.getLogger(Settings.class.getName()).log(Level.FINE, String.format("Settings.getDataFile() - file: '%s'", file));
LOGGER.log(Level.FINE, String.format("Settings.getDataFile() - file: '%s'", file));
if (file == null) {
return null;
}
if (file.startsWith("[JAR]")) {
Logger.getLogger(Settings.class.getName()).log(Level.FINE, "Settings.getDataFile() - transforming filename");
LOGGER.log(Level.FINE, "Settings.getDataFile() - transforming filename");
final File jarPath = getJarPath();
Logger.getLogger(Settings.class.getName()).log(Level.FINE, String.format("Settings.getDataFile() - jar file: '%s'", jarPath.toString()));
LOGGER.log(Level.FINE, String.format("Settings.getDataFile() - jar file: '%s'", jarPath.toString()));
final File retVal = new File(jarPath, file.substring(6));
Logger.getLogger(Settings.class.getName()).log(Level.FINE, String.format("Settings.getDataFile() - returning: '%s'", retVal.toString()));
LOGGER.log(Level.FINE, String.format("Settings.getDataFile() - returning: '%s'", retVal.toString()));
return retVal;
}
return new File(file);
@@ -302,7 +440,7 @@ public final class Settings {
try {
decodedPath = URLDecoder.decode(jarPath, "UTF-8");
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(Settings.class.getName()).log(Level.FINEST, null, ex);
LOGGER.log(Level.FINEST, null, ex);
}
final File path = new File(decodedPath);
@@ -323,17 +461,32 @@ public final class Settings {
* @return the property from the properties file
*/
public static String getString(String key, String defaultValue) {
final String str = System.getProperty(key, INSTANCE.props.getProperty(key, defaultValue));
final String str = System.getProperty(key, localSettings.get().props.getProperty(key, defaultValue));
return str;
}
/**
* A reference to the temporary directory; used incase it needs to be deleted during cleanup.
*/
private static File tempDirectory = null;
/**
* Returns the temporary directory.
*
* @return the temporary directory
* @throws java.io.IOException thrown if the temporary directory does not exist and cannot be created
*/
public static File getTempDirectory() {
return new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")));
public static File getTempDirectory() throws IOException {
final File tmpDir = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")));
if (!tmpDir.exists()) {
if (!tmpDir.mkdirs()) {
final String msg = String.format("Unable to make a temporary folder '%s'", tmpDir.getPath());
throw new IOException(msg);
} else {
tempDirectory = tmpDir;
}
}
return tmpDir;
}
/**
@@ -345,7 +498,7 @@ public final class Settings {
* @return the property from the properties file
*/
public static String getString(String key) {
return System.getProperty(key, INSTANCE.props.getProperty(key));
return System.getProperty(key, localSettings.get().props.getProperty(key));
}
/**
@@ -354,7 +507,7 @@ public final class Settings {
* @param key the property key to remove
*/
public static void removeProperty(String key) {
INSTANCE.props.remove(key);
localSettings.get().props.remove(key);
}
/**
@@ -392,7 +545,7 @@ public final class Settings {
value = Integer.parseInt(Settings.getString(key));
} catch (NumberFormatException ex) {
final String msg = String.format("Could not convert property '%s' to an int.", key);
Logger.getLogger(Settings.class.getName()).log(Level.FINEST, msg, ex);
LOGGER.log(Level.FINEST, msg, ex);
value = defaultValue;
}
return value;
@@ -435,4 +588,28 @@ public final class Settings {
}
return value;
}
/**
* Returns a boolean value from the properties file. If the value was specified as a system property or passed in
* via the <code>-Dprop=value</code> argument this method will return the value from the system properties before
* the values in the contained configuration file.
*
* @param key the key to lookup within the properties file
* @param defaultValue the default value to return if the setting does not exist
* @return the property from the properties file
* @throws InvalidSettingException is thrown if there is an error retrieving the setting
*/
public static boolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException {
boolean value;
try {
final String strValue = Settings.getString(key);
if (strValue == null) {
return defaultValue;
}
value = Boolean.parseBoolean(strValue);
} catch (NumberFormatException ex) {
throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
}
return value;
}
}

View File

@@ -0,0 +1,118 @@
/*
* 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;
import java.io.IOException;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.URL;
/**
* A URLConnection Factory to create new connections. This encapsulates several configuration checks to ensure that the
* connection uses the correct proxy settings.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class URLConnectionFactory {
/**
* Private constructor for this factory.
*/
private URLConnectionFactory() {
}
/**
* Utility method to create an HttpURLConnection. If the application is configured to use a proxy this method will
* retrieve the proxy settings and use them when setting up the connection.
*
* @param url the url to connect to
* @return an HttpURLConnection
* @throws URLConnectionFailureException thrown if there is an exception
*/
public static HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException {
HttpURLConnection conn = null;
Proxy proxy = null;
final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_URL);
try {
if (proxyUrl != null) {
final int proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT);
final SocketAddress address = new InetSocketAddress(proxyUrl, proxyPort);
final String username = Settings.getString(Settings.KEYS.PROXY_USERNAME);
final String password = Settings.getString(Settings.KEYS.PROXY_PASSWORD);
if (username != null && password != null) {
final Authenticator auth = new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
if (getRequestorType().equals(Authenticator.RequestorType.PROXY)) {
return new PasswordAuthentication(username, password.toCharArray());
}
return super.getPasswordAuthentication();
}
};
Authenticator.setDefault(auth);
}
proxy = new Proxy(Proxy.Type.HTTP, address);
conn = (HttpURLConnection) url.openConnection(proxy);
} else {
conn = (HttpURLConnection) url.openConnection();
}
final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 60000);
conn.setConnectTimeout(timeout);
} catch (IOException ex) {
if (conn != null) {
try {
conn.disconnect();
} finally {
conn = null;
}
}
throw new URLConnectionFailureException("Error getting connection.", ex);
}
return conn;
}
/**
* Utility method to create an HttpURLConnection. The use of a proxy here is optional as there may be cases where a
* proxy is configured but we don't want to use it (for example, if there's an internal repository configured)
*
* @param url the url to connect to
* @param proxy whether to use the proxy (if configured)
* @return a newly constructed HttpURLConnection
* @throws URLConnectionFailureException thrown if there is an exception
*/
public static HttpURLConnection createHttpURLConnection(URL url, boolean proxy) throws URLConnectionFailureException {
if (proxy) {
return createHttpURLConnection(url);
}
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) url.openConnection();
final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 60000);
conn.setConnectTimeout(timeout);
} catch (IOException ioe) {
throw new URLConnectionFailureException("Error getting connection.", ioe);
}
return conn;
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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;
import java.io.IOException;
/**
* An exception used when the creation of an URLConnection fails.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class URLConnectionFailureException extends IOException {
/**
* The serial version UID.
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new URLConnectionFailureException.
*/
public URLConnectionFailureException() {
super();
}
/**
* Creates a new URLConnectionFailureException.
*
* @param msg a message for the exception.
*/
public URLConnectionFailureException(String msg) {
super(msg);
}
/**
* Creates a new URLConnectionFailureException.
*
* @param ex the cause of the download failure.
*/
public URLConnectionFailureException(Throwable ex) {
super(ex);
}
/**
* Creates a new URLConnectionFailureException.
*
* @param msg a message for the exception.
* @param ex the cause of the download failure.
*/
public URLConnectionFailureException(String msg, Throwable ex) {
super(msg, ex);
}
}

Binary file not shown.

View File

@@ -9,3 +9,5 @@ org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer
org.owasp.dependencycheck.analyzer.NvdCveAnalyzer
org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer
org.owasp.dependencycheck.analyzer.NexusAnalyzer
org.owasp.dependencycheck.analyzer.NuspecAnalyzer
org.owasp.dependencycheck.analyzer.AssemblyAnalyzer

View File

@@ -13,8 +13,10 @@ max.download.threads=3
# 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.
data.directory=[JAR]/data
data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;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
# user name and password for the database connection. The inherent case is to use H2.
# As such, this unsecure username/password exist.
data.user=dcuser
@@ -30,11 +32,6 @@ data.password=DC-Pass1337!
data.driver_name=org.h2.Driver
data.driver_path=
# the path to the cpe xml file
cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.xml.gz
# the path to the cpe meta data file.
cpe.meta.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.meta
# the number of days that the modified nvd cve data holds data for. We don't need
# to update the other files if we are within this timespan. Per NIST this file
# holds 8 days of updates, we are using 7 just to be safe.
@@ -47,7 +44,15 @@ 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=http://nvd.nist.gov/download/nvdcve-%d.xml
# file type analyzer settings:
analyzer.archive.enabled=true
analyzer.jar.enabled=true
analyzer.nuspec.enabled=true
analyzer.assembly.enabled=true
# the URL for searching Nexus for SHA-1 hashes and whether it's enabled
analyzer.nexus.enabled=true
analyzer.nexus.url=http://repository.sonatype.org/service/local/
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)
# are configured
analyzer.nexus.proxy=true

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="analysis" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="https://www.owasp.org/index.php/OWASP_Dependency_Check#1.1">
<xs:schema id="analysis" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="https://www.owasp.org/index.php/OWASP_Dependency_Check#1.2">
<xs:element name="analysis">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
@@ -119,64 +119,124 @@
<xs:element name="identifiers" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="identifier" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="url" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required" />
<xs:attribute name="confidence" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
<xs:sequence>
<xs:element name="identifier" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="url" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required" />
<xs:attribute name="confidence" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:sequence>
<xs:element name="suppressedIdentifier" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="url" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required" />
<xs:attribute name="confidence" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="vulnerabilities" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="vulnerability" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cvssScore" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="severity" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cwe" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="description" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="references" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="reference" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="source" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="url" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="vulnerableSoftware" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="software" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="allPreviousVersion" type="xs:boolean" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:sequence>
<xs:element name="vulnerability" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cvssScore" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="severity" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cwe" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="description" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="references" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="reference" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="source" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="url" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="vulnerableSoftware" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="software" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="allPreviousVersion" type="xs:boolean" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:sequence>
<xs:element name="suppressedVulnerability" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cvssScore" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="severity" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cwe" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="description" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="references" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="reference" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="source" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="url" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="vulnerableSoftware" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="software" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="allPreviousVersion" type="xs:boolean" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>

View File

@@ -39,15 +39,23 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
var content = "#content" + h.id.substr(6);
var header = "#" + h.id;
$(content).slideToggle("fast");
var exprx = /expandablesubsection/;
var exprx = /expandable\b/;
if (exprx.exec($(header).attr("class"))) {
$(header).addClass("collapsed");
$(header).removeClass("expandable");
} else {
$(header).addClass("expandable");
$(header).removeClass("collapsed");
}
var essrx = /expandablesubsection/;
var cssrx = /collaspablesubsection/;
if (essrx.exec($(header).attr("class"))) {
$(header).addClass("collaspablesubsection");
$(header).removeClass("expandablesubsection");
} else {
} else if (cssrx.exec($(header).attr("class"))) {
$(header).addClass("expandablesubsection");
$(header).removeClass("collaspablesubsection");
}
});
});
@@ -129,6 +137,19 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
#modal-text:focus {
outline: none;
}
.suppressedLabel {
cursor: default;
padding:1px;
background-color: #eeeeee;
border: 1px solid #555555;
color:#555555;
text-decoration:none;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
-khtml-border-radius: 3px;
-o-border-radius: 3px;
border-radius: 3px;
}
.copybutton {
padding:1px;
background-color: #eeeeee;
@@ -215,24 +236,25 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
.hidden {
display: none;
}
.exandable {}
.expandablesubsection {
.expandable {
cursor: pointer;
/*background-image: url(img/plus.gif);*/
background-image: url(data:image/gif;base64,R0lGODlhDAAMAIABAICAgP///yH5BAEAAAEALAAAAAAMAAwAAAIcjI8Hy22Q1FNwhnpxhW3d2XFWJn2PNiZbyERuAQA7);
background-repeat: no-repeat;
background-position: 98% 50%;
}
.collapsed {
cursor: pointer;
background-image: url(data:image/gif;base64,R0lGODlhDAAMAIABAICAgP///yH5BAEAAAEALAAAAAAMAAwAAAIajI8Hy22Q1IszQHphW3ZuXUUZ1ZXi8zFkUgAAOw==);
background-repeat: no-repeat;
background-position: 98% 50%;
}
.expandablesubsection {
-moz-border-radius-bottomleft:15px; /* bottom left corner */
-webkit-border-bottom-left-radius:15px; /* bottom left corner */
border-bottom-left-radius: 15px;
border-bottom: 1px solid #cccccc;
}
.collaspablesubsection {
cursor: pointer;
/*background-image: url(img/minus.gif);*/
background-image: url(data:image/gif;base64,R0lGODlhDAAMAIABAICAgP///yH5BAEAAAEALAAAAAAMAAwAAAIajI8Hy22Q1IszQHphW3ZuXUUZ1ZXi8zFkUgAAOw==);
background-repeat: no-repeat;
background-position: 98% 50%;
-moz-border-radius-bottomleft:0px; /* bottom left corner */
-webkit-border-bottom-left-radius:0px; /* bottom left corner */
border-bottom-left-radius: 0px;
@@ -244,7 +266,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
border-bottom-left-radius: 0px;
border-bottom: 0px solid #ffffff;
}
.content {
margin-top:0px;
margin-left:20px;
@@ -448,6 +469,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
color: blue;
float:right;
}
.disclaimer {
color: #888888;
font: 9px "Droid Sans",Arial,"Helvetica Neue","Lucida Grande",sans-serif
}
</style>
</head>
<body>
@@ -459,27 +485,45 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</div>
<div class="wrapper">
<h1>Dependency-Check Report</h1>
<p class="disclaimer">Dependency-Check is an open source tool performing a best effort analysis of 3rd party dependencies;
false positives and false negatives may exist in the analysis performed by the tool. Use of the tool and
the reporting provided constitutes acceptance for use in an AS IS condition, and there are NO warranties,
implied or otherwise, with regard to the analysis or its use. Any use of the tool and the reporting provided
is at the users risk. In no event shall the copyright holder or OWASP be held liable for any damages whatsoever
arising out of or in connection with the use of this tool, the analysis performed, or the resulting report.</p>
]]#
<h2 class="">Project:&nbsp;$esc.html($applicationName)</h2>
<h2 class="">Project:&nbsp;$enc.html($applicationName)</h2>
<div class="">
#set($depCount=$dependencies.size())
#set($vulnDepCount=0)
#set($vulnCount=0)
#set($vulnSuppressedCount=0)
#set($cpeSuppressedCount=0)
#foreach($dependency in $dependencies)
#set($depCount=$depCount+$dependency.getRelatedDependencies().size())
#if($dependency.getVulnerabilities().size()>0)
#set($vulnCount=$vulnCount+1)
#set($vulnDepCount=$vulnDepCount+1)
#set($vulnCount=$vulnCount+$dependency.getVulnerabilities().size())
#end
#if($dependency.getSuppressedIdentifiers().size()>0)
#set($cpeSuppressedCount=$cpeSuppressedCount+1)
#end
#if($dependency.getSuppressedVulnerabilities().size()>0)
#set($vulnSuppressedCount=$vulnSuppressedCount+$dependency.getSuppressedVulnerabilities().size())
#end
#end
Scan Information (<a href="#" onclick="toggleDisplay(this, '.scaninfo'); return false;">show all</a>):<br/>
<ul class="indent">
<li><i>dependency-check version</i>: $version</li>
<li><i>Report Generated On</i>: $date</li>
<li><i>Report Generated On</i>: $scanDate</li>
<li><i>Dependencies Scanned</i>:&nbsp;$depCount</li>
<li><i>Vulnerable Dependencies</i>:&nbsp;$vulnCount</li>
<li><i>Vulnerable Dependencies</i>:&nbsp;$vulnDepCount</li>
<li><i>Vulnerabilities Found</i>:&nbsp;$vulnCount</li>
<li><i>Vulnerabilities Suppressed</i>:&nbsp;$vulnSuppressedCount</li>
<li class="scaninfo">...</li>
#foreach($prop in $properties.getMetaData().entrySet())
<li class="scaninfo hidden"><i>$esc.html($prop.key)</i>: $esc.html($prop.value)</li>
<li class="scaninfo hidden"><i>$enc.html($prop.key)</i>: $enc.html($prop.value)</li>
#end
</ul><br/>
Dependency Display:&nbsp;<a href="#" onclick="toggleDisplay(this,'.notvulnerable'); return false;">show all</a><br/><br/>
@@ -488,11 +532,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
#foreach($dependency in $dependencies)
#set($lnkcnt=$lnkcnt+1)
<li class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end">
<a href="#l${lnkcnt}_$esc.html($esc.url($dependency.Sha1sum))">$esc.html($dependency.FileName)</a>
<a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.FileName)</a>
#if($dependency.getRelatedDependencies().size()>0)
<ul>
#foreach($related in $dependency.getRelatedDependencies())
<li>$esc.html($related.FileName)</li>
<li>$enc.html($related.FileName)</li>
#end
</ul>
#end
@@ -505,22 +549,22 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
#set($vsctr=0) ##counter to create unique groups for vulnerable software
#foreach($dependency in $dependencies)
#set($lnkcnt=$lnkcnt+1)
<h3 class="subsectionheader standardsubsection#if($dependency.getVulnerabilities().size()==0) notvulnerable#end"><a name="l${lnkcnt}_$esc.html($dependency.Sha1sum)"></a>$esc.html($dependency.FileName)</h3>
<h3 class="subsectionheader standardsubsection#if($dependency.getVulnerabilities().size()==0) notvulnerable#end"><a name="l${lnkcnt}_$enc.html($dependency.Sha1sum)"></a>$enc.html($dependency.FileName)</h3>
<div class="subsectioncontent#if($dependency.getVulnerabilities().size()==0) notvulnerable#end">
#if ($dependency.description)
<p><b>Description:</b>&nbsp;$esc.html($dependency.description)<br/></p>
<p><b>Description:</b>&nbsp;$enc.html($dependency.description)<br/></p>
#end
<p>
#if ($dependency.license)
#if ($dependency.license.startsWith("http://"))
<b>License:</b><pre class="indent"><a href="$esc.html($dependency.license)">$esc.html($dependency.license)</a></pre>
<b>License:</b><pre class="indent"><a href="$enc.html($dependency.license)">$enc.html($dependency.license)</a></pre>
#else
<b>License:</b><pre class="indent">$esc.html($dependency.license)</pre>
<b>License:</b><pre class="indent">$enc.html($dependency.license)</pre>
#end
#end
<b>File&nbsp;Path:</b>&nbsp;$esc.html($dependency.FilePath)<br/>
<b>MD5:</b>&nbsp;$esc.html($dependency.Md5sum)<br/>
<b>SHA1:</b>&nbsp;$esc.html($dependency.Sha1sum)
<b>File&nbsp;Path:</b>&nbsp;$enc.html($dependency.FilePath)<br/>
<b>MD5:</b>&nbsp;$enc.html($dependency.Md5sum)<br/>
<b>SHA1:</b>&nbsp;$enc.html($dependency.Sha1sum)
</p>
#set($cnt=$cnt+1)
<h4 id="header$cnt" class="subsectionheader expandable expandablesubsection white">Evidence</h4>
@@ -528,7 +572,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<table class="lined fullwidth" border="0">
<tr><th class="left" style="width:10%;">Source</th><th class="left" style="width:20%;">Name</th><th class="left" style="width:70%;">Value</th></tr>
#foreach($evidence in $dependency.getEvidenceUsed())
<tr><td>$esc.html($evidence.getSource())</td><td>$esc.html($evidence.getName())</td><td>$esc.html($evidence.getValue())</td></tr>
<tr><td>$enc.html($evidence.getSource())</td><td>$enc.html($evidence.getName())</td><td>$enc.html($evidence.getValue())</td></tr>
#end
</table>
</div>
@@ -538,18 +582,18 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<div id="content$cnt" class="subsectioncontent standardsubsection hidden">
<ul>
#foreach($related in $dependency.getRelatedDependencies())
<li>$esc.html($related.FileName)
<li>$enc.html($related.FileName)
<ul>
<li>File Path:&nbsp;$esc.html($related.FilePath)</li>
<li>SHA1:&nbsp;$esc.html($related.Sha1sum)</li>
<li>MD5:&nbsp;$esc.html($related.Md5sum)</li>
<li>File Path:&nbsp;$enc.html($related.FilePath)</li>
<li>SHA1:&nbsp;$enc.html($related.Sha1sum)</li>
<li>MD5:&nbsp;$enc.html($related.Md5sum)</li>
#foreach($id in $related.getIdentifiers())
#if ($id.type=="maven")
#if( $id.url )
##yes, we are HTML Encoding the href. this is okay. We can't URL encode as we have to trust the analyzer here...
<li>$esc.html($id.type):&nbsp;<a href="$esc.html($id.url)" target="_blank">$esc.html($id.value)</a>
<li>$enc.html($id.type):&nbsp;<a href="$enc.html($id.url)" target="_blank">$enc.html($id.value)</a>
#else
<li>$esc.html($id.type):&nbsp;$esc.html($id.value)
<li>$enc.html($id.type):&nbsp;$enc.html($id.value)
#end
</li>
#end
@@ -568,7 +612,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
#end
#end
<h4 id="header$cnt" class="subsectionheader white">Identifiers</h4>
##:&nbsp;<a href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$esc.url($cpevalue)" target="_blank">$esc.html($cpevalue)</a></h4>
##:&nbsp;<a href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($cpevalue)" target="_blank">$enc.html($cpevalue)</a></h4>
<div id="content$cnt" class="subsectioncontent standardsubsection">
#if ($dependency.getIdentifiers().size()==0)
<ul><li><b>None</b></li></ul>
@@ -577,19 +621,19 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
#foreach($id in $dependency.getIdentifiers())
#if( $id.url )
##yes, we are HTML Encoding the href. this is okay. We can't URL encode as we have to trust the analyzer here...
<li><b>$esc.html($id.type):</b>&nbsp;<a href="$esc.html($id.url)" target="_blank">$esc.html($id.value)</a>
<li><b>$enc.html($id.type):</b>&nbsp;<a href="$enc.html($id.url)" target="_blank">$enc.html($id.value)</a>
#else
<li><b>$esc.html($id.type):</b>&nbsp;$esc.html($id.value)
<li><b>$enc.html($id.type):</b>&nbsp;$enc.html($id.value)
#end
#if ($id.confidence)
&nbsp;&nbsp;<i>Confidence</i>:$id.confidence
#end
#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
&nbsp;&nbsp;<button class="copybutton" onclick="copyText('$esc.html($dependency.FileName)', '$esc.html($dependency.Sha1sum)', 'cpe', '$esc.html($id.value)')">suppress</button>
&nbsp;&nbsp;<button class="copybutton" onclick="copyText('$enc.html($dependency.FileNameForJavaScript)', '$enc.html($dependency.Sha1sum)', 'cpe', '$enc.html($id.value)')">suppress</button>
#end
#if ($id.description)
<br/>$esc.html($id.description)
<br/>$enc.html($id.description)
#end
</li>
#end
@@ -602,7 +646,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<div id="content$cnt" class="subsectioncontent standardsubsection">
#foreach($vuln in $dependency.getVulnerabilities())
#set($vsctr=$vsctr+1)
<p><b><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=$esc.url($vuln.name)">$esc.html($vuln.name)</a></b>&nbsp;&nbsp;<button class="copybutton" onclick="copyText('$esc.html($dependency.FileName)', '$esc.html($dependency.Sha1sum)', 'cve', '$esc.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>&nbsp;&nbsp;<button class="copybutton" onclick="copyText('$enc.html($dependency.FileNameForJavaScript)', '$enc.html($dependency.Sha1sum)', 'cve', '$enc.html($vuln.name)')">suppress</button></p>
<p>Severity:
#if ($vuln.cvssScore<4.0)
Low
@@ -615,20 +659,20 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
#if ($vuln.cwe)
<br/>CWE: $vuln.cwe
#end</p>
<p>$esc.html($vuln.description)
<p>$enc.html($vuln.description)
#if ($vuln.getReferences().size()>0)
<ul>
#foreach($ref in $vuln.getReferences())
<li>$esc.html($ref.source) - <a target="_blank" href="$esc.html($ref.url)">$ref.name</a></li>
<li>$enc.html($ref.source) - <a target="_blank" href="$enc.html($ref.url)">$ref.name</a></li>
#end
</ul>
#end
</p>
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul>
<li class="vs$vsctr"><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$esc.url($vuln.matchedCPE)">$esc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
<li class="vs$vsctr"><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
<li class="vs$vsctr">...</li>
#foreach($vs in $vuln.getVulnerableSoftware())
<li class="vs$vsctr hidden"><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$esc.url($vs.name)">$esc.html($vs.name)</a> #if($vs.hasPreviousVersion()) and all previous versions#end</li>
<li class="vs$vsctr hidden"><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($vs.name)">$enc.html($vs.name)</a> #if($vs.hasPreviousVersion()) and all previous versions#end</li>
#end
</ul></p>
#end
@@ -636,6 +680,138 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
#end
</div>
#end
## BEGIN SUPPRESSED VULNERABILITIES
#if ($vulnSuppressedCount>0 || $cpeSuppressedCount>0)
#set($cnt=$cnt+1)
<h2 id="header$cnt" class="expandable">Suppressed Vulnerabilities</h3>
<div id="content$cnt" class="hidden">
#foreach($dependency in $dependencies)
#if ($dependency.getSuppressedIdentifiers().size()>0 || $dependency.getSuppressedVulnerabilities().size()>0)
#set($lnkcnt=$lnkcnt+1)
<h3 class="subsectionheader standardsubsection">$enc.html($dependency.FileName)</h3>
<div class="subsectioncontent">
#if ($dependency.description)
<p><b>Description:</b>&nbsp;$enc.html($dependency.description)<br/></p>
#end
<p>
#if ($dependency.license)
#if ($dependency.license.startsWith("http://"))
<b>License:</b><pre class="indent"><a href="$enc.html($dependency.license)">$enc.html($dependency.license)</a></pre>
#else
<b>License:</b><pre class="indent">$enc.html($dependency.license)</pre>
#end
#end
<b>File&nbsp;Path:</b>&nbsp;$enc.html($dependency.FilePath)<br/>
<b>MD5:</b>&nbsp;$enc.html($dependency.Md5sum)<br/>
<b>SHA1:</b>&nbsp;$enc.html($dependency.Sha1sum)
</p>
#set($cnt=$cnt+1)
<h4 id="header$cnt" class="subsectionheader expandable expandablesubsection white">Evidence</h4>
<div id="content$cnt" class="subsectioncontent standardsubsection hidden">
<table class="lined fullwidth" border="0">
<tr><th class="left" style="width:10%;">Source</th><th class="left" style="width:20%;">Name</th><th class="left" style="width:70%;">Value</th></tr>
#foreach($evidence in $dependency.getEvidenceUsed())
<tr><td>$enc.html($evidence.getSource())</td><td>$enc.html($evidence.getName())</td><td>$enc.html($evidence.getValue())</td></tr>
#end
</table>
</div>
#if($dependency.getRelatedDependencies().size()>0)
#set($cnt=$cnt+1)
<h4 id="header$cnt" class="subsectionheader expandable expandablesubsection white">Related Dependencies</h4>
<div id="content$cnt" class="subsectioncontent standardsubsection hidden">
<ul>
#foreach($related in $dependency.getRelatedDependencies())
<li>$enc.html($related.FileName)
<ul>
<li>File Path:&nbsp;$enc.html($related.FilePath)</li>
<li>SHA1:&nbsp;$enc.html($related.Sha1sum)</li>
<li>MD5:&nbsp;$enc.html($related.Md5sum)</li>
</ul>
</li>
#end
</ul>
</div>
#end
#set($cnt=$cnt+1)
#set($cpeCount=0)
#foreach($id in $dependency.getSuppressedIdentifiers())
#if($id.type.equals("cpe"))
#set($cpeCount=$cpeCount+1)
#end
#end
<h4 id="header$cnt" class="subsectionheader white">Suppressed Identifiers</h4>
##:&nbsp;<a href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($cpevalue)" target="_blank">$enc.html($cpevalue)</a></h4>
<div id="content$cnt" class="subsectioncontent standardsubsection">
#if ($dependency.getSuppressedIdentifiers().size()==0)
<ul><li><b>None</b></li></ul>
#else ## ($dependency.getSuppressedIdentifiers().size()>0)
<ul>
#foreach($id in $dependency.getSuppressedIdentifiers())
#if( $id.url )
##yes, we are HTML Encoding the href. this is okay. We can't URL encode as we have to trust the analyzer here...
<li><b>$enc.html($id.type):</b>&nbsp;<a href="$enc.html($id.url)" target="_blank">$enc.html($id.value)</a>&nbsp;&nbsp;<span class="suppressedLabel" >suppressed</span>
#else
<li><b>$enc.html($id.type):</b>&nbsp;$enc.html($id.value)&nbsp;&nbsp;<span class="suppressedLabel" >suppressed</span>
#end
#if ($id.confidence)
&nbsp;&nbsp;<i>Confidence</i>:$id.confidence
#end
#if ($id.description)
<br/>$enc.html($id.description)
#end
</li>
#end
</ul>
#end
</div>
#if($dependency.getSuppressedVulnerabilities().size()>0)
#set($cnt=$cnt+1)
<h4 id="header$cnt" class="subsectionheader expandable collaspablesubsection white">Suppressed Vulnerabilities</h4>
<div id="content$cnt" class="subsectioncontent standardsubsection">
#foreach($vuln in $dependency.getSuppressedVulnerabilities())
#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>&nbsp;&nbsp;<span class="suppressedLabel" >suppressed</span></p>
<p>Severity:
#if ($vuln.cvssScore<4.0)
Low
#elseif ($vuln.cvssScore>=7.0)
High
#else
Medium
#end
<br/>CVSS Score: $vuln.cvssScore
#if ($vuln.cwe)
<br/>CWE: $vuln.cwe
#end</p>
<p>$enc.html($vuln.description)
#if ($vuln.getReferences().size()>0)
<ul>
#foreach($ref in $vuln.getReferences())
<li>$enc.html($ref.source) - <a target="_blank" href="$enc.html($ref.url)">$ref.name</a></li>
#end
</ul>
#end
</p>
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul>
<li class="vs$vsctr"><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
<li class="vs$vsctr">...</li>
#foreach($vs in $vuln.getVulnerableSoftware())
<li class="vs$vsctr hidden"><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$enc.url($vs.name)">$enc.html($vs.name)</a> #if($vs.hasPreviousVersion()) and all previous versions#end</li>
#end
</ul></p>
#end
</div>
#end
</div>
#end
#end
</div>
#end
## END SUPPRESSED VULNERABILITIES
</div>
</div>
<div><br/><br/>This report contains data retrieved from the <a href="nvd.nist.gov">National Vulnerability Database</a>.</div>

View File

@@ -161,14 +161,25 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
margin-top:3px;
margin-bottom:3px;
}
.disclaimer {
color: #888888;
font: 9px "Droid Sans",Arial,"Helvetica Neue","Lucida Grande",sans-serif
}
</style>
</head>
<body>
<div>
<h1 class="sectionheader">Vulnerability Report</h1>
<p class="disclaimer">Dependency-Check is an open source tool performing a best effort analysis of 3rd party dependencies;
false positives and false negatives may exist in the analysis performed by the tool. Use of the tool and
the reporting provided constitutes acceptance for use in an AS IS condition, and there are NO warranties,
implied or otherwise, with regard to the analysis or its use. Any use of the tool and the reporting provided
is at the users risk. In no event shall the copyright holder or OWASP be held liable for any damages whatsoever
arising out of or in connection with the use of this tool, the analysis performed, or the resulting report.</p>
]]#
<h2 class="sectionheader white">Project:&nbsp;$esc.html($applicationName)</h2>
<div class="sectioncontent">Report Generated On: $date<br/><br/>
<h2 class="sectionheader white">Project:&nbsp;$enc.html($applicationName)</h2>
<div class="sectioncontent">Report Generated On: $scanDate<br/><br/>
#set($depCount=$dependencies.size())
#set($vulnCount=0)
@@ -194,7 +205,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
#if($dependency.getVulnerabilities().size()>0)
#foreach($vuln in $dependency.getVulnerabilities())
<tr>
<td><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=$esc.url($vuln.name)">$esc.html($vuln.name)</a></td>
<td><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=$enc.url($vuln.name)">$enc.html($vuln.name)</a></td>
<td>
#if ($vuln.cwe)
$vuln.cwe
@@ -211,10 +222,10 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
($vuln.cvssScore)
<td>#set($cnt=$cnt+1)
#if($dependency.getRelatedDependencies().size()>0)<span id="header$cnt" class="expandable collapsedList">#end
$esc.html($dependency.FileName)
$enc.html($dependency.FileName)
#if($dependency.getRelatedDependencies().size()>0)&nbsp;&nbsp;&nbsp;</span><div id="content$cnt" class="hidden">#end
#foreach($related in $dependency.getRelatedDependencies())
$esc.html($related.FileName)<br/>
$enc.html($related.FileName)<br/>
#end
#if($dependency.getRelatedDependencies().size()>0)</div#end
</td>

View File

@@ -18,47 +18,47 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
@author Jeremy Long <jeremy.long@owasp.org>
@version 1.1
*#<?xml version="1.0"?>
<analysis xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check#1.1">
<analysis xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check#1.2">
<scanInfo>
<engineVersion>$version</engineVersion>
#foreach($prop in $properties.getMetaData().entrySet())
<dataSource>
<name>$esc.xml($prop.key)</name>
<timestamp>$esc.xml($prop.value)</timestamp>
<name>$enc.xml($prop.key)</name>
<timestamp>$enc.xml($prop.value)</timestamp>
</dataSource>
#end
</scanInfo>
<projectInfo>
<name>$esc.xml($applicationName)</name>
<reportDate>$date</reportDate>
<name>$enc.xml($applicationName)</name>
<reportDate>$scanDateXML</reportDate>
<credits>This report contains data retrieved from the National Vulnerability Database: http://nvd.nist.gov</credits>
</projectInfo>
<dependencies>
#foreach($dependency in $dependencies)
<dependency>
<fileName>$esc.xml($dependency.FileName)</fileName>
<filePath>$esc.xml($dependency.FilePath)</filePath>
<md5>$esc.xml($dependency.Md5sum)</md5>
<sha1>$esc.xml($dependency.Sha1sum)</sha1>
<fileName>$enc.xml($dependency.FileName)</fileName>
<filePath>$enc.xml($dependency.FilePath)</filePath>
<md5>$enc.xml($dependency.Md5sum)</md5>
<sha1>$enc.xml($dependency.Sha1sum)</sha1>
#if ($dependency.description)
<description>$esc.xml($dependency.description)</description>
<description>$enc.xml($dependency.description)</description>
#end
#if ($dependency.license)
<license>$esc.xml($dependency.license)</license>
<license>$enc.xml($dependency.license)</license>
#end
#if ($dependency.getRelatedDependencies().size()>0)
<relatedDependencies>
#foreach($related in $dependency.getRelatedDependencies())
<relatedDependency>
<filePath>$esc.xml($related.FilePath)</filePath>
<sha1>$esc.xml($related.Sha1sum)</sha1>
<md5>$esc.xml($related.Md5sum)</md5>
<filePath>$enc.xml($related.FilePath)</filePath>
<sha1>$enc.xml($related.Sha1sum)</sha1>
<md5>$enc.xml($related.Md5sum)</md5>
#foreach($id in $related.getIdentifiers())
#if ($id.type=="maven")
<identifier type="$esc.xml($id.type)">
<identifier type="$enc.xml($id.type)">
<name>($id.value)</name>
#if( $id.url )
<url>$esc.xml($id.url)</url>
<url>$enc.xml($id.url)</url>
#end
</identifier>
#end
@@ -70,32 +70,43 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<evidenceCollected>
#foreach($evidence in $dependency.getEvidenceUsed())
<evidence>
<source>$esc.xml($evidence.getSource())</source>
<name>$esc.xml($evidence.getName())</name>
<value>$esc.xml($evidence.getValue().trim())</value>
<source>$enc.xml($evidence.getSource())</source>
<name>$enc.xml($evidence.getName())</name>
<value>$enc.xml($evidence.getValue().trim())</value>
</evidence>
#end
</evidenceCollected>
#if($dependency.getIdentifiers().size()>0)
<identifiers>
#foreach($id in $dependency.getIdentifiers())
<identifier type="$esc.xml($id.type)" #if($id.confidence)confidence="$id.confidence"#end>
<identifier type="$enc.xml($id.type)" #if($id.confidence)confidence="$id.confidence"#end>
<name>($id.value)</name>
#if( $id.url )
<url>$esc.xml($id.url)</url>
<url>$enc.xml($id.url)</url>
#end
#if( $id.description )
<description>$esc.xml($id.description)</description>
<description>$enc.xml($id.description)</description>
#end
</identifier>
#end
#foreach($id in $dependency.getSuppressedIdentifiers())
<suppressedIdentifier type="$enc.xml($id.type)" #if($id.confidence)confidence="$id.confidence"#end>
<name>($id.value)</name>
#if( $id.url )
<url>$enc.xml($id.url)</url>
#end
#if( $id.description )
<description>$enc.xml($id.description)</description>
#end
</suppressedIdentifier>
#end
</identifiers>
#end
#if($dependency.getVulnerabilities().size()>0)
#if($dependency.getVulnerabilities().size()>0 || $dependency.getSuppressedVulnerabilities().size()>0)
<vulnerabilities>
#foreach($vuln in $dependency.getVulnerabilities())
<vulnerability>
<name>$esc.xml($vuln.name)</name>
<name>$enc.xml($vuln.name)</name>
<cvssScore>$vuln.cvssScore</cvssScore>
#if ($vuln.cvssScore<4.0)
<severity>Low</severity>
@@ -105,24 +116,55 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<severity>Medium</severity>
#end
#if ($vuln.cwe)
<cwe>$esc.xml($vuln.cwe)</cwe>
<cwe>$enc.xml($vuln.cwe)</cwe>
#end
<description>$esc.xml($vuln.description)</description>
<description>$enc.xml($vuln.description)</description>
<references>
#foreach($ref in $vuln.getReferences())
<reference>
<source>$esc.xml($ref.source)</source>
<url>$esc.xml($ref.url)</url>
<name>$esc.xml($ref.name)</name>
<source>$enc.xml($ref.source)</source>
<url>$enc.xml($ref.url)</url>
<name>$enc.xml($ref.name)</name>
</reference>
#end
</references>
<vulnerableSoftware>
#foreach($vs in $vuln.getVulnerableSoftware())
<software#if($vs.hasPreviousVersion()) allPreviousVersion="true"#end>$esc.xml($vs.name)</software>
<software#if($vs.hasPreviousVersion()) allPreviousVersion="true"#end>$enc.xml($vs.name)</software>
#end
</vulnerableSoftware>
</vulnerability>
#end
#foreach($vuln in $dependency.getSuppressedVulnerabilities())
<suppressedVulnerability>
<name>$enc.xml($vuln.name)</name>
<cvssScore>$vuln.cvssScore</cvssScore>
#if ($vuln.cvssScore<4.0)
<severity>Low</severity>
#elseif ($vuln.cvssScore>=7.0)
<severity>High</severity>
#else
<severity>Medium</severity>
#end
#if ($vuln.cwe)
<cwe>$enc.xml($vuln.cwe)</cwe>
#end
<description>$enc.xml($vuln.description)</description>
<references>
#foreach($ref in $vuln.getReferences())
<reference>
<source>$enc.xml($ref.source)</source>
<url>$enc.xml($ref.url)</url>
<name>$enc.xml($ref.name)</name>
</reference>
#end
</references>
<vulnerableSoftware>
#foreach($vs in $vuln.getVulnerableSoftware())
<software#if($vs.hasPreviousVersion()) allPreviousVersion="true"#end>$enc.xml($vs.name)</software>
#end
</vulnerableSoftware>
</suppressedVulnerability>
#end
</vulnerabilities>
#end

View File

@@ -0,0 +1,37 @@
/*
* 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;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.owasp.dependencycheck.utils.Settings;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class BaseTest {
@BeforeClass
public static void setUpClass() throws Exception {
Settings.initialize();
}
@AfterClass
public static void tearDownClass() throws Exception {
Settings.cleanup();
}
}

View File

@@ -18,28 +18,20 @@
package org.owasp.dependencycheck;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.reporting.ReportGenerator;
import org.owasp.dependencycheck.utils.Settings;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class EngineIntegrationTest {
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
public class EngineIntegrationTest extends BaseTest {
@Before
public void setUp() throws Exception {
@@ -57,8 +49,31 @@ public class EngineIntegrationTest {
*/
@Test
public void testScan() throws Exception {
String testClasses = "target/test-classes";
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.
*
* @throws Exception is thrown when an exception occurs.
*/
@Test
public void testEngine() throws Exception {
String testClasses = "target/test-classes";
// 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);
instance.analyzeDependencies();
@@ -69,5 +84,6 @@ public class EngineIntegrationTest {
ReportGenerator rg = new ReportGenerator("DependencyCheck",
instance.getDependencies(), instance.getAnalyzers(), dbProp);
rg.generateReports("./target/", "ALL");
instance.cleanup();
}
}

View File

@@ -18,45 +18,23 @@
package org.owasp.dependencycheck.analyzer;
import java.util.Set;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class AbstractAnalyzerTest {
public AbstractAnalyzerTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
public class AbstractFileTypeAnalyzerTest extends BaseTest {
/**
* Test of newHashSet method, of class AbstractAnalyzer.
*/
@Test
public void testNewHashSet() {
Set result = AbstractAnalyzer.newHashSet("one", "two");
Set result = AbstractFileTypeAnalyzer.newHashSet("one", "two");
assertEquals(2, result.size());
assertTrue(result.contains("one"));
assertTrue(result.contains("two"));

View File

@@ -0,0 +1,104 @@
/*
* 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) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.suppression.SuppressionRule;
import org.owasp.dependencycheck.utils.Settings;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class AbstractSuppressionAnalyzerTest extends BaseTest {
@Before
public void setUp() throws Exception {
try {
final String uri = this.getClass().getClassLoader().getResource("suppressions.xml").toURI().toURL().toString();
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, uri);
} catch (URISyntaxException ex) {
Logger.getLogger(AbstractSuppressionAnalyzerTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (MalformedURLException ex) {
Logger.getLogger(AbstractSuppressionAnalyzerTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Test of getSupportedExtensions method, of class AbstractSuppressionAnalyzer.
*/
@Test
public void testGetSupportedExtensions() {
AbstractSuppressionAnalyzer instance = new AbstractSuppressionAnalyzerImpl();
Set<String> result = instance.getSupportedExtensions();
assertNull(result);
}
/**
* Test of initialize method, of class AbstractSuppressionAnalyzer.
*/
@Test
public void testInitialize() throws Exception {
AbstractSuppressionAnalyzer instance = new AbstractSuppressionAnalyzerImpl();
instance.initialize();
}
/**
* Test of getRules method, of class AbstractSuppressionAnalyzer.
*/
@Test
public void testGetRules() throws Exception {
AbstractSuppressionAnalyzer instance = new AbstractSuppressionAnalyzerImpl();
instance.initialize();
int expCount = 5;
List<SuppressionRule> result = instance.getRules();
assertEquals(expCount, result.size());
}
public class AbstractSuppressionAnalyzerImpl extends AbstractSuppressionAnalyzer {
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public String getName() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public AnalysisPhase getAnalysisPhase() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
}

View File

@@ -18,52 +18,28 @@
package org.owasp.dependencycheck.analyzer;
import java.util.Iterator;
import java.util.Set;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class AnalyzerServiceTest {
public AnalyzerServiceTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
public class AnalyzerServiceTest extends BaseTest {
/**
* Test of getAnalyzers method, of class AnalyzerService.
*/
@Test
public void testGetAnalyzers() {
AnalyzerService instance = AnalyzerService.getInstance();
AnalyzerService instance = new AnalyzerService(Thread.currentThread().getContextClassLoader());
Iterator<Analyzer> result = instance.getAnalyzers();
boolean found = false;
while (result.hasNext()) {
Analyzer a = result.next();
Set<String> e = a.getSupportedExtensions();
if (e != null && e.contains("jar")) {
if ("Jar Analyzer".equals(a.getName())) {
found = true;
}
}

Some files were not shown because too many files have changed in this diff Show More