
de.fraunhofer.iem.scanner.ScannerSettings Maven / Gradle / Ivy
package de.fraunhofer.iem.scanner;
import com.google.common.io.Files;
import crypto.exceptions.CryptoAnalysisParserException;
import crypto.reporting.Reporter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import picocli.CommandLine;
import picocli.CommandLine.ExitCode;
@CommandLine.Command(mixinStandardHelpOptions = true)
public class ScannerSettings implements Callable {
@CommandLine.Option(
names = {"--appPath"},
description = "The path to the jar file to be analyzed",
required = true)
private String appPath = null;
@CommandLine.Option(
names = {"--rulesDir"},
description =
"The path to the ruleset directory. Can be a simple directory or a ZIP file. If you are"
+ " using a ZIP file, please make sure that the path ends with '.zip'",
required = true)
private String rulesDir = null;
@CommandLine.Option(
names = {"--framework"},
description =
"The framework to construct the call graph and the intermediate representation")
private String frameworkOption = null;
@CommandLine.Option(
names = {"--cg"},
description =
"The call graph to resolve method calls. Possible values are CHA, SPARK and SPARKLIB (default: CHA)")
private String cg = null;
@CommandLine.Option(
names = {"--sootPath"},
description = "The absolute path of the whole project")
private String sootPath = "";
@CommandLine.Option(
names = {"--reportPath"},
description = "Path for a directory to write the reports into")
private String reportPath = null;
@CommandLine.Option(
names = {"--reportFormat"},
split = ",",
description =
"The format of the report. Possible values are CMD, TXT, SARIF, CSV and CSV_SUMMARY (default: CMD)."
+ " Multiple formats should be split with a comma (e.g. CMD,TXT,CSV)")
private String[] reportFormat = null;
@CommandLine.Option(
names = {"--visualization"},
description = "Visualize the errors (requires --reportPath to be set)")
private boolean visualization = false;
@CommandLine.Option(
names = {"--sparseStrategy"},
description =
"Strategy to sparsify Boomerang queries. Possible values are NONE, TYPE_BASED, and "
+ "ALIAS_AWARE (default: NONE)")
private String sparseStrategyInput = null;
@CommandLine.Option(
names = {"--ignoreSections"},
description =
"Names of packages, classes and methods to be ignored during the analysis. This "
+ "input expects path to a file containing one name per line. For example, "
+ "'de.example.testClass' ignores the class 'testClass', 'de.example.exampleClass.exampleMethod "
+ "ignores the method 'exampleMethod' in 'exampleClass', and 'de.example.*' ignores all classes "
+ "and methods in the package 'example'. Using this option may increase the analysis performance. "
+ "Note that constructors are methods that can be specified with ''.")
private String ignoreSectionsPath = null;
@CommandLine.Option(
names = {"--timeout"},
description =
"Timeout for seeds in milliseconds. If a seed exceeds this value, CryptoAnalysis aborts the "
+ "typestate and extract parameter analysis and continues with the results computed so far. (default: 10000)")
private int timeout = 10000;
public enum CallGraphAlgorithm {
CHA,
SPARK,
SPARK_LIB,
}
public enum Framework {
SOOT,
SOOT_UP,
OPAL
}
public enum SparseStrategy {
NONE,
TYPE_BASED,
ALIAS_AWARE,
}
private CallGraphAlgorithm callGraphAlgorithm;
private Framework framework;
private Collection reportFormats;
private Collection ignoredSections;
private SparseStrategy sparseStrategy;
public ScannerSettings() {
callGraphAlgorithm = CallGraphAlgorithm.CHA;
reportFormats = Set.of(Reporter.ReportFormat.CMD);
framework = Framework.SOOT;
ignoredSections = new ArrayList<>();
sparseStrategy = SparseStrategy.NONE;
}
public void parseSettingsFromCLI(String[] settings) throws CryptoAnalysisParserException {
CommandLine parser = new CommandLine(this);
parser.setOptionsCaseInsensitive(true);
int exitCode = parser.execute(settings);
if (frameworkOption != null) {
framework = parseFrameworkOption(frameworkOption);
}
if (cg != null) {
callGraphAlgorithm = parseCallGraphOption(cg);
}
if (reportFormat != null) {
reportFormats = parseReportFormatOption(reportFormat);
}
if (ignoreSectionsPath != null) {
ignoredSections = parseIgnoredSectionOption(ignoreSectionsPath);
}
if (visualization && reportPath == null) {
throw new CryptoAnalysisParserException(
"If visualization is enabled, the reportPath has to be set");
}
if (sparseStrategyInput != null) {
sparseStrategy = parseSparseStrategyOption(sparseStrategyInput);
}
if (timeout < 0) {
throw new CryptoAnalysisParserException("Timeout should not be less than 0");
}
if (exitCode != ExitCode.OK) {
throw new CryptoAnalysisParserException("Error while parsing the CLI arguments");
}
}
private Framework parseFrameworkOption(String option) throws CryptoAnalysisParserException {
String frameworkValue = option.toLowerCase();
return switch (frameworkValue) {
case "soot" -> Framework.SOOT;
case "soot_up" -> Framework.SOOT_UP;
case "opal" -> Framework.OPAL;
default ->
throw new CryptoAnalysisParserException(
"Incorrect framework option: " + option);
};
}
private CallGraphAlgorithm parseCallGraphOption(String option)
throws CryptoAnalysisParserException {
String callGraphValue = option.toLowerCase();
return switch (callGraphValue) {
case "cha" -> CallGraphAlgorithm.CHA;
case "spark" -> CallGraphAlgorithm.SPARK;
case "sparklib" -> CallGraphAlgorithm.SPARK_LIB;
default ->
throw new CryptoAnalysisParserException(
"Incorrect call graph value: " + option);
};
}
private Collection parseReportFormatOption(String[] settings)
throws CryptoAnalysisParserException {
Collection formats = new HashSet<>();
for (String format : settings) {
String reportFormatValue = format.toLowerCase();
switch (reportFormatValue) {
case "cmd":
formats.add(Reporter.ReportFormat.CMD);
break;
case "txt":
formats.add(Reporter.ReportFormat.TXT);
break;
case "sarif":
formats.add(Reporter.ReportFormat.SARIF);
break;
case "csv":
formats.add(Reporter.ReportFormat.CSV);
break;
case "csv_summary":
formats.add(Reporter.ReportFormat.CSV_SUMMARY);
break;
case "github_annotation":
formats.add(Reporter.ReportFormat.GITHUB_ANNOTATION);
break;
default:
throw new CryptoAnalysisParserException(
"Incorrect report format value: " + format);
}
}
return formats;
}
private Collection parseIgnoredSectionOption(String path)
throws CryptoAnalysisParserException {
Collection result = new ArrayList<>();
File ignorePackageFile = new File(path);
if (ignorePackageFile.isFile() && ignorePackageFile.canRead()) {
try {
List lines = Files.readLines(ignorePackageFile, Charset.defaultCharset());
result.addAll(lines);
} catch (IOException e) {
throw new CryptoAnalysisParserException(
"Error while reading file " + ignorePackageFile + ": " + e.getMessage());
}
} else {
throw new CryptoAnalysisParserException(
ignorePackageFile + " is not a file or cannot be read");
}
return result;
}
private SparseStrategy parseSparseStrategyOption(String option) {
String strategyLowerCase = option.toLowerCase();
return switch (strategyLowerCase) {
case "none" -> SparseStrategy.NONE;
case "type_based" -> SparseStrategy.TYPE_BASED;
case "alias_aware" -> SparseStrategy.ALIAS_AWARE;
default ->
throw new CryptoAnalysisParserException(
"Incorrect sparsification strategy: " + option);
};
}
public String getApplicationPath() {
return appPath;
}
public void setApplicationPath(String applicationPath) {
this.appPath = applicationPath;
}
public String getRulesetPath() {
return rulesDir;
}
public void setRulesetPath(String rulesetPath) {
this.rulesDir = rulesetPath;
}
public Framework getFramework() {
return framework;
}
public void setFramework(Framework framework) {
this.framework = framework;
}
public CallGraphAlgorithm getCallGraph() {
return callGraphAlgorithm;
}
public void setCallGraph(CallGraphAlgorithm callGraphAlgorithm) {
this.callGraphAlgorithm = callGraphAlgorithm;
}
public String getSootPath() {
return sootPath;
}
public void setSootPath(String sootPath) {
this.sootPath = sootPath;
}
public String getReportDirectory() {
return reportPath;
}
public void setReportDirectory(String reportDirectory) {
this.reportPath = reportDirectory;
}
public Collection getReportFormats() {
return reportFormats;
}
public void setReportFormats(Collection reportFormats) {
this.reportFormats = new HashSet<>(reportFormats);
}
public boolean isVisualization() {
return visualization;
}
public void setVisualization(boolean visualization) {
this.visualization = visualization;
}
public SparseStrategy getSparseStrategy() {
return sparseStrategy;
}
public void setSparseStrategy(SparseStrategy strategy) {
this.sparseStrategy = strategy;
}
public Collection getIgnoredSections() {
return ignoredSections;
}
public void setIgnoredSections(Collection ignoredSections) {
this.ignoredSections = new HashSet<>(ignoredSections);
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
@Override
public Integer call() throws Exception {
return 0;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy