1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck;
19
20 import java.io.File;
21 import java.io.FileNotFoundException;
22
23 import org.apache.commons.cli.CommandLine;
24 import org.apache.commons.cli.CommandLineParser;
25 import org.apache.commons.cli.DefaultParser;
26 import org.apache.commons.cli.HelpFormatter;
27 import org.apache.commons.cli.Option;
28 import org.apache.commons.cli.OptionGroup;
29 import org.apache.commons.cli.Options;
30 import org.apache.commons.cli.ParseException;
31 import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
32 import org.owasp.dependencycheck.utils.InvalidSettingException;
33 import org.owasp.dependencycheck.utils.Settings;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37
38
39
40
41
42 public final class CliParser {
43
44
45
46
47 private static final Logger LOGGER = LoggerFactory.getLogger(CliParser.class);
48
49
50
51 private CommandLine line;
52
53
54
55 private boolean isValid = true;
56
57
58
59
60
61
62
63
64
65 public void parse(String[] args) throws FileNotFoundException, ParseException {
66 line = parseArgs(args);
67
68 if (line != null) {
69 validateArgs();
70 }
71 }
72
73
74
75
76
77
78
79
80 private CommandLine parseArgs(String[] args) throws ParseException {
81 final CommandLineParser parser = new DefaultParser();
82 final Options options = createCommandLineOptions();
83 return parser.parse(options, args);
84 }
85
86
87
88
89
90
91
92
93
94 private void validateArgs() throws FileNotFoundException, ParseException {
95 if (isUpdateOnly() || isRunScan()) {
96 final String value = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS);
97 if (value != null) {
98 try {
99 final int i = Integer.parseInt(value);
100 if (i < 0) {
101 throw new ParseException("Invalid Setting: cveValidForHours must be a number greater than or equal to 0.");
102 }
103 } catch (NumberFormatException ex) {
104 throw new ParseException("Invalid Setting: cveValidForHours must be a number greater than or equal to 0.");
105 }
106 }
107 }
108 if (isRunScan()) {
109 validatePathExists(getScanFiles(), ARGUMENT.SCAN);
110 validatePathExists(getReportDirectory(), ARGUMENT.OUT);
111 if (getPathToMono() != null) {
112 validatePathExists(getPathToMono(), ARGUMENT.PATH_TO_MONO);
113 }
114 if (!line.hasOption(ARGUMENT.APP_NAME) && !line.hasOption(ARGUMENT.PROJECT)) {
115 throw new ParseException("Missing '" + ARGUMENT.PROJECT + "' argument; the scan cannot be run without the an project name.");
116 }
117 if (line.hasOption(ARGUMENT.OUTPUT_FORMAT)) {
118 final String format = line.getOptionValue(ARGUMENT.OUTPUT_FORMAT);
119 try {
120 Format.valueOf(format);
121 } catch (IllegalArgumentException ex) {
122 final String msg = String.format("An invalid 'format' of '%s' was specified. "
123 + "Supported output formats are XML, HTML, VULN, or ALL", format);
124 throw new ParseException(msg);
125 }
126 }
127 if ((getBaseCve12Url() != null || getBaseCve20Url() != null || getModifiedCve12Url() != null || getModifiedCve20Url() != null)
128 && (getBaseCve12Url() == null || getBaseCve20Url() == null || getModifiedCve12Url() == null || getModifiedCve20Url() == null)) {
129 final String msg = "If one of the CVE URLs is specified they must all be specified; please add the missing CVE URL.";
130 throw new ParseException(msg);
131 }
132 if (line.hasOption((ARGUMENT.SYM_LINK_DEPTH))) {
133 try {
134 final int i = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH));
135 if (i < 0) {
136 throw new ParseException("Symbolic Link Depth (symLink) must be greater than zero.");
137 }
138 } catch (NumberFormatException ex) {
139 throw new ParseException("Symbolic Link Depth (symLink) is not a number.");
140 }
141 }
142 }
143 }
144
145
146
147
148
149
150
151
152
153
154
155 private void validatePathExists(String[] paths, String optType) throws FileNotFoundException {
156 for (String path : paths) {
157 validatePathExists(path, optType);
158 }
159 }
160
161
162
163
164
165
166
167
168
169
170
171 private void validatePathExists(String path, String argumentName) throws FileNotFoundException {
172 if (path == null) {
173 isValid = false;
174 final String msg = String.format("Invalid '%s' argument: null", argumentName);
175 throw new FileNotFoundException(msg);
176 } else if (!path.contains("*") && !path.contains("?")) {
177 File f = new File(path);
178 if ("o".equalsIgnoreCase(argumentName.substring(0, 1)) && !"ALL".equalsIgnoreCase(this.getReportFormat())) {
179 final String checkPath = path.toLowerCase();
180 if (checkPath.endsWith(".html") || checkPath.endsWith(".xml") || checkPath.endsWith(".htm")) {
181 if (f.getParentFile() == null) {
182 f = new File(".", path);
183 }
184 if (!f.getParentFile().isDirectory()) {
185 isValid = false;
186 final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
187 throw new FileNotFoundException(msg);
188 }
189 }
190 } else if (!f.exists()) {
191 isValid = false;
192 final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
193 throw new FileNotFoundException(msg);
194 }
195 } else if (path.startsWith("//") || path.startsWith("\\\\")) {
196 isValid = false;
197 final String msg = String.format("Invalid '%s' argument: '%s'%nUnable to scan paths that start with '//'.", argumentName, path);
198 throw new FileNotFoundException(msg);
199 } else if ((path.endsWith("/*") && !path.endsWith("**/*")) || (path.endsWith("\\*") && path.endsWith("**\\*"))) {
200 final String msg = String.format("Possibly incorrect path '%s' from argument '%s' because it ends with a slash star; "
201 + "dependency-check uses ant-style paths", path, argumentName);
202 LOGGER.warn(msg);
203 }
204 }
205
206
207
208
209
210
211
212 @SuppressWarnings("static-access")
213 private Options createCommandLineOptions() {
214 final Options options = new Options();
215 addStandardOptions(options);
216 addAdvancedOptions(options);
217 addDeprecatedOptions(options);
218 return options;
219 }
220
221
222
223
224
225
226
227 @SuppressWarnings("static-access")
228 private void addStandardOptions(final Options options) throws IllegalArgumentException {
229 final Option help = new Option(ARGUMENT.HELP_SHORT, ARGUMENT.HELP, false,
230 "Print this message.");
231
232 final Option advancedHelp = Option.builder().longOpt(ARGUMENT.ADVANCED_HELP)
233 .desc("Print the advanced help message.").build();
234
235 final Option version = new Option(ARGUMENT.VERSION_SHORT, ARGUMENT.VERSION,
236 false, "Print the version information.");
237
238 final Option noUpdate = new Option(ARGUMENT.DISABLE_AUTO_UPDATE_SHORT, ARGUMENT.DISABLE_AUTO_UPDATE,
239 false, "Disables the automatic updating of the CPE data.");
240
241 final Option projectName = Option.builder().hasArg().argName("name").longOpt(ARGUMENT.PROJECT)
242 .desc("The name of the project being scanned. This is a required argument.")
243 .build();
244
245 final Option path = Option.builder(ARGUMENT.SCAN_SHORT).argName("path").hasArg().longOpt(ARGUMENT.SCAN)
246 .desc("The path to scan - this option can be specified multiple times. Ant style"
247 + " paths are supported (e.g. path/**/*.jar).")
248 .build();
249
250 final Option excludes = Option.builder().argName("pattern").hasArg().longOpt(ARGUMENT.EXCLUDE)
251 .desc("Specify and exclusion pattern. This option can be specified multiple times"
252 + " and it accepts Ant style excludsions.")
253 .build();
254
255 final Option props = Option.builder(ARGUMENT.PROP_SHORT).argName("file").hasArg().longOpt(ARGUMENT.PROP)
256 .desc("A property file to load.")
257 .build();
258
259 final Option out = Option.builder(ARGUMENT.OUT_SHORT).argName("path").hasArg().longOpt(ARGUMENT.OUT)
260 .desc("The folder to write reports to. This defaults to the current directory. "
261 + "It is possible to set this to a specific file name if the format argument is not set to ALL.")
262 .build();
263
264 final Option outputFormat = Option.builder(ARGUMENT.OUTPUT_FORMAT_SHORT).argName("format").hasArg().longOpt(ARGUMENT.OUTPUT_FORMAT)
265 .desc("The output format to write to (XML, HTML, VULN, ALL). The default is HTML.")
266 .build();
267
268 final Option verboseLog = Option.builder(ARGUMENT.VERBOSE_LOG_SHORT).argName("file").hasArg().longOpt(ARGUMENT.VERBOSE_LOG)
269 .desc("The file path to write verbose logging information.")
270 .build();
271
272 final Option symLinkDepth = Option.builder().argName("depth").hasArg().longOpt(ARGUMENT.SYM_LINK_DEPTH)
273 .desc("Sets how deep nested symbolic links will be followed; 0 indicates symbolic links will not be followed.")
274 .build();
275
276 final Option suppressionFile = Option.builder().argName("file").hasArg().longOpt(ARGUMENT.SUPPRESSION_FILE)
277 .desc("The file path to the suppression XML file.")
278 .build();
279
280 final Option hintsFile = Option.builder().argName("file").hasArg().longOpt(ARGUMENT.HINTS_FILE)
281 .desc("The file path to the hints XML file.")
282 .build();
283
284 final Option cveValidForHours = Option.builder().argName("hours").hasArg().longOpt(ARGUMENT.CVE_VALID_FOR_HOURS)
285 .desc("The number of hours to wait before checking for new updates from the NVD.")
286 .build();
287
288 final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL)
289 .desc("Enables the experimental analzers.")
290 .build();
291
292 final Option failOnCVSS = Option.builder().argName("score").hasArg().longOpt(ARGUMENT.FAIL_ON_CVSS)
293 .desc("Specifies if the build should be failed if a CVSS score above a specified level is identified. "
294 + "The default is 11; since the CVSS scores are 0-10, by default the build will never fail.")
295 .build();
296
297
298 final OptionGroup og = new OptionGroup();
299 og.addOption(path);
300
301 final OptionGroup exog = new OptionGroup();
302 exog.addOption(excludes);
303
304 options.addOptionGroup(og)
305 .addOptionGroup(exog)
306 .addOption(projectName)
307 .addOption(out)
308 .addOption(outputFormat)
309 .addOption(version)
310 .addOption(help)
311 .addOption(advancedHelp)
312 .addOption(noUpdate)
313 .addOption(symLinkDepth)
314 .addOption(props)
315 .addOption(verboseLog)
316 .addOption(suppressionFile)
317 .addOption(hintsFile)
318 .addOption(cveValidForHours)
319 .addOption(experimentalEnabled)
320 .addOption(failOnCVSS);
321 }
322
323
324
325
326
327
328
329
330
331 @SuppressWarnings("static-access")
332 private void addAdvancedOptions(final Options options) throws IllegalArgumentException {
333
334 final Option cve12Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_12)
335 .desc("Base URL for each year’s CVE 1.2, the %d will be replaced with the year. ")
336 .build();
337
338 final Option cve20Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_20)
339 .desc("Base URL for each year’s CVE 2.0, the %d will be replaced with the year.")
340 .build();
341
342 final Option cve12Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_12)
343 .desc("URL for the modified CVE 1.2.")
344 .build();
345
346 final Option cve20Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_20)
347 .desc("URL for the modified CVE 2.0.")
348 .build();
349
350 final Option updateOnly = Option.builder().longOpt(ARGUMENT.UPDATE_ONLY)
351 .desc("Only update the local NVD data cache; no scan will be executed.").build();
352
353 final Option data = Option.builder(ARGUMENT.DATA_DIRECTORY_SHORT).argName("path").hasArg().longOpt(ARGUMENT.DATA_DIRECTORY)
354 .desc("The location of the H2 Database file. This option should generally not be set.")
355 .build();
356
357 final Option nexusUrl = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.NEXUS_URL)
358 .desc("The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). "
359 + "If not set the Nexus Analyzer will be disabled.").build();
360
361 final Option nexusUsesProxy = Option.builder().argName("true/false").hasArg().longOpt(ARGUMENT.NEXUS_USES_PROXY)
362 .desc("Whether or not the configured proxy should be used when connecting to Nexus.")
363 .build();
364
365 final Option additionalZipExtensions = Option.builder().argName("extensions").hasArg()
366 .longOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS)
367 .desc("A comma separated list of additional extensions to be scanned as ZIP files "
368 + "(ZIP, EAR, WAR are already treated as zip files)").build();
369
370 final Option pathToMono = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.PATH_TO_MONO)
371 .desc("The path to Mono for .NET Assembly analysis on non-windows systems.")
372 .build();
373
374 final Option pathToBundleAudit = Option.builder().argName("path").hasArg()
375 .longOpt(ARGUMENT.PATH_TO_BUNDLE_AUDIT)
376 .desc("The path to bundle-audit for Gem bundle analysis.").build();
377
378 final Option connectionTimeout = Option.builder(ARGUMENT.CONNECTION_TIMEOUT_SHORT).argName("timeout").hasArg()
379 .longOpt(ARGUMENT.CONNECTION_TIMEOUT).desc("The connection timeout (in milliseconds) to use when downloading resources.")
380 .build();
381
382 final Option proxyServer = Option.builder().argName("server").hasArg().longOpt(ARGUMENT.PROXY_SERVER)
383 .desc("The proxy server to use when downloading resources.").build();
384
385 final Option proxyPort = Option.builder().argName("port").hasArg().longOpt(ARGUMENT.PROXY_PORT)
386 .desc("The proxy port to use when downloading resources.").build();
387
388 final Option proxyUsername = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.PROXY_USERNAME)
389 .desc("The proxy username to use when downloading resources.").build();
390
391 final Option proxyPassword = Option.builder().argName("pass").hasArg().longOpt(ARGUMENT.PROXY_PASSWORD)
392 .desc("The proxy password to use when downloading resources.").build();
393
394 final Option connectionString = Option.builder().argName("connStr").hasArg().longOpt(ARGUMENT.CONNECTION_STRING)
395 .desc("The connection string to the database.").build();
396
397 final Option dbUser = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.DB_NAME)
398 .desc("The username used to connect to the database.").build();
399
400 final Option dbPassword = Option.builder().argName("password").hasArg().longOpt(ARGUMENT.DB_PASSWORD)
401 .desc("The password for connecting to the database.").build();
402
403 final Option dbDriver = Option.builder().argName("driver").hasArg().longOpt(ARGUMENT.DB_DRIVER)
404 .desc("The database driver name.").build();
405
406 final Option dbDriverPath = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.DB_DRIVER_PATH)
407 .desc("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.")
408 .build();
409
410 final Option disableJarAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_JAR)
411 .desc("Disable the Jar Analyzer.").build();
412
413 final Option disableArchiveAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ARCHIVE)
414 .desc("Disable the Archive Analyzer.").build();
415
416 final Option disableNuspecAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NUSPEC)
417 .desc("Disable the Nuspec Analyzer.").build();
418
419 final Option disableAssemblyAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ASSEMBLY)
420 .desc("Disable the .NET Assembly Analyzer.").build();
421
422 final Option disablePythonDistributionAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_DIST)
423 .desc("Disable the Python Distribution Analyzer.").build();
424
425 final Option disablePythonPackageAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_PKG)
426 .desc("Disable the Python Package Analyzer.").build();
427
428 final Option disableComposerAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_COMPOSER)
429 .desc("Disable the PHP Composer Analyzer.").build();
430
431 final Option disableAutoconfAnalyzer = Option.builder()
432 .longOpt(ARGUMENT.DISABLE_AUTOCONF)
433 .desc("Disable the Autoconf Analyzer.").build();
434
435 final Option disableOpenSSLAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_OPENSSL)
436 .desc("Disable the OpenSSL Analyzer.").build();
437 final Option disableCmakeAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CMAKE)
438 .desc("Disable the Cmake Analyzer.").build();
439
440 final Option cocoapodsAnalyzerEnabled = Option.builder().longOpt(ARGUMENT.DISABLE_COCOAPODS)
441 .desc("Disable the CocoaPods Analyzer.").build();
442 final Option swiftPackageManagerAnalyzerEnabled = Option.builder().longOpt(ARGUMENT.DISABLE_SWIFT)
443 .desc("Disable the swift package Analyzer.").build();
444
445 final Option disableCentralAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CENTRAL)
446 .desc("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable "
447 + "the Nexus Analyzer.").build();
448
449 final Option disableNexusAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NEXUS)
450 .desc("Disable the Nexus Analyzer.").build();
451
452 final Option purge = Option.builder().longOpt(ARGUMENT.PURGE_NVD)
453 .desc("Purges the local NVD data cache")
454 .build();
455
456 options.addOption(updateOnly)
457 .addOption(cve12Base)
458 .addOption(cve20Base)
459 .addOption(cve12Modified)
460 .addOption(cve20Modified)
461 .addOption(proxyPort)
462 .addOption(proxyServer)
463 .addOption(proxyUsername)
464 .addOption(proxyPassword)
465 .addOption(connectionTimeout)
466 .addOption(connectionString)
467 .addOption(dbUser)
468 .addOption(data)
469 .addOption(dbPassword)
470 .addOption(dbDriver)
471 .addOption(dbDriverPath)
472 .addOption(disableJarAnalyzer)
473 .addOption(disableArchiveAnalyzer)
474 .addOption(disableAssemblyAnalyzer)
475 .addOption(pathToBundleAudit)
476 .addOption(disablePythonDistributionAnalyzer)
477 .addOption(disableCmakeAnalyzer)
478 .addOption(disablePythonPackageAnalyzer)
479 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_RUBYGEMS)
480 .desc("Disable the Ruby Gemspec Analyzer.").build())
481 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_BUNDLE_AUDIT)
482 .desc("Disable the Ruby Bundler-Audit Analyzer.").build())
483 .addOption(disableAutoconfAnalyzer)
484 .addOption(disableComposerAnalyzer)
485 .addOption(disableOpenSSLAnalyzer)
486 .addOption(disableNuspecAnalyzer)
487 .addOption(disableCentralAnalyzer)
488 .addOption(disableNexusAnalyzer)
489 .addOption(cocoapodsAnalyzerEnabled)
490 .addOption(swiftPackageManagerAnalyzerEnabled)
491 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_NODE_JS)
492 .desc("Disable the Node.js Package Analyzer.").build())
493 .addOption(nexusUrl)
494 .addOption(nexusUsesProxy)
495 .addOption(additionalZipExtensions)
496 .addOption(pathToMono)
497 .addOption(pathToBundleAudit)
498 .addOption(purge);
499 }
500
501
502
503
504
505
506
507
508
509
510 @SuppressWarnings({"static-access", "deprecation"})
511 private void addDeprecatedOptions(final Options options) throws IllegalArgumentException {
512
513 final Option proxyServer = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.PROXY_URL)
514 .desc("The proxy url argument is deprecated, use proxyserver instead.")
515 .build();
516 final Option appName = Option.builder(ARGUMENT.APP_NAME_SHORT).argName("name").hasArg().longOpt(ARGUMENT.APP_NAME)
517 .desc("The name of the project being scanned.")
518 .build();
519
520 options.addOption(proxyServer);
521 options.addOption(appName);
522 }
523
524
525
526
527
528
529 public boolean isGetVersion() {
530 return (line != null) && line.hasOption(ARGUMENT.VERSION);
531 }
532
533
534
535
536
537
538 public boolean isGetHelp() {
539 return (line != null) && line.hasOption(ARGUMENT.HELP);
540 }
541
542
543
544
545
546
547 public boolean isRunScan() {
548 return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN);
549 }
550
551
552
553
554
555
556
557 public int getSymLinkDepth() {
558 int value = 0;
559 try {
560 value = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH, "0"));
561 if (value < 0) {
562 value = 0;
563 }
564 } catch (NumberFormatException ex) {
565 LOGGER.debug("Symbolic link was not a number");
566 }
567 return value;
568 }
569
570
571
572
573
574
575
576 public boolean isJarDisabled() {
577 return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR);
578 }
579
580
581
582
583
584
585
586 public boolean isArchiveDisabled() {
587 return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE);
588 }
589
590
591
592
593
594
595
596 public boolean isNuspecDisabled() {
597 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC);
598 }
599
600
601
602
603
604
605
606 public boolean isAssemblyDisabled() {
607 return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY);
608 }
609
610
611
612
613
614
615
616
617 public boolean isBundleAuditDisabled() {
618 return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT);
619 }
620
621
622
623
624
625
626
627 public boolean isPythonDistributionDisabled() {
628 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST);
629 }
630
631
632
633
634
635
636
637 public boolean isPythonPackageDisabled() {
638 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG);
639 }
640
641
642
643
644
645
646
647 public boolean isRubyGemspecDisabled() {
648 return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS);
649 }
650
651
652
653
654
655
656
657 public boolean isCmakeDisabled() {
658 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE);
659 }
660
661
662
663
664
665
666
667 public boolean isAutoconfDisabled() {
668 return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF);
669 }
670
671
672
673
674
675
676
677 public boolean isComposerDisabled() {
678 return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER);
679 }
680
681
682
683
684
685
686
687 public boolean isNexusDisabled() {
688 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
689 }
690
691
692
693
694
695
696
697 public boolean isOpenSSLDisabled() {
698 return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL);
699 }
700
701
702
703
704
705
706
707 public boolean isNodeJsDisabled() {
708 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS);
709 }
710
711
712
713
714
715
716
717
718 public boolean isCocoapodsAnalyzerDisabled() {
719 return (line != null) && line.hasOption(ARGUMENT.DISABLE_COCOAPODS);
720 }
721
722
723
724
725
726
727
728
729 public boolean isSwiftPackageAnalyzerDisabled() {
730 return (line != null) && line.hasOption(ARGUMENT.DISABLE_SWIFT);
731 }
732
733
734
735
736
737
738
739 public boolean isCentralDisabled() {
740 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
741 }
742
743
744
745
746
747
748
749 public String getNexusUrl() {
750 if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) {
751 return null;
752 } else {
753 return line.getOptionValue(ARGUMENT.NEXUS_URL);
754 }
755 }
756
757
758
759
760
761
762
763
764 public boolean isNexusUsesProxy() {
765
766
767 if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) {
768 try {
769 return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY);
770 } catch (InvalidSettingException ise) {
771 return true;
772 }
773 } else {
774 return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY));
775 }
776 }
777
778
779
780
781 public void printHelp() {
782 final HelpFormatter formatter = new HelpFormatter();
783 final Options options = new Options();
784 addStandardOptions(options);
785 if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) {
786 addAdvancedOptions(options);
787 }
788 final String helpMsg = String.format("%n%s"
789 + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
790 + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n",
791 Settings.getString("application.name", "DependencyCheck"),
792 Settings.getString("application.name", "DependencyCheck"));
793
794 formatter.printHelp(Settings.getString("application.name", "DependencyCheck"),
795 helpMsg,
796 options,
797 "",
798 true);
799 }
800
801
802
803
804
805
806
807 public String[] getScanFiles() {
808 return line.getOptionValues(ARGUMENT.SCAN);
809 }
810
811
812
813
814
815
816
817 public String[] getExcludeList() {
818 return line.getOptionValues(ARGUMENT.EXCLUDE);
819 }
820
821
822
823
824
825
826
827 public String getReportDirectory() {
828 return line.getOptionValue(ARGUMENT.OUT, ".");
829 }
830
831
832
833
834
835
836
837 public String getPathToMono() {
838 return line.getOptionValue(ARGUMENT.PATH_TO_MONO);
839 }
840
841
842
843
844
845
846 public String getPathToBundleAudit() {
847 return line.getOptionValue(ARGUMENT.PATH_TO_BUNDLE_AUDIT);
848 }
849
850
851
852
853
854
855
856 public String getReportFormat() {
857 return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML");
858 }
859
860
861
862
863
864
865 public String getProjectName() {
866 final String appName = line.getOptionValue(ARGUMENT.APP_NAME);
867 String name = line.getOptionValue(ARGUMENT.PROJECT);
868 if (name == null && appName != null) {
869 name = appName;
870 LOGGER.warn("The '" + ARGUMENT.APP_NAME + "' argument should no longer be used; use '" + ARGUMENT.PROJECT + "' instead.");
871 }
872 return name;
873 }
874
875
876
877
878
879
880 public String getBaseCve12Url() {
881 return line.getOptionValue(ARGUMENT.CVE_BASE_12);
882 }
883
884
885
886
887
888
889 public String getBaseCve20Url() {
890 return line.getOptionValue(ARGUMENT.CVE_BASE_20);
891 }
892
893
894
895
896
897
898 public String getModifiedCve12Url() {
899 return line.getOptionValue(ARGUMENT.CVE_MOD_12);
900 }
901
902
903
904
905
906
907 public String getModifiedCve20Url() {
908 return line.getOptionValue(ARGUMENT.CVE_MOD_20);
909 }
910
911
912
913
914
915
916 public String getConnectionTimeout() {
917 return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT);
918 }
919
920
921
922
923
924
925 @SuppressWarnings("deprecation")
926 public String getProxyServer() {
927
928 String server = line.getOptionValue(ARGUMENT.PROXY_SERVER);
929 if (server == null) {
930 server = line.getOptionValue(ARGUMENT.PROXY_URL);
931 if (server != null) {
932 LOGGER.warn("An old command line argument 'proxyurl' was detected; use proxyserver instead");
933 }
934 }
935 return server;
936 }
937
938
939
940
941
942
943 public String getProxyPort() {
944 return line.getOptionValue(ARGUMENT.PROXY_PORT);
945 }
946
947
948
949
950
951
952 public String getProxyUsername() {
953 return line.getOptionValue(ARGUMENT.PROXY_USERNAME);
954 }
955
956
957
958
959
960
961 public String getProxyPassword() {
962 return line.getOptionValue(ARGUMENT.PROXY_PASSWORD);
963 }
964
965
966
967
968
969
970 public String getDataDirectory() {
971 return line.getOptionValue(ARGUMENT.DATA_DIRECTORY);
972 }
973
974
975
976
977
978
979 public File getPropertiesFile() {
980 final String path = line.getOptionValue(ARGUMENT.PROP);
981 if (path != null) {
982 return new File(path);
983 }
984 return null;
985 }
986
987
988
989
990
991
992 public String getVerboseLog() {
993 return line.getOptionValue(ARGUMENT.VERBOSE_LOG);
994 }
995
996
997
998
999
1000
1001 public String getSuppressionFile() {
1002 return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE);
1003 }
1004
1005
1006
1007
1008
1009
1010 public String getHintsFile() {
1011 return line.getOptionValue(ARGUMENT.HINTS_FILE);
1012 }
1013
1014
1015
1016
1017
1018
1019
1020 public void printVersionInfo() {
1021 final String version = String.format("%s version %s",
1022 Settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"),
1023 Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
1024 System.out.println(version);
1025 }
1026
1027
1028
1029
1030
1031
1032
1033
1034 public boolean isAutoUpdate() {
1035 return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE);
1036 }
1037
1038
1039
1040
1041
1042
1043
1044 public boolean isUpdateOnly() {
1045 return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY);
1046 }
1047
1048
1049
1050
1051
1052
1053
1054 public boolean isPurge() {
1055 return line != null && line.hasOption(ARGUMENT.PURGE_NVD);
1056 }
1057
1058
1059
1060
1061
1062
1063
1064 public String getDatabaseDriverName() {
1065 return line.getOptionValue(ARGUMENT.DB_DRIVER);
1066 }
1067
1068
1069
1070
1071
1072
1073
1074 public String getDatabaseDriverPath() {
1075 return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH);
1076 }
1077
1078
1079
1080
1081
1082
1083
1084
1085 public String getConnectionString() {
1086 return line.getOptionValue(ARGUMENT.CONNECTION_STRING);
1087 }
1088
1089
1090
1091
1092
1093
1094
1095
1096 public String getDatabaseUser() {
1097 return line.getOptionValue(ARGUMENT.DB_NAME);
1098 }
1099
1100
1101
1102
1103
1104
1105
1106
1107 public String getDatabasePassword() {
1108 return line.getOptionValue(ARGUMENT.DB_PASSWORD);
1109 }
1110
1111
1112
1113
1114
1115
1116
1117 public String getAdditionalZipExtensions() {
1118 return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS);
1119 }
1120
1121
1122
1123
1124
1125
1126 public Integer getCveValidForHours() {
1127 final String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS);
1128 if (v != null) {
1129 return Integer.parseInt(v);
1130 }
1131 return null;
1132 }
1133
1134
1135
1136
1137
1138
1139 public boolean isExperimentalEnabled() {
1140 return line.hasOption(ARGUMENT.EXPERIMENTAL);
1141 }
1142
1143
1144
1145
1146
1147
1148
1149 public int getFailOnCVSS() {
1150 if (line.hasOption(ARGUMENT.FAIL_ON_CVSS)) {
1151 final String value = line.getOptionValue(ARGUMENT.FAIL_ON_CVSS);
1152 try {
1153 return Integer.parseInt(value);
1154 } catch (NumberFormatException nfe) {
1155 return 11;
1156 }
1157 } else {
1158 return 11;
1159 }
1160 }
1161
1162
1163
1164
1165
1166 public static class ARGUMENT {
1167
1168
1169
1170
1171 public static final String SCAN = "scan";
1172
1173
1174
1175 public static final String SCAN_SHORT = "s";
1176
1177
1178
1179
1180 public static final String DISABLE_AUTO_UPDATE = "noupdate";
1181
1182
1183
1184
1185 public static final String DISABLE_AUTO_UPDATE_SHORT = "n";
1186
1187
1188
1189
1190 public static final String UPDATE_ONLY = "updateonly";
1191
1192
1193
1194
1195 public static final String PURGE_NVD = "purge";
1196
1197
1198
1199
1200 public static final String OUT = "out";
1201
1202
1203
1204
1205 public static final String OUT_SHORT = "o";
1206
1207
1208
1209
1210 public static final String OUTPUT_FORMAT = "format";
1211
1212
1213
1214
1215 public static final String OUTPUT_FORMAT_SHORT = "f";
1216
1217
1218
1219
1220 public static final String PROJECT = "project";
1221
1222
1223
1224
1225
1226
1227 @Deprecated
1228 public static final String APP_NAME = "app";
1229
1230
1231
1232
1233
1234
1235 @Deprecated
1236 public static final String APP_NAME_SHORT = "a";
1237
1238
1239
1240 public static final String HELP = "help";
1241
1242
1243
1244 public static final String ADVANCED_HELP = "advancedHelp";
1245
1246
1247
1248 public static final String HELP_SHORT = "h";
1249
1250
1251
1252 public static final String VERSION_SHORT = "v";
1253
1254
1255
1256 public static final String VERSION = "version";
1257
1258
1259
1260 public static final String PROXY_PORT = "proxyport";
1261
1262
1263
1264 public static final String PROXY_SERVER = "proxyserver";
1265
1266
1267
1268
1269
1270 @Deprecated
1271 public static final String PROXY_URL = "proxyurl";
1272
1273
1274
1275 public static final String PROXY_USERNAME = "proxyuser";
1276
1277
1278
1279 public static final String PROXY_PASSWORD = "proxypass";
1280
1281
1282
1283 public static final String CONNECTION_TIMEOUT_SHORT = "c";
1284
1285
1286
1287 public static final String CONNECTION_TIMEOUT = "connectiontimeout";
1288
1289
1290
1291
1292 public static final String PROP_SHORT = "P";
1293
1294
1295
1296
1297 public static final String PROP = "propertyfile";
1298
1299
1300
1301 public static final String DATA_DIRECTORY = "data";
1302
1303
1304
1305 public static final String CVE_MOD_12 = "cveUrl12Modified";
1306
1307
1308
1309 public static final String CVE_MOD_20 = "cveUrl20Modified";
1310
1311
1312
1313 public static final String CVE_BASE_12 = "cveUrl12Base";
1314
1315
1316
1317 public static final String CVE_BASE_20 = "cveUrl20Base";
1318
1319
1320
1321
1322 public static final String DATA_DIRECTORY_SHORT = "d";
1323
1324
1325
1326 public static final String VERBOSE_LOG = "log";
1327
1328
1329
1330
1331 public static final String VERBOSE_LOG_SHORT = "l";
1332
1333
1334
1335
1336
1337 public static final String SYM_LINK_DEPTH = "symLink";
1338
1339
1340
1341
1342 public static final String SUPPRESSION_FILE = "suppression";
1343
1344
1345
1346 public static final String HINTS_FILE = "hints";
1347
1348
1349
1350
1351 public static final String CVE_VALID_FOR_HOURS = "cveValidForHours";
1352
1353
1354
1355 public static final String DISABLE_JAR = "disableJar";
1356
1357
1358
1359 public static final String DISABLE_ARCHIVE = "disableArchive";
1360
1361
1362
1363 public static final String DISABLE_PY_DIST = "disablePyDist";
1364
1365
1366
1367 public static final String DISABLE_PY_PKG = "disablePyPkg";
1368
1369
1370
1371 public static final String DISABLE_COMPOSER = "disableComposer";
1372
1373
1374
1375 public static final String DISABLE_RUBYGEMS = "disableRubygems";
1376
1377
1378
1379 public static final String DISABLE_AUTOCONF = "disableAutoconf";
1380
1381
1382
1383 public static final String DISABLE_CMAKE = "disableCmake";
1384
1385
1386
1387 public static final String DISABLE_COCOAPODS = "disableCocoapodsAnalyzer";
1388
1389
1390
1391 public static final String DISABLE_SWIFT = "disableSwiftPackageManagerAnalyzer";
1392
1393
1394
1395 public static final String DISABLE_ASSEMBLY = "disableAssembly";
1396
1397
1398
1399 public static final String DISABLE_BUNDLE_AUDIT = "disableBundleAudit";
1400
1401
1402
1403 public static final String DISABLE_NUSPEC = "disableNuspec";
1404
1405
1406
1407 public static final String DISABLE_CENTRAL = "disableCentral";
1408
1409
1410
1411 public static final String DISABLE_NEXUS = "disableNexus";
1412
1413
1414
1415 public static final String DISABLE_OPENSSL = "disableOpenSSL";
1416
1417
1418
1419 public static final String DISABLE_NODE_JS = "disableNodeJS";
1420
1421
1422
1423 public static final String NEXUS_URL = "nexus";
1424
1425
1426
1427
1428 public static final String NEXUS_USES_PROXY = "nexusUsesProxy";
1429
1430
1431
1432 public static final String CONNECTION_STRING = "connectionString";
1433
1434
1435
1436 public static final String DB_NAME = "dbUser";
1437
1438
1439
1440 public static final String DB_PASSWORD = "dbPassword";
1441
1442
1443
1444 public static final String DB_DRIVER = "dbDriverName";
1445
1446
1447
1448
1449 public static final String DB_DRIVER_PATH = "dbDriverPath";
1450
1451
1452
1453
1454 public static final String PATH_TO_MONO = "mono";
1455
1456
1457
1458 public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
1459
1460
1461
1462 public static final String EXCLUDE = "exclude";
1463
1464
1465
1466
1467 public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit";
1468
1469
1470
1471 private static final String EXPERIMENTAL = "enableExperimental";
1472
1473
1474
1475 private static final String FAIL_ON_CVSS = "failOnCVSS";
1476 }
1477 }