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.utils.FileFilterBuilder;
26 import org.owasp.dependencycheck.utils.Settings;
27
28 import java.io.File;
29 import java.io.FileFilter;
30 import java.io.IOException;
31 import java.nio.charset.Charset;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
34 import org.owasp.dependencycheck.exception.InitializationException;
35
36
37
38
39
40
41 public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
42
43
44
45
46 private static final int HEXADECIMAL = 16;
47
48
49
50 private static final String OPENSSLV_H = "opensslv.h";
51
52
53
54
55 private static final FileFilter OPENSSLV_FILTER = FileFilterBuilder.newInstance().addFilenames(OPENSSLV_H).build();
56
57
58
59 private static final Pattern VERSION_PATTERN = Pattern.compile(
60 "define\\s+OPENSSL_VERSION_NUMBER\\s+0x([0-9a-zA-Z]{8})L", Pattern.DOTALL
61 | Pattern.CASE_INSENSITIVE);
62
63
64
65 private static final int MAJOR_OFFSET = 28;
66
67
68
69 private static final long MINOR_MASK = 0x0ff00000L;
70
71
72
73 private static final int MINOR_OFFSET = 20;
74
75
76
77 private static final long FIX_MASK = 0x000ff000L;
78
79
80
81 private static final int FIX_OFFSET = 12;
82
83
84
85 private static final long PATCH_MASK = 0x00000ff0L;
86
87
88
89 private static final int PATCH_OFFSET = 4;
90
91
92
93 private static final int NUM_LETTERS = 26;
94
95
96
97 private static final int STATUS_MASK = 0x0000000f;
98
99
100
101
102
103
104
105 static String getOpenSSLVersion(long openSSLVersionConstant) {
106 final long major = openSSLVersionConstant >>> MAJOR_OFFSET;
107 final long minor = (openSSLVersionConstant & MINOR_MASK) >>> MINOR_OFFSET;
108 final long fix = (openSSLVersionConstant & FIX_MASK) >>> FIX_OFFSET;
109 final long patchLevel = (openSSLVersionConstant & PATCH_MASK) >>> PATCH_OFFSET;
110 final String patch = 0 == patchLevel || patchLevel > NUM_LETTERS ? "" : String.valueOf((char) (patchLevel + 'a' - 1));
111 final int statusCode = (int) (openSSLVersionConstant & STATUS_MASK);
112 final String status = 0xf == statusCode ? "" : (0 == statusCode ? "-dev" : "-beta" + statusCode);
113 return String.format("%d.%d.%d%s%s", major, minor, fix, patch, status);
114 }
115
116
117
118
119
120
121 @Override
122 public String getName() {
123 return "OpenSSL Source Analyzer";
124 }
125
126
127
128
129
130
131 @Override
132 public AnalysisPhase getAnalysisPhase() {
133 return AnalysisPhase.INFORMATION_COLLECTION;
134 }
135
136
137
138
139
140
141 @Override
142 protected FileFilter getFileFilter() {
143 return OPENSSLV_FILTER;
144 }
145
146
147
148
149
150
151 @Override
152 protected void initializeFileTypeAnalyzer() throws InitializationException {
153
154 }
155
156
157
158
159
160
161
162
163
164 @Override
165 protected void analyzeDependency(Dependency dependency, Engine engine)
166 throws AnalysisException {
167 final File file = dependency.getActualFile();
168 final String parentName = file.getParentFile().getName();
169 boolean found = false;
170 final String contents = getFileContents(file);
171 if (!contents.isEmpty()) {
172 final Matcher matcher = VERSION_PATTERN.matcher(contents);
173 if (matcher.find()) {
174 dependency.getVersionEvidence().addEvidence(OPENSSLV_H, "Version Constant",
175 getOpenSSLVersion(Long.parseLong(matcher.group(1), HEXADECIMAL)), Confidence.HIGH);
176 found = true;
177 }
178 }
179 if (found) {
180 dependency.setDisplayFileName(parentName + File.separatorChar + OPENSSLV_H);
181 dependency.getVendorEvidence().addEvidence(OPENSSLV_H, "Vendor", "OpenSSL", Confidence.HIGHEST);
182 dependency.getProductEvidence().addEvidence(OPENSSLV_H, "Product", "OpenSSL", Confidence.HIGHEST);
183 } else {
184 engine.getDependencies().remove(dependency);
185 }
186 }
187
188
189
190
191
192
193
194
195 private String getFileContents(final File actualFile)
196 throws AnalysisException {
197 try {
198 return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
199 } catch (IOException e) {
200 throw new AnalysisException(
201 "Problem occurred while reading dependency file.", e);
202 }
203 }
204
205
206
207
208
209
210 @Override
211 protected String getAnalyzerEnabledSettingKey() {
212 return Settings.KEYS.ANALYZER_OPENSSL_ENABLED;
213 }
214 }