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.isUpdateOnly()) {
99 populateSettings(cli);
100 runUpdateOnly();
101 } else if (cli.isRunScan()) {
102 populateSettings(cli);
103 try {
104 runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles(), cli.getExcludeList());
105 } catch (InvalidScanPathException ex) {
106 LOGGER.log(Level.SEVERE, "An invalid scan path was detected; unable to scan '//*' paths");
107 }
108 } else {
109 cli.printHelp();
110 }
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124 private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
125 String[] excludes) throws InvalidScanPathException {
126 Engine engine = null;
127 try {
128 engine = new Engine();
129 List<String> antStylePaths = new ArrayList<String>();
130 if (excludes == null || excludes.length == 0) {
131 for (String file : files) {
132 if (file.contains("*") || file.contains("?")) {
133 antStylePaths.add(file);
134 } else {
135 engine.scan(file);
136 }
137 }
138 } else {
139 antStylePaths = Arrays.asList(files);
140 }
141
142 final Set<File> paths = new HashSet<File>();
143 for (String file : antStylePaths) {
144 final DirectoryScanner scanner = new DirectoryScanner();
145 String include = file.replace('\\', '/');
146 File baseDir;
147
148 if (include.startsWith("//")) {
149 throw new InvalidScanPathException("Unable to scan paths specified by //");
150 } else if (include.startsWith("./")) {
151 baseDir = new File(".");
152 include = include.substring(2);
153 } else if (include.startsWith("/")) {
154 baseDir = new File("/");
155 include = include.substring(1);
156 } else if (include.contains("/")) {
157 final int pos = include.indexOf('/');
158 final String tmp = include.substring(0, pos);
159 if (tmp.contains("*") || tmp.contains("?")) {
160 baseDir = new File(".");
161 } else {
162 baseDir = new File(tmp);
163 include = include.substring(pos + 1);
164 }
165 } else {
166 baseDir = new File(".");
167 }
168 scanner.setBasedir(baseDir);
169 scanner.setIncludes(include);
170 if (excludes != null && excludes.length > 0) {
171 scanner.addExcludes(excludes);
172 }
173 scanner.scan();
174 if (scanner.getIncludedFilesCount() > 0) {
175 for (String s : scanner.getIncludedFiles()) {
176 final File f = new File(baseDir, s);
177 paths.add(f);
178 }
179 }
180 }
181 engine.scan(paths);
182
183 engine.analyzeDependencies();
184 final List<Dependency> dependencies = engine.getDependencies();
185 DatabaseProperties prop = null;
186 CveDB cve = null;
187 try {
188 cve = new CveDB();
189 cve.open();
190 prop = cve.getDatabaseProperties();
191 } catch (DatabaseException ex) {
192 LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
193 } finally {
194 if (cve != null) {
195 cve.close();
196 }
197 }
198 final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
199 try {
200 report.generateReports(reportDirectory, outputFormat);
201 } catch (IOException ex) {
202 LOGGER.log(Level.SEVERE, "There was an IO error while attempting to generate the report.");
203 LOGGER.log(Level.FINE, null, ex);
204 } catch (Throwable ex) {
205 LOGGER.log(Level.SEVERE, "There was an error while attempting to generate the report.");
206 LOGGER.log(Level.FINE, null, ex);
207 }
208 } catch (DatabaseException ex) {
209 LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
210 LOGGER.log(Level.FINE, "", ex);
211 } finally {
212 if (engine != null) {
213 engine.cleanup();
214 }
215 }
216 }
217
218
219
220
221 private void runUpdateOnly() {
222 Engine engine = null;
223 try {
224 engine = new Engine();
225 engine.doUpdates();
226 } catch (DatabaseException ex) {
227 LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
228 LOGGER.log(Level.FINE, "", ex);
229 } finally {
230 if (engine != null) {
231 engine.cleanup();
232 }
233 }
234 }
235
236
237
238
239
240
241
242 private void populateSettings(CliParser cli) {
243
244 final boolean autoUpdate = cli.isAutoUpdate();
245 final String connectionTimeout = cli.getConnectionTimeout();
246 final String proxyServer = cli.getProxyServer();
247 final String proxyPort = cli.getProxyPort();
248 final String proxyUser = cli.getProxyUsername();
249 final String proxyPass = cli.getProxyPassword();
250 final String dataDirectory = cli.getDataDirectory();
251 final File propertiesFile = cli.getPropertiesFile();
252 final String suppressionFile = cli.getSuppressionFile();
253 final boolean jarDisabled = cli.isJarDisabled();
254 final boolean archiveDisabled = cli.isArchiveDisabled();
255 final boolean pyDistDisabled = cli.isPythonDistributionDisabled();
256 final boolean pyPkgDisabled = cli.isPythonPackageDisabled();
257 final boolean assemblyDisabled = cli.isAssemblyDisabled();
258 final boolean nuspecDisabled = cli.isNuspecDisabled();
259 final boolean centralDisabled = cli.isCentralDisabled();
260 final boolean nexusDisabled = cli.isNexusDisabled();
261 final String nexusUrl = cli.getNexusUrl();
262 final String databaseDriverName = cli.getDatabaseDriverName();
263 final String databaseDriverPath = cli.getDatabaseDriverPath();
264 final String connectionString = cli.getConnectionString();
265 final String databaseUser = cli.getDatabaseUser();
266 final String databasePassword = cli.getDatabasePassword();
267 final String additionalZipExtensions = cli.getAdditionalZipExtensions();
268 final String pathToMono = cli.getPathToMono();
269
270 if (propertiesFile != null) {
271 try {
272 Settings.mergeProperties(propertiesFile);
273 } catch (FileNotFoundException ex) {
274 final String msg = String.format("Unable to load properties file '%s'", propertiesFile.getPath());
275 LOGGER.log(Level.SEVERE, msg);
276 LOGGER.log(Level.FINE, null, ex);
277 } catch (IOException ex) {
278 final String msg = String.format("Unable to find properties file '%s'", propertiesFile.getPath());
279 LOGGER.log(Level.SEVERE, msg);
280 LOGGER.log(Level.FINE, null, ex);
281 }
282 }
283
284
285
286 final boolean nexusUsesProxy = cli.isNexusUsesProxy();
287 if (dataDirectory != null) {
288 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
289 } else if (System.getProperty("basedir") != null) {
290 final File dataDir = new File(System.getProperty("basedir"), "data");
291 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
292 } else {
293 final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath());
294 final File base = jarPath.getParentFile();
295 final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
296 final File dataDir = new File(base, sub);
297 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
298 }
299 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
300 if (proxyServer != null && !proxyServer.isEmpty()) {
301 Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer);
302 }
303 if (proxyPort != null && !proxyPort.isEmpty()) {
304 Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
305 }
306 if (proxyUser != null && !proxyUser.isEmpty()) {
307 Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUser);
308 }
309 if (proxyPass != null && !proxyPass.isEmpty()) {
310 Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPass);
311 }
312 if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
313 Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
314 }
315 if (suppressionFile != null && !suppressionFile.isEmpty()) {
316 Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
317 }
318
319
320 Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !jarDisabled);
321 Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !archiveDisabled);
322 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !pyDistDisabled);
323 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, !pyPkgDisabled);
324 Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !nuspecDisabled);
325 Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !assemblyDisabled);
326
327 Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !centralDisabled);
328 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !nexusDisabled);
329 if (nexusUrl != null && !nexusUrl.isEmpty()) {
330 Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
331 }
332 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
333 if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
334 Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
335 }
336 if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
337 Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
338 }
339 if (connectionString != null && !connectionString.isEmpty()) {
340 Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
341 }
342 if (databaseUser != null && !databaseUser.isEmpty()) {
343 Settings.setString(Settings.KEYS.DB_USER, databaseUser);
344 }
345 if (databasePassword != null && !databasePassword.isEmpty()) {
346 Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
347 }
348 if (additionalZipExtensions != null && !additionalZipExtensions.isEmpty()) {
349 Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions);
350 }
351 if (pathToMono != null && !pathToMono.isEmpty()) {
352 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
353 }
354 }
355 }