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