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.dependency.Confidence;
24 import org.owasp.dependencycheck.dependency.Dependency;
25 import org.owasp.dependencycheck.dependency.EvidenceCollection;
26 import org.owasp.dependencycheck.utils.FileFilterBuilder;
27 import org.owasp.dependencycheck.utils.Settings;
28 import org.owasp.dependencycheck.utils.UrlStringUtils;
29
30 import java.io.File;
31 import java.io.FileFilter;
32 import java.io.IOException;
33 import java.nio.charset.Charset;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.regex.Matcher;
37 import java.util.regex.Pattern;
38
39
40
41
42
43
44
45
46 @Experimental
47 public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
48
49
50
51
52 private static final String CONFIGURE = "configure";
53
54
55
56
57 private static final String CONFIGURE_IN = "configure.in";
58
59
60
61
62 private static final String CONFIGURE_AC = "configure.ac";
63
64
65
66
67 private static final String ANALYZER_NAME = "Autoconf Analyzer";
68
69
70
71
72 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
73
74
75
76
77 private static final String[] EXTENSIONS = {"ac", "in"};
78
79
80
81
82 private static final Pattern PACKAGE_VAR = Pattern.compile(
83 "PACKAGE_(.+?)='(.*?)'", Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
84
85
86
87
88 private static final Pattern AC_INIT_PATTERN;
89
90 static {
91
92 final String param = "\\[{0,2}(.+?)\\]{0,2}";
93 final String sepParam = "\\s*,\\s*" + param;
94
95
96
97
98
99
100
101
102 AC_INIT_PATTERN = Pattern.compile(String.format(
103 "AC_INIT\\(%s%s(%s)?(%s)?(%s)?\\s*\\)", param, sepParam,
104 sepParam, sepParam, sepParam), Pattern.DOTALL
105 | Pattern.CASE_INSENSITIVE);
106 }
107
108
109
110
111 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames(CONFIGURE).addExtensions(
112 EXTENSIONS).build();
113
114
115
116
117
118
119 @Override
120 protected FileFilter getFileFilter() {
121 return FILTER;
122 }
123
124
125
126
127
128
129 @Override
130 public String getName() {
131 return ANALYZER_NAME;
132 }
133
134
135
136
137
138
139 @Override
140 public AnalysisPhase getAnalysisPhase() {
141 return ANALYSIS_PHASE;
142 }
143
144
145
146
147
148
149 @Override
150 protected String getAnalyzerEnabledSettingKey() {
151 return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED;
152 }
153
154 @Override
155 protected void analyzeFileType(Dependency dependency, Engine engine)
156 throws AnalysisException {
157 final File actualFile = dependency.getActualFile();
158 final String name = actualFile.getName();
159 if (name.startsWith(CONFIGURE)) {
160 final File parent = actualFile.getParentFile();
161 final String parentName = parent.getName();
162 dependency.setDisplayFileName(parentName + "/" + name);
163 final boolean isOutputScript = CONFIGURE.equals(name);
164 if (isOutputScript || CONFIGURE_AC.equals(name)
165 || CONFIGURE_IN.equals(name)) {
166 final String contents = getFileContents(actualFile);
167 if (!contents.isEmpty()) {
168 if (isOutputScript) {
169 extractConfigureScriptEvidence(dependency, name,
170 contents);
171 } else {
172 gatherEvidence(dependency, name, contents);
173 }
174 }
175 }
176 } else {
177
178 final List<Dependency> dependencies = new ArrayList<Dependency>(
179 engine.getDependencies());
180 dependencies.remove(dependency);
181 engine.setDependencies(dependencies);
182 }
183 }
184
185
186
187
188
189
190
191
192 private void extractConfigureScriptEvidence(Dependency dependency,
193 final String name, final String contents) {
194 final Matcher matcher = PACKAGE_VAR.matcher(contents);
195 while (matcher.find()) {
196 final String variable = matcher.group(1);
197 final String value = matcher.group(2);
198 if (!value.isEmpty()) {
199 if (variable.endsWith("NAME")) {
200 dependency.getProductEvidence().addEvidence(name, variable,
201 value, Confidence.HIGHEST);
202 } else if ("VERSION".equals(variable)) {
203 dependency.getVersionEvidence().addEvidence(name, variable,
204 value, Confidence.HIGHEST);
205 } else if ("BUGREPORT".equals(variable)) {
206 dependency.getVendorEvidence().addEvidence(name, variable,
207 value, Confidence.HIGH);
208 } else if ("URL".equals(variable)) {
209 dependency.getVendorEvidence().addEvidence(name, variable,
210 value, Confidence.HIGH);
211 }
212 }
213 }
214 }
215
216
217
218
219
220
221
222
223 private String getFileContents(final File actualFile)
224 throws AnalysisException {
225 try {
226 return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
227 } catch (IOException e) {
228 throw new AnalysisException(
229 "Problem occurred while reading dependency file.", e);
230 }
231 }
232
233
234
235
236
237
238
239
240 private void gatherEvidence(Dependency dependency, final String name,
241 String contents) {
242 final Matcher matcher = AC_INIT_PATTERN.matcher(contents);
243 if (matcher.find()) {
244 final EvidenceCollection productEvidence = dependency
245 .getProductEvidence();
246 productEvidence.addEvidence(name, "Package", matcher.group(1),
247 Confidence.HIGHEST);
248 dependency.getVersionEvidence().addEvidence(name,
249 "Package Version", matcher.group(2), Confidence.HIGHEST);
250 final EvidenceCollection vendorEvidence = dependency
251 .getVendorEvidence();
252 if (null != matcher.group(3)) {
253 vendorEvidence.addEvidence(name, "Bug report address",
254 matcher.group(4), Confidence.HIGH);
255 }
256 if (null != matcher.group(5)) {
257 productEvidence.addEvidence(name, "Tarname", matcher.group(6),
258 Confidence.HIGH);
259 }
260 if (null != matcher.group(7)) {
261 final String url = matcher.group(8);
262 if (UrlStringUtils.isUrl(url)) {
263 vendorEvidence.addEvidence(name, "URL", url,
264 Confidence.HIGH);
265 }
266 }
267 }
268 }
269
270
271
272
273
274
275 @Override
276 protected void initializeFileTypeAnalyzer() throws Exception {
277
278 }
279 }