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
585 public boolean isPythonDistributionDisabled() {
586 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST);
587 }
588
589
590
591
592
593
594 public boolean isPythonPackageDisabled() {
595 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG);
596 }
597
598
599
600
601
602
603 public boolean isRubyGemspecDisabled() {
604 return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS);
605 }
606
607
608
609
610
611
612 public boolean isCmakeDisabled() {
613 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE);
614 }
615
616
617
618
619
620
621 public boolean isAutoconfDisabled() {
622 return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF);
623 }
624
625
626
627
628
629
630 public boolean isComposerDisabled() {
631 return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER);
632 }
633
634
635
636
637
638
639 public boolean isNexusDisabled() {
640 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
641 }
642
643
644
645
646
647
648 public boolean isOpenSSLDisabled() {
649 return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL);
650 }
651
652
653
654
655
656
657 public boolean isNodeJsDisabled() {
658 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS);
659 }
660
661
662
663
664
665
666 public boolean isCentralDisabled() {
667 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
668 }
669
670
671
672
673
674
675 public String getNexusUrl() {
676 if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) {
677 return null;
678 } else {
679 return line.getOptionValue(ARGUMENT.NEXUS_URL);
680 }
681 }
682
683
684
685
686
687
688 public boolean isNexusUsesProxy() {
689
690
691 if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) {
692 try {
693 return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY);
694 } catch (InvalidSettingException ise) {
695 return true;
696 }
697 } else {
698 return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY));
699 }
700 }
701
702
703
704
705 public void printHelp() {
706 final HelpFormatter formatter = new HelpFormatter();
707 final Options options = new Options();
708 addStandardOptions(options);
709 if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) {
710 addAdvancedOptions(options);
711 }
712 final String helpMsg = String.format("%n%s"
713 + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
714 + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n",
715 Settings.getString("application.name", "DependencyCheck"),
716 Settings.getString("application.name", "DependencyCheck"));
717
718 formatter.printHelp(Settings.getString("application.name", "DependencyCheck"),
719 helpMsg,
720 options,
721 "",
722 true);
723 }
724
725
726
727
728
729
730 public String[] getScanFiles() {
731 return line.getOptionValues(ARGUMENT.SCAN);
732 }
733
734
735
736
737
738
739 public String[] getExcludeList() {
740 return line.getOptionValues(ARGUMENT.EXCLUDE);
741 }
742
743
744
745
746
747
748 public String getReportDirectory() {
749 return line.getOptionValue(ARGUMENT.OUT, ".");
750 }
751
752
753
754
755
756
757 public String getPathToMono() {
758 return line.getOptionValue(ARGUMENT.PATH_TO_MONO);
759 }
760
761
762
763
764
765
766 public String getPathToBundleAudit() {
767 return line.getOptionValue(ARGUMENT.PATH_TO_BUNDLE_AUDIT);
768 }
769
770
771
772
773
774
775 public String getReportFormat() {
776 return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML");
777 }
778
779
780
781
782
783
784 public String getProjectName() {
785 final String appName = line.getOptionValue(ARGUMENT.APP_NAME);
786 String name = line.getOptionValue(ARGUMENT.PROJECT);
787 if (name == null && appName != null) {
788 name = appName;
789 LOGGER.warn("The '" + ARGUMENT.APP_NAME + "' argument should no longer be used; use '" + ARGUMENT.PROJECT + "' instead.");
790 }
791 return name;
792 }
793
794
795
796
797
798
799 public String getBaseCve12Url() {
800 return line.getOptionValue(ARGUMENT.CVE_BASE_12);
801 }
802
803
804
805
806
807
808 public String getBaseCve20Url() {
809 return line.getOptionValue(ARGUMENT.CVE_BASE_20);
810 }
811
812
813
814
815
816
817 public String getModifiedCve12Url() {
818 return line.getOptionValue(ARGUMENT.CVE_MOD_12);
819 }
820
821
822
823
824
825
826 public String getModifiedCve20Url() {
827 return line.getOptionValue(ARGUMENT.CVE_MOD_20);
828 }
829
830
831
832
833
834
835 public String getConnectionTimeout() {
836 return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT);
837 }
838
839
840
841
842
843
844 @SuppressWarnings("deprecation")
845 public String getProxyServer() {
846
847 String server = line.getOptionValue(ARGUMENT.PROXY_SERVER);
848 if (server == null) {
849 server = line.getOptionValue(ARGUMENT.PROXY_URL);
850 if (server != null) {
851 LOGGER.warn("An old command line argument 'proxyurl' was detected; use proxyserver instead");
852 }
853 }
854 return server;
855 }
856
857
858
859
860
861
862 public String getProxyPort() {
863 return line.getOptionValue(ARGUMENT.PROXY_PORT);
864 }
865
866
867
868
869
870
871 public String getProxyUsername() {
872 return line.getOptionValue(ARGUMENT.PROXY_USERNAME);
873 }
874
875
876
877
878
879
880 public String getProxyPassword() {
881 return line.getOptionValue(ARGUMENT.PROXY_PASSWORD);
882 }
883
884
885
886
887
888
889 public String getDataDirectory() {
890 return line.getOptionValue(ARGUMENT.DATA_DIRECTORY);
891 }
892
893
894
895
896
897
898 public File getPropertiesFile() {
899 final String path = line.getOptionValue(ARGUMENT.PROP);
900 if (path != null) {
901 return new File(path);
902 }
903 return null;
904 }
905
906
907
908
909
910
911 public String getVerboseLog() {
912 return line.getOptionValue(ARGUMENT.VERBOSE_LOG);
913 }
914
915
916
917
918
919
920 public String getSuppressionFile() {
921 return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE);
922 }
923
924
925
926
927
928
929
930 public void printVersionInfo() {
931 final String version = String.format("%s version %s",
932 Settings.getString(Settings.KEYS.APPLICATION_VAME, "dependency-check"),
933 Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
934 System.out.println(version);
935 }
936
937
938
939
940
941
942 public boolean isAutoUpdate() {
943 return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE);
944 }
945
946
947
948
949
950
951 public boolean isUpdateOnly() {
952 return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY);
953 }
954
955
956
957
958
959
960 public boolean isPurge() {
961 return line != null && line.hasOption(ARGUMENT.PURGE_NVD);
962 }
963
964
965
966
967
968
969 public String getDatabaseDriverName() {
970 return line.getOptionValue(ARGUMENT.DB_DRIVER);
971 }
972
973
974
975
976
977
978 public String getDatabaseDriverPath() {
979 return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH);
980 }
981
982
983
984
985
986
987 public String getConnectionString() {
988 return line.getOptionValue(ARGUMENT.CONNECTION_STRING);
989 }
990
991
992
993
994
995
996 public String getDatabaseUser() {
997 return line.getOptionValue(ARGUMENT.DB_NAME);
998 }
999
1000
1001
1002
1003
1004
1005 public String getDatabasePassword() {
1006 return line.getOptionValue(ARGUMENT.DB_PASSWORD);
1007 }
1008
1009
1010
1011
1012
1013
1014 public String getAdditionalZipExtensions() {
1015 return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS);
1016 }
1017
1018
1019
1020
1021
1022
1023 public Integer getCveValidForHours() {
1024 final String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS);
1025 if (v != null) {
1026 return Integer.parseInt(v);
1027 }
1028 return null;
1029 }
1030
1031
1032
1033
1034 public static class ARGUMENT {
1035
1036
1037
1038
1039 public static final String SCAN = "scan";
1040
1041
1042
1043 public static final String SCAN_SHORT = "s";
1044
1045
1046
1047 public static final String DISABLE_AUTO_UPDATE = "noupdate";
1048
1049
1050
1051 public static final String DISABLE_AUTO_UPDATE_SHORT = "n";
1052
1053
1054
1055 public static final String UPDATE_ONLY = "updateonly";
1056
1057
1058
1059 public static final String PURGE_NVD = "purge";
1060
1061
1062
1063 public static final String OUT = "out";
1064
1065
1066
1067 public static final String OUT_SHORT = "o";
1068
1069
1070
1071 public static final String OUTPUT_FORMAT = "format";
1072
1073
1074
1075 public static final String OUTPUT_FORMAT_SHORT = "f";
1076
1077
1078
1079 public static final String PROJECT = "project";
1080
1081
1082
1083
1084
1085 @Deprecated
1086 public static final String APP_NAME = "app";
1087
1088
1089
1090
1091
1092 @Deprecated
1093 public static final String APP_NAME_SHORT = "a";
1094
1095
1096
1097 public static final String HELP = "help";
1098
1099
1100
1101 public static final String ADVANCED_HELP = "advancedHelp";
1102
1103
1104
1105 public static final String HELP_SHORT = "h";
1106
1107
1108
1109 public static final String VERSION_SHORT = "v";
1110
1111
1112
1113 public static final String VERSION = "version";
1114
1115
1116
1117 public static final String PROXY_PORT = "proxyport";
1118
1119
1120
1121 public static final String PROXY_SERVER = "proxyserver";
1122
1123
1124
1125
1126
1127 @Deprecated
1128 public static final String PROXY_URL = "proxyurl";
1129
1130
1131
1132 public static final String PROXY_USERNAME = "proxyuser";
1133
1134
1135
1136 public static final String PROXY_PASSWORD = "proxypass";
1137
1138
1139
1140 public static final String CONNECTION_TIMEOUT_SHORT = "c";
1141
1142
1143
1144 public static final String CONNECTION_TIMEOUT = "connectiontimeout";
1145
1146
1147
1148 public static final String PROP_SHORT = "P";
1149
1150
1151
1152 public static final String PROP = "propertyfile";
1153
1154
1155
1156 public static final String DATA_DIRECTORY = "data";
1157
1158
1159
1160 public static final String CVE_MOD_12 = "cveUrl12Modified";
1161
1162
1163
1164 public static final String CVE_MOD_20 = "cveUrl20Modified";
1165
1166
1167
1168 public static final String CVE_BASE_12 = "cveUrl12Base";
1169
1170
1171
1172 public static final String CVE_BASE_20 = "cveUrl20Base";
1173
1174
1175
1176 public static final String DATA_DIRECTORY_SHORT = "d";
1177
1178
1179
1180 public static final String VERBOSE_LOG = "log";
1181
1182
1183
1184 public static final String VERBOSE_LOG_SHORT = "l";
1185
1186
1187
1188
1189 public static final String SYM_LINK_DEPTH = "symLink";
1190
1191
1192
1193 public static final String SUPPRESSION_FILE = "suppression";
1194
1195
1196
1197 public static final String CVE_VALID_FOR_HOURS = "cveValidForHours";
1198
1199
1200
1201 public static final String DISABLE_JAR = "disableJar";
1202
1203
1204
1205 public static final String DISABLE_ARCHIVE = "disableArchive";
1206
1207
1208
1209 public static final String DISABLE_PY_DIST = "disablePyDist";
1210
1211
1212
1213 public static final String DISABLE_PY_PKG = "disablePyPkg";
1214
1215
1216
1217 public static final String DISABLE_COMPOSER = "disableComposer";
1218
1219
1220
1221 public static final String DISABLE_RUBYGEMS = "disableRubygems";
1222
1223
1224
1225 public static final String DISABLE_AUTOCONF = "disableAutoconf";
1226
1227
1228
1229 public static final String DISABLE_CMAKE = "disableCmake";
1230
1231
1232
1233 public static final String DISABLE_ASSEMBLY = "disableAssembly";
1234
1235
1236
1237 public static final String DISABLE_BUNDLE_AUDIT = "disableBundleAudit";
1238
1239
1240
1241 public static final String DISABLE_NUSPEC = "disableNuspec";
1242
1243
1244
1245 public static final String DISABLE_CENTRAL = "disableCentral";
1246
1247
1248
1249 public static final String DISABLE_NEXUS = "disableNexus";
1250
1251
1252
1253 public static final String DISABLE_OPENSSL = "disableOpenSSL";
1254
1255
1256
1257 public static final String DISABLE_NODE_JS = "disableNodeJS";
1258
1259
1260
1261 public static final String NEXUS_URL = "nexus";
1262
1263
1264
1265 public static final String NEXUS_USES_PROXY = "nexusUsesProxy";
1266
1267
1268
1269 public static final String CONNECTION_STRING = "connectionString";
1270
1271
1272
1273 public static final String DB_NAME = "dbUser";
1274
1275
1276
1277 public static final String DB_PASSWORD = "dbPassword";
1278
1279
1280
1281 public static final String DB_DRIVER = "dbDriverName";
1282
1283
1284
1285 public static final String DB_DRIVER_PATH = "dbDriverPath";
1286
1287
1288
1289 public static final String PATH_TO_MONO = "mono";
1290
1291
1292
1293 public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
1294
1295
1296
1297 public static final String EXCLUDE = "exclude";
1298
1299
1300
1301 public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit";
1302 }
1303 }