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 cveValidForHours = Option.builder().argName("hours").hasArg().longOpt(ARGUMENT.CVE_VALID_FOR_HOURS)
281 .desc("The number of hours to wait before checking for new updates from the NVD.")
282 .build();
283
284 final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL)
285 .desc("Enables the experimental analzers.")
286 .build();
287
288
289 final OptionGroup og = new OptionGroup();
290 og.addOption(path);
291
292 final OptionGroup exog = new OptionGroup();
293 exog.addOption(excludes);
294
295 options.addOptionGroup(og)
296 .addOptionGroup(exog)
297 .addOption(projectName)
298 .addOption(out)
299 .addOption(outputFormat)
300 .addOption(version)
301 .addOption(help)
302 .addOption(advancedHelp)
303 .addOption(noUpdate)
304 .addOption(symLinkDepth)
305 .addOption(props)
306 .addOption(verboseLog)
307 .addOption(suppressionFile)
308 .addOption(cveValidForHours)
309 .addOption(experimentalEnabled);
310 }
311
312
313
314
315
316
317
318
319
320 @SuppressWarnings("static-access")
321 private void addAdvancedOptions(final Options options) throws IllegalArgumentException {
322
323 final Option cve12Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_12)
324 .desc("Base URL for each year’s CVE 1.2, the %d will be replaced with the year. ")
325 .build();
326
327 final Option cve20Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_20)
328 .desc("Base URL for each year’s CVE 2.0, the %d will be replaced with the year.")
329 .build();
330
331 final Option cve12Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_12)
332 .desc("URL for the modified CVE 1.2.")
333 .build();
334
335 final Option cve20Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_20)
336 .desc("URL for the modified CVE 2.0.")
337 .build();
338
339 final Option updateOnly = Option.builder().longOpt(ARGUMENT.UPDATE_ONLY)
340 .desc("Only update the local NVD data cache; no scan will be executed.").build();
341
342 final Option data = Option.builder(ARGUMENT.DATA_DIRECTORY_SHORT).argName("path").hasArg().longOpt(ARGUMENT.DATA_DIRECTORY)
343 .desc("The location of the H2 Database file. This option should generally not be set.")
344 .build();
345
346 final Option nexusUrl = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.NEXUS_URL)
347 .desc("The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). "
348 + "If not set the Nexus Analyzer will be disabled.").build();
349
350 final Option nexusUsesProxy = Option.builder().argName("true/false").hasArg().longOpt(ARGUMENT.NEXUS_USES_PROXY)
351 .desc("Whether or not the configured proxy should be used when connecting to Nexus.")
352 .build();
353
354 final Option additionalZipExtensions = Option.builder().argName("extensions").hasArg()
355 .longOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS)
356 .desc("A comma separated list of additional extensions to be scanned as ZIP files "
357 + "(ZIP, EAR, WAR are already treated as zip files)").build();
358
359 final Option pathToMono = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.PATH_TO_MONO)
360 .desc("The path to Mono for .NET Assembly analysis on non-windows systems.")
361 .build();
362
363 final Option pathToBundleAudit = Option.builder().argName("path").hasArg()
364 .longOpt(ARGUMENT.PATH_TO_BUNDLE_AUDIT)
365 .desc("The path to bundle-audit for Gem bundle analysis.").build();
366
367 final Option connectionTimeout = Option.builder(ARGUMENT.CONNECTION_TIMEOUT_SHORT).argName("timeout").hasArg()
368 .longOpt(ARGUMENT.CONNECTION_TIMEOUT).desc("The connection timeout (in milliseconds) to use when downloading resources.")
369 .build();
370
371 final Option proxyServer = Option.builder().argName("server").hasArg().longOpt(ARGUMENT.PROXY_SERVER)
372 .desc("The proxy server to use when downloading resources.").build();
373
374 final Option proxyPort = Option.builder().argName("port").hasArg().longOpt(ARGUMENT.PROXY_PORT)
375 .desc("The proxy port to use when downloading resources.").build();
376
377 final Option proxyUsername = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.PROXY_USERNAME)
378 .desc("The proxy username to use when downloading resources.").build();
379
380 final Option proxyPassword = Option.builder().argName("pass").hasArg().longOpt(ARGUMENT.PROXY_PASSWORD)
381 .desc("The proxy password to use when downloading resources.").build();
382
383 final Option connectionString = Option.builder().argName("connStr").hasArg().longOpt(ARGUMENT.CONNECTION_STRING)
384 .desc("The connection string to the database.").build();
385
386 final Option dbUser = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.DB_NAME)
387 .desc("The username used to connect to the database.").build();
388
389 final Option dbPassword = Option.builder().argName("password").hasArg().longOpt(ARGUMENT.DB_PASSWORD)
390 .desc("The password for connecting to the database.").build();
391
392 final Option dbDriver = Option.builder().argName("driver").hasArg().longOpt(ARGUMENT.DB_DRIVER)
393 .desc("The database driver name.").build();
394
395 final Option dbDriverPath = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.DB_DRIVER_PATH)
396 .desc("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.")
397 .build();
398
399 final Option disableJarAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_JAR)
400 .desc("Disable the Jar Analyzer.").build();
401
402 final Option disableArchiveAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ARCHIVE)
403 .desc("Disable the Archive Analyzer.").build();
404
405 final Option disableNuspecAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NUSPEC)
406 .desc("Disable the Nuspec Analyzer.").build();
407
408 final Option disableAssemblyAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ASSEMBLY)
409 .desc("Disable the .NET Assembly Analyzer.").build();
410
411 final Option disablePythonDistributionAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_DIST)
412 .desc("Disable the Python Distribution Analyzer.").build();
413
414 final Option disablePythonPackageAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_PKG)
415 .desc("Disable the Python Package Analyzer.").build();
416
417 final Option disableComposerAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_COMPOSER)
418 .desc("Disable the PHP Composer Analyzer.").build();
419
420 final Option disableAutoconfAnalyzer = Option.builder()
421 .longOpt(ARGUMENT.DISABLE_AUTOCONF)
422 .desc("Disable the Autoconf Analyzer.").build();
423
424 final Option disableOpenSSLAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_OPENSSL)
425 .desc("Disable the OpenSSL Analyzer.").build();
426 final Option disableCmakeAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CMAKE)
427 .desc("Disable the Cmake Analyzer.").build();
428
429 final Option disableCentralAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CENTRAL)
430 .desc("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable "
431 + "the Nexus Analyzer.").build();
432
433 final Option disableNexusAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NEXUS)
434 .desc("Disable the Nexus Analyzer.").build();
435
436 final Option purge = Option.builder().longOpt(ARGUMENT.PURGE_NVD)
437 .desc("Purges the local NVD data cache")
438 .build();
439
440 options.addOption(updateOnly)
441 .addOption(cve12Base)
442 .addOption(cve20Base)
443 .addOption(cve12Modified)
444 .addOption(cve20Modified)
445 .addOption(proxyPort)
446 .addOption(proxyServer)
447 .addOption(proxyUsername)
448 .addOption(proxyPassword)
449 .addOption(connectionTimeout)
450 .addOption(connectionString)
451 .addOption(dbUser)
452 .addOption(data)
453 .addOption(dbPassword)
454 .addOption(dbDriver)
455 .addOption(dbDriverPath)
456 .addOption(disableJarAnalyzer)
457 .addOption(disableArchiveAnalyzer)
458 .addOption(disableAssemblyAnalyzer)
459 .addOption(pathToBundleAudit)
460 .addOption(disablePythonDistributionAnalyzer)
461 .addOption(disableCmakeAnalyzer)
462 .addOption(disablePythonPackageAnalyzer)
463 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_RUBYGEMS)
464 .desc("Disable the Ruby Gemspec Analyzer.").build())
465 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_BUNDLE_AUDIT)
466 .desc("Disable the Ruby Bundler-Audit Analyzer.").build())
467 .addOption(disableAutoconfAnalyzer)
468 .addOption(disableComposerAnalyzer)
469 .addOption(disableOpenSSLAnalyzer)
470 .addOption(disableNuspecAnalyzer)
471 .addOption(disableCentralAnalyzer)
472 .addOption(disableNexusAnalyzer)
473 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_NODE_JS)
474 .desc("Disable the Node.js Package Analyzer.").build())
475 .addOption(nexusUrl)
476 .addOption(nexusUsesProxy)
477 .addOption(additionalZipExtensions)
478 .addOption(pathToMono)
479 .addOption(pathToBundleAudit)
480 .addOption(purge);
481 }
482
483
484
485
486
487
488
489
490
491
492 @SuppressWarnings({"static-access", "deprecation"})
493 private void addDeprecatedOptions(final Options options) throws IllegalArgumentException {
494
495 final Option proxyServer = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.PROXY_URL)
496 .desc("The proxy url argument is deprecated, use proxyserver instead.")
497 .build();
498 final Option appName = Option.builder(ARGUMENT.APP_NAME_SHORT).argName("name").hasArg().longOpt(ARGUMENT.APP_NAME)
499 .desc("The name of the project being scanned.")
500 .build();
501
502 options.addOption(proxyServer);
503 options.addOption(appName);
504 }
505
506
507
508
509
510
511 public boolean isGetVersion() {
512 return (line != null) && line.hasOption(ARGUMENT.VERSION);
513 }
514
515
516
517
518
519
520 public boolean isGetHelp() {
521 return (line != null) && line.hasOption(ARGUMENT.HELP);
522 }
523
524
525
526
527
528
529 public boolean isRunScan() {
530 return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN);
531 }
532
533
534
535
536
537
538
539 public int getSymLinkDepth() {
540 int value = 0;
541 try {
542 value = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH, "0"));
543 if (value < 0) {
544 value = 0;
545 }
546 } catch (NumberFormatException ex) {
547 LOGGER.debug("Symbolic link was not a number");
548 }
549 return value;
550 }
551
552
553
554
555
556
557
558 public boolean isJarDisabled() {
559 return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR);
560 }
561
562
563
564
565
566
567
568 public boolean isArchiveDisabled() {
569 return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE);
570 }
571
572
573
574
575
576
577
578 public boolean isNuspecDisabled() {
579 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC);
580 }
581
582
583
584
585
586
587
588 public boolean isAssemblyDisabled() {
589 return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY);
590 }
591
592
593
594
595
596
597
598
599 public boolean isBundleAuditDisabled() {
600 return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT);
601 }
602
603
604
605
606
607
608
609 public boolean isPythonDistributionDisabled() {
610 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST);
611 }
612
613
614
615
616
617
618
619 public boolean isPythonPackageDisabled() {
620 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG);
621 }
622
623
624
625
626
627
628
629 public boolean isRubyGemspecDisabled() {
630 return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS);
631 }
632
633
634
635
636
637
638
639 public boolean isCmakeDisabled() {
640 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE);
641 }
642
643
644
645
646
647
648
649 public boolean isAutoconfDisabled() {
650 return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF);
651 }
652
653
654
655
656
657
658
659 public boolean isComposerDisabled() {
660 return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER);
661 }
662
663
664
665
666
667
668
669 public boolean isNexusDisabled() {
670 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
671 }
672
673
674
675
676
677
678
679 public boolean isOpenSSLDisabled() {
680 return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL);
681 }
682
683
684
685
686
687
688
689 public boolean isNodeJsDisabled() {
690 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS);
691 }
692
693
694
695
696
697
698
699 public boolean isCentralDisabled() {
700 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
701 }
702
703
704
705
706
707
708
709 public String getNexusUrl() {
710 if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) {
711 return null;
712 } else {
713 return line.getOptionValue(ARGUMENT.NEXUS_URL);
714 }
715 }
716
717
718
719
720
721
722
723
724 public boolean isNexusUsesProxy() {
725
726
727 if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) {
728 try {
729 return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY);
730 } catch (InvalidSettingException ise) {
731 return true;
732 }
733 } else {
734 return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY));
735 }
736 }
737
738
739
740
741 public void printHelp() {
742 final HelpFormatter formatter = new HelpFormatter();
743 final Options options = new Options();
744 addStandardOptions(options);
745 if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) {
746 addAdvancedOptions(options);
747 }
748 final String helpMsg = String.format("%n%s"
749 + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
750 + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n",
751 Settings.getString("application.name", "DependencyCheck"),
752 Settings.getString("application.name", "DependencyCheck"));
753
754 formatter.printHelp(Settings.getString("application.name", "DependencyCheck"),
755 helpMsg,
756 options,
757 "",
758 true);
759 }
760
761
762
763
764
765
766
767 public String[] getScanFiles() {
768 return line.getOptionValues(ARGUMENT.SCAN);
769 }
770
771
772
773
774
775
776
777 public String[] getExcludeList() {
778 return line.getOptionValues(ARGUMENT.EXCLUDE);
779 }
780
781
782
783
784
785
786
787 public String getReportDirectory() {
788 return line.getOptionValue(ARGUMENT.OUT, ".");
789 }
790
791
792
793
794
795
796
797 public String getPathToMono() {
798 return line.getOptionValue(ARGUMENT.PATH_TO_MONO);
799 }
800
801
802
803
804
805
806 public String getPathToBundleAudit() {
807 return line.getOptionValue(ARGUMENT.PATH_TO_BUNDLE_AUDIT);
808 }
809
810
811
812
813
814
815
816 public String getReportFormat() {
817 return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML");
818 }
819
820
821
822
823
824
825 public String getProjectName() {
826 final String appName = line.getOptionValue(ARGUMENT.APP_NAME);
827 String name = line.getOptionValue(ARGUMENT.PROJECT);
828 if (name == null && appName != null) {
829 name = appName;
830 LOGGER.warn("The '" + ARGUMENT.APP_NAME + "' argument should no longer be used; use '" + ARGUMENT.PROJECT + "' instead.");
831 }
832 return name;
833 }
834
835
836
837
838
839
840 public String getBaseCve12Url() {
841 return line.getOptionValue(ARGUMENT.CVE_BASE_12);
842 }
843
844
845
846
847
848
849 public String getBaseCve20Url() {
850 return line.getOptionValue(ARGUMENT.CVE_BASE_20);
851 }
852
853
854
855
856
857
858 public String getModifiedCve12Url() {
859 return line.getOptionValue(ARGUMENT.CVE_MOD_12);
860 }
861
862
863
864
865
866
867 public String getModifiedCve20Url() {
868 return line.getOptionValue(ARGUMENT.CVE_MOD_20);
869 }
870
871
872
873
874
875
876 public String getConnectionTimeout() {
877 return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT);
878 }
879
880
881
882
883
884
885 @SuppressWarnings("deprecation")
886 public String getProxyServer() {
887
888 String server = line.getOptionValue(ARGUMENT.PROXY_SERVER);
889 if (server == null) {
890 server = line.getOptionValue(ARGUMENT.PROXY_URL);
891 if (server != null) {
892 LOGGER.warn("An old command line argument 'proxyurl' was detected; use proxyserver instead");
893 }
894 }
895 return server;
896 }
897
898
899
900
901
902
903 public String getProxyPort() {
904 return line.getOptionValue(ARGUMENT.PROXY_PORT);
905 }
906
907
908
909
910
911
912 public String getProxyUsername() {
913 return line.getOptionValue(ARGUMENT.PROXY_USERNAME);
914 }
915
916
917
918
919
920
921 public String getProxyPassword() {
922 return line.getOptionValue(ARGUMENT.PROXY_PASSWORD);
923 }
924
925
926
927
928
929
930 public String getDataDirectory() {
931 return line.getOptionValue(ARGUMENT.DATA_DIRECTORY);
932 }
933
934
935
936
937
938
939 public File getPropertiesFile() {
940 final String path = line.getOptionValue(ARGUMENT.PROP);
941 if (path != null) {
942 return new File(path);
943 }
944 return null;
945 }
946
947
948
949
950
951
952 public String getVerboseLog() {
953 return line.getOptionValue(ARGUMENT.VERBOSE_LOG);
954 }
955
956
957
958
959
960
961 public String getSuppressionFile() {
962 return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE);
963 }
964
965
966
967
968
969
970
971 public void printVersionInfo() {
972 final String version = String.format("%s version %s",
973 Settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"),
974 Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
975 System.out.println(version);
976 }
977
978
979
980
981
982
983
984
985 public boolean isAutoUpdate() {
986 return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE);
987 }
988
989
990
991
992
993
994
995 public boolean isUpdateOnly() {
996 return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY);
997 }
998
999
1000
1001
1002
1003
1004
1005 public boolean isPurge() {
1006 return line != null && line.hasOption(ARGUMENT.PURGE_NVD);
1007 }
1008
1009
1010
1011
1012
1013
1014
1015 public String getDatabaseDriverName() {
1016 return line.getOptionValue(ARGUMENT.DB_DRIVER);
1017 }
1018
1019
1020
1021
1022
1023
1024
1025 public String getDatabaseDriverPath() {
1026 return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH);
1027 }
1028
1029
1030
1031
1032
1033
1034
1035
1036 public String getConnectionString() {
1037 return line.getOptionValue(ARGUMENT.CONNECTION_STRING);
1038 }
1039
1040
1041
1042
1043
1044
1045
1046
1047 public String getDatabaseUser() {
1048 return line.getOptionValue(ARGUMENT.DB_NAME);
1049 }
1050
1051
1052
1053
1054
1055
1056
1057
1058 public String getDatabasePassword() {
1059 return line.getOptionValue(ARGUMENT.DB_PASSWORD);
1060 }
1061
1062
1063
1064
1065
1066
1067
1068 public String getAdditionalZipExtensions() {
1069 return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS);
1070 }
1071
1072
1073
1074
1075
1076
1077 public Integer getCveValidForHours() {
1078 final String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS);
1079 if (v != null) {
1080 return Integer.parseInt(v);
1081 }
1082 return null;
1083 }
1084
1085
1086
1087
1088
1089
1090 public boolean isExperimentalEnabled() {
1091 return line.hasOption(ARGUMENT.EXPERIMENTAL);
1092 }
1093
1094
1095
1096
1097
1098 public static class ARGUMENT {
1099
1100
1101
1102
1103 public static final String SCAN = "scan";
1104
1105
1106
1107 public static final String SCAN_SHORT = "s";
1108
1109
1110
1111
1112 public static final String DISABLE_AUTO_UPDATE = "noupdate";
1113
1114
1115
1116
1117 public static final String DISABLE_AUTO_UPDATE_SHORT = "n";
1118
1119
1120
1121
1122 public static final String UPDATE_ONLY = "updateonly";
1123
1124
1125
1126
1127 public static final String PURGE_NVD = "purge";
1128
1129
1130
1131
1132 public static final String OUT = "out";
1133
1134
1135
1136
1137 public static final String OUT_SHORT = "o";
1138
1139
1140
1141
1142 public static final String OUTPUT_FORMAT = "format";
1143
1144
1145
1146
1147 public static final String OUTPUT_FORMAT_SHORT = "f";
1148
1149
1150
1151
1152 public static final String PROJECT = "project";
1153
1154
1155
1156
1157
1158
1159 @Deprecated
1160 public static final String APP_NAME = "app";
1161
1162
1163
1164
1165
1166
1167 @Deprecated
1168 public static final String APP_NAME_SHORT = "a";
1169
1170
1171
1172 public static final String HELP = "help";
1173
1174
1175
1176 public static final String ADVANCED_HELP = "advancedHelp";
1177
1178
1179
1180 public static final String HELP_SHORT = "h";
1181
1182
1183
1184 public static final String VERSION_SHORT = "v";
1185
1186
1187
1188 public static final String VERSION = "version";
1189
1190
1191
1192 public static final String PROXY_PORT = "proxyport";
1193
1194
1195
1196 public static final String PROXY_SERVER = "proxyserver";
1197
1198
1199
1200
1201
1202 @Deprecated
1203 public static final String PROXY_URL = "proxyurl";
1204
1205
1206
1207 public static final String PROXY_USERNAME = "proxyuser";
1208
1209
1210
1211 public static final String PROXY_PASSWORD = "proxypass";
1212
1213
1214
1215 public static final String CONNECTION_TIMEOUT_SHORT = "c";
1216
1217
1218
1219 public static final String CONNECTION_TIMEOUT = "connectiontimeout";
1220
1221
1222
1223
1224 public static final String PROP_SHORT = "P";
1225
1226
1227
1228
1229 public static final String PROP = "propertyfile";
1230
1231
1232
1233 public static final String DATA_DIRECTORY = "data";
1234
1235
1236
1237 public static final String CVE_MOD_12 = "cveUrl12Modified";
1238
1239
1240
1241 public static final String CVE_MOD_20 = "cveUrl20Modified";
1242
1243
1244
1245 public static final String CVE_BASE_12 = "cveUrl12Base";
1246
1247
1248
1249 public static final String CVE_BASE_20 = "cveUrl20Base";
1250
1251
1252
1253
1254 public static final String DATA_DIRECTORY_SHORT = "d";
1255
1256
1257
1258 public static final String VERBOSE_LOG = "log";
1259
1260
1261
1262
1263 public static final String VERBOSE_LOG_SHORT = "l";
1264
1265
1266
1267
1268
1269 public static final String SYM_LINK_DEPTH = "symLink";
1270
1271
1272
1273
1274 public static final String SUPPRESSION_FILE = "suppression";
1275
1276
1277
1278
1279 public static final String CVE_VALID_FOR_HOURS = "cveValidForHours";
1280
1281
1282
1283 public static final String DISABLE_JAR = "disableJar";
1284
1285
1286
1287 public static final String DISABLE_ARCHIVE = "disableArchive";
1288
1289
1290
1291 public static final String DISABLE_PY_DIST = "disablePyDist";
1292
1293
1294
1295 public static final String DISABLE_PY_PKG = "disablePyPkg";
1296
1297
1298
1299 public static final String DISABLE_COMPOSER = "disableComposer";
1300
1301
1302
1303 public static final String DISABLE_RUBYGEMS = "disableRubygems";
1304
1305
1306
1307 public static final String DISABLE_AUTOCONF = "disableAutoconf";
1308
1309
1310
1311 public static final String DISABLE_CMAKE = "disableCmake";
1312
1313
1314
1315 public static final String DISABLE_ASSEMBLY = "disableAssembly";
1316
1317
1318
1319 public static final String DISABLE_BUNDLE_AUDIT = "disableBundleAudit";
1320
1321
1322
1323 public static final String DISABLE_NUSPEC = "disableNuspec";
1324
1325
1326
1327 public static final String DISABLE_CENTRAL = "disableCentral";
1328
1329
1330
1331 public static final String DISABLE_NEXUS = "disableNexus";
1332
1333
1334
1335 public static final String DISABLE_OPENSSL = "disableOpenSSL";
1336
1337
1338
1339 public static final String DISABLE_NODE_JS = "disableNodeJS";
1340
1341
1342
1343 public static final String NEXUS_URL = "nexus";
1344
1345
1346
1347
1348 public static final String NEXUS_USES_PROXY = "nexusUsesProxy";
1349
1350
1351
1352 public static final String CONNECTION_STRING = "connectionString";
1353
1354
1355
1356 public static final String DB_NAME = "dbUser";
1357
1358
1359
1360 public static final String DB_PASSWORD = "dbPassword";
1361
1362
1363
1364 public static final String DB_DRIVER = "dbDriverName";
1365
1366
1367
1368
1369 public static final String DB_DRIVER_PATH = "dbDriverPath";
1370
1371
1372
1373
1374 public static final String PATH_TO_MONO = "mono";
1375
1376
1377
1378 public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
1379
1380
1381
1382 public static final String EXCLUDE = "exclude";
1383
1384
1385
1386
1387 public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit";
1388
1389
1390
1391 private static final String EXPERIMENTAL = "enableExperimental";
1392 }
1393 }