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