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 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Set;
29 import java.util.logging.Level;
30 import java.util.logging.Logger;
31 import org.apache.commons.cli.ParseException;
32 import org.owasp.dependencycheck.data.nvdcve.CveDB;
33 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
34 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
35 import org.owasp.dependencycheck.dependency.Dependency;
36 import org.owasp.dependencycheck.org.apache.tools.ant.DirectoryScanner;
37 import org.owasp.dependencycheck.reporting.ReportGenerator;
38 import org.owasp.dependencycheck.utils.LogUtils;
39 import org.owasp.dependencycheck.utils.Settings;
40
41
42
43
44
45
46 public class App {
47
48
49
50
51 private static final String LOG_PROPERTIES_FILE = "log.properties";
52
53
54
55
56 private static final Logger LOGGER = Logger.getLogger(App.class.getName());
57
58
59
60
61
62
63 public static void main(String[] args) {
64 try {
65 Settings.initialize();
66 final App app = new App();
67 app.run(args);
68 } finally {
69 Settings.cleanup(true);
70 }
71 }
72
73
74
75
76
77
78 public void run(String[] args) {
79 final CliParser cli = new CliParser();
80
81 try {
82 cli.parse(args);
83 } catch (FileNotFoundException ex) {
84 System.err.println(ex.getMessage());
85 cli.printHelp();
86 return;
87 } catch (ParseException ex) {
88 System.err.println(ex.getMessage());
89 cli.printHelp();
90 return;
91 }
92
93 final InputStream in = App.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
94 LogUtils.prepareLogger(in, cli.getVerboseLog());
95
96 if (cli.isGetVersion()) {
97 cli.printVersionInfo();
98 } else if (cli.isRunScan()) {
99 populateSettings(cli);
100 try {
101 runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles(), cli.getExcludeList());
102 } catch (InvalidScanPathException ex) {
103 Logger.getLogger(App.class.getName()).log(Level.SEVERE, "An invalid scan path was detected; unable to scan '//*' paths");
104 }
105 } else {
106 cli.printHelp();
107 }
108 }
109
110
111
112
113
114
115
116
117
118
119
120
121 private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
122 String[] excludes) throws InvalidScanPathException {
123 Engine engine = null;
124 try {
125 engine = new Engine();
126 List<String> antStylePaths = new ArrayList<String>();
127 if (excludes == null || excludes.length == 0) {
128 for (String file : files) {
129 if (file.contains("*") || file.contains("?")) {
130 antStylePaths.add(file);
131 } else {
132 engine.scan(file);
133 }
134 }
135 } else {
136 antStylePaths = Arrays.asList(files);
137 }
138
139 final Set<File> paths = new HashSet<File>();
140 for (String file : antStylePaths) {
141 final DirectoryScanner scanner = new DirectoryScanner();
142 String include = file.replace('\\', '/');
143 File baseDir;
144
145 if (include.startsWith("//")) {
146 throw new InvalidScanPathException("Unable to scan paths specified by //");
147 } else if (include.startsWith("./")) {
148 baseDir = new File(".");
149 include = include.substring(2);
150 } else if (include.startsWith("/")) {
151 baseDir = new File("/");
152 include = include.substring(1);
153 } else if (include.contains("/")) {
154 final int pos = include.indexOf('/');
155 final String tmp = include.substring(0, pos);
156 if (tmp.contains("*") || tmp.contains("?")) {
157 baseDir = new File(".");
158 } else {
159 baseDir = new File(tmp);
160 include = include.substring(pos + 1);
161 }
162 } else {
163 baseDir = new File(".");
164 }
165 scanner.setBasedir(baseDir);
166 scanner.setIncludes(include);
167 if (excludes != null && excludes.length > 0) {
168 scanner.addExcludes(excludes);
169 }
170 scanner.scan();
171 if (scanner.getIncludedFilesCount() > 0) {
172 for (String s : scanner.getIncludedFiles()) {
173 final File f = new File(baseDir, s);
174 paths.add(f);
175 }
176 }
177 }
178 engine.scan(paths);
179
180 engine.analyzeDependencies();
181 final List<Dependency> dependencies = engine.getDependencies();
182 DatabaseProperties prop = null;
183 CveDB cve = null;
184 try {
185 cve = new CveDB();
186 cve.open();
187 prop = cve.getDatabaseProperties();
188 } catch (DatabaseException ex) {
189 LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
190 } finally {
191 if (cve != null) {
192 cve.close();
193 }
194 }
195 final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
196 try {
197 report.generateReports(reportDirectory, outputFormat);
198 } catch (IOException ex) {
199 LOGGER.log(Level.SEVERE, "There was an IO error while attempting to generate the report.");
200 LOGGER.log(Level.FINE, null, ex);
201 } catch (Throwable ex) {
202 LOGGER.log(Level.SEVERE, "There was an error while attempting to generate the report.");
203 LOGGER.log(Level.FINE, null, ex);
204 }
205 } catch (DatabaseException ex) {
206 LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
207 LOGGER.log(Level.FINE, "", ex);
208 } finally {
209 if (engine != null) {
210 engine.cleanup();
211 }
212 }
213 }
214
215
216
217
218
219
220
221 private void populateSettings(CliParser cli) {
222
223 final boolean autoUpdate = cli.isAutoUpdate();
224 final String connectionTimeout = cli.getConnectionTimeout();
225 final String proxyServer = cli.getProxyServer();
226 final String proxyPort = cli.getProxyPort();
227 final String proxyUser = cli.getProxyUsername();
228 final String proxyPass = cli.getProxyPassword();
229 final String dataDirectory = cli.getDataDirectory();
230 final File propertiesFile = cli.getPropertiesFile();
231 final String suppressionFile = cli.getSuppressionFile();
232 final boolean jarDisabled = cli.isJarDisabled();
233 final boolean archiveDisabled = cli.isArchiveDisabled();
234 final boolean assemblyDisabled = cli.isAssemblyDisabled();
235 final boolean nuspecDisabled = cli.isNuspecDisabled();
236 final boolean nexusDisabled = cli.isNexusDisabled();
237 final String nexusUrl = cli.getNexusUrl();
238 final String databaseDriverName = cli.getDatabaseDriverName();
239 final String databaseDriverPath = cli.getDatabaseDriverPath();
240 final String connectionString = cli.getConnectionString();
241 final String databaseUser = cli.getDatabaseUser();
242 final String databasePassword = cli.getDatabasePassword();
243 final String additionalZipExtensions = cli.getAdditionalZipExtensions();
244 final String pathToMono = cli.getPathToMono();
245
246 if (propertiesFile != null) {
247 try {
248 Settings.mergeProperties(propertiesFile);
249 } catch (FileNotFoundException ex) {
250 final String msg = String.format("Unable to load properties file '%s'", propertiesFile.getPath());
251 LOGGER.log(Level.SEVERE, msg);
252 LOGGER.log(Level.FINE, null, ex);
253 } catch (IOException ex) {
254 final String msg = String.format("Unable to find properties file '%s'", propertiesFile.getPath());
255 LOGGER.log(Level.SEVERE, msg);
256 LOGGER.log(Level.FINE, null, ex);
257 }
258 }
259
260
261
262 final boolean nexusUsesProxy = cli.isNexusUsesProxy();
263 if (dataDirectory != null) {
264 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
265 } else if (System.getProperty("basedir") != null) {
266 final File dataDir = new File(System.getProperty("basedir"), "data");
267 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
268 } else {
269 final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath());
270 final File base = jarPath.getParentFile();
271 final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
272 final File dataDir = new File(base, sub);
273 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
274 }
275 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
276 if (proxyServer != null && !proxyServer.isEmpty()) {
277 Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer);
278 }
279 if (proxyPort != null && !proxyPort.isEmpty()) {
280 Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
281 }
282 if (proxyUser != null && !proxyUser.isEmpty()) {
283 Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUser);
284 }
285 if (proxyPass != null && !proxyPass.isEmpty()) {
286 Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPass);
287 }
288 if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
289 Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
290 }
291 if (suppressionFile != null && !suppressionFile.isEmpty()) {
292 Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
293 }
294
295
296 Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !jarDisabled);
297 Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !archiveDisabled);
298 Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !nuspecDisabled);
299 Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !assemblyDisabled);
300
301 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !nexusDisabled);
302 if (nexusUrl != null && !nexusUrl.isEmpty()) {
303 Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
304 }
305 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
306 if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
307 Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
308 }
309 if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
310 Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
311 }
312 if (connectionString != null && !connectionString.isEmpty()) {
313 Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
314 }
315 if (databaseUser != null && !databaseUser.isEmpty()) {
316 Settings.setString(Settings.KEYS.DB_USER, databaseUser);
317 }
318 if (databasePassword != null && !databasePassword.isEmpty()) {
319 Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
320 }
321 if (additionalZipExtensions != null && !additionalZipExtensions.isEmpty()) {
322 Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions);
323 }
324 if (pathToMono != null && !pathToMono.isEmpty()) {
325 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
326 }
327 }
328 }