1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.analyzer;
19
20 import org.apache.commons.io.FileUtils;
21 import org.owasp.dependencycheck.Engine;
22 import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
23 import org.owasp.dependencycheck.data.central.CentralSearch;
24 import org.owasp.dependencycheck.data.nexus.MavenArtifact;
25 import org.owasp.dependencycheck.dependency.Confidence;
26 import org.owasp.dependencycheck.dependency.Dependency;
27 import org.owasp.dependencycheck.dependency.Evidence;
28 import org.owasp.dependencycheck.xml.pom.PomUtils;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import java.io.File;
33 import java.io.FileFilter;
34 import java.io.FileNotFoundException;
35 import java.io.IOException;
36 import java.net.URL;
37 import java.util.List;
38 import org.owasp.dependencycheck.utils.DownloadFailedException;
39 import org.owasp.dependencycheck.utils.Downloader;
40 import org.owasp.dependencycheck.utils.FileFilterBuilder;
41 import org.owasp.dependencycheck.utils.InvalidSettingException;
42 import org.owasp.dependencycheck.utils.Settings;
43
44
45
46
47
48
49
50 public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
51
52
53
54
55 private static final Logger LOGGER = LoggerFactory.getLogger(CentralAnalyzer.class);
56
57
58
59
60 private static final String ANALYZER_NAME = "Central Analyzer";
61
62
63
64
65 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
66
67
68
69
70 private static final String SUPPORTED_EXTENSIONS = "jar";
71
72
73
74
75 private boolean errorFlag = false;
76
77
78
79
80 private CentralSearch searcher;
81
82
83
84 private final boolean enabled = checkEnabled();
85
86
87
88
89
90
91 @Override
92 public boolean isEnabled() {
93 return enabled;
94 }
95
96
97
98
99
100
101 private boolean checkEnabled() {
102 boolean retval = false;
103
104 try {
105 if (Settings.getBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED)) {
106 if (!Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)
107 || NexusAnalyzer.DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL))) {
108 LOGGER.debug("Enabling the Central analyzer");
109 retval = true;
110 } else {
111 LOGGER.info("Nexus analyzer is enabled, disabling the Central Analyzer");
112 }
113 } else {
114 LOGGER.info("Central analyzer disabled");
115 }
116 } catch (InvalidSettingException ise) {
117 LOGGER.warn("Invalid setting. Disabling the Central analyzer");
118 }
119 return retval;
120 }
121
122
123
124
125
126
127 @Override
128 public void initializeFileTypeAnalyzer() throws Exception {
129 LOGGER.debug("Initializing Central analyzer");
130 LOGGER.debug("Central analyzer enabled: {}", isEnabled());
131 if (isEnabled()) {
132 final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_CENTRAL_URL);
133 LOGGER.debug("Central Analyzer URL: {}", searchUrl);
134 searcher = new CentralSearch(new URL(searchUrl));
135 }
136 }
137
138
139
140
141
142
143 @Override
144 public String getName() {
145 return ANALYZER_NAME;
146 }
147
148
149
150
151
152
153 @Override
154 protected String getAnalyzerEnabledSettingKey() {
155 return Settings.KEYS.ANALYZER_CENTRAL_ENABLED;
156 }
157
158
159
160
161
162
163 @Override
164 public AnalysisPhase getAnalysisPhase() {
165 return ANALYSIS_PHASE;
166 }
167
168
169
170
171 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(SUPPORTED_EXTENSIONS).build();
172
173 @Override
174 protected FileFilter getFileFilter() {
175 return FILTER;
176 }
177
178
179
180
181
182
183
184
185 @Override
186 public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
187 if (errorFlag || !isEnabled()) {
188 return;
189 }
190
191 try {
192 final List<MavenArtifact> mas = searcher.searchSha1(dependency.getSha1sum());
193 final Confidence confidence = mas.size() > 1 ? Confidence.HIGH : Confidence.HIGHEST;
194 for (MavenArtifact ma : mas) {
195 LOGGER.debug("Central analyzer found artifact ({}) for dependency ({})", ma, dependency.getFileName());
196 dependency.addAsEvidence("central", ma, confidence);
197 boolean pomAnalyzed = false;
198 for (Evidence e : dependency.getVendorEvidence()) {
199 if ("pom".equals(e.getSource())) {
200 pomAnalyzed = true;
201 break;
202 }
203 }
204 if (!pomAnalyzed && ma.getPomUrl() != null) {
205 File pomFile = null;
206 try {
207 final File baseDir = Settings.getTempDirectory();
208 pomFile = File.createTempFile("pom", ".xml", baseDir);
209 if (!pomFile.delete()) {
210 LOGGER.warn("Unable to fetch pom.xml for {} from Central; "
211 + "this could result in undetected CPE/CVEs.", dependency.getFileName());
212 LOGGER.debug("Unable to delete temp file");
213 }
214 LOGGER.debug("Downloading {}", ma.getPomUrl());
215 Downloader.fetchFile(new URL(ma.getPomUrl()), pomFile);
216 PomUtils.analyzePOM(dependency, pomFile);
217
218 } catch (DownloadFailedException ex) {
219 LOGGER.warn("Unable to download pom.xml for {} from Central; "
220 + "this could result in undetected CPE/CVEs.", dependency.getFileName());
221 } finally {
222 if (pomFile != null && !FileUtils.deleteQuietly(pomFile)) {
223 pomFile.deleteOnExit();
224 }
225 }
226 }
227
228 }
229 } catch (IllegalArgumentException iae) {
230 LOGGER.info("invalid sha1-hash on {}", dependency.getFileName());
231 } catch (FileNotFoundException fnfe) {
232 LOGGER.debug("Artifact not found in repository: '{}", dependency.getFileName());
233 } catch (IOException ioe) {
234 LOGGER.debug("Could not connect to Central search", ioe);
235 errorFlag = true;
236 }
237 }
238 }