1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.data.update;
19
20 import java.io.IOException;
21 import java.net.HttpURLConnection;
22 import java.net.MalformedURLException;
23 import java.net.URL;
24 import org.apache.commons.io.IOUtils;
25 import org.owasp.dependencycheck.data.nvdcve.CveDB;
26 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
27 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
28 import org.owasp.dependencycheck.data.update.exception.UpdateException;
29 import org.owasp.dependencycheck.utils.DateUtil;
30 import org.owasp.dependencycheck.utils.DependencyVersion;
31 import org.owasp.dependencycheck.utils.InvalidSettingException;
32 import org.owasp.dependencycheck.utils.Settings;
33 import org.owasp.dependencycheck.utils.URLConnectionFactory;
34 import org.owasp.dependencycheck.utils.URLConnectionFailureException;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38
39
40
41
42
43
44
45
46 public class EngineVersionCheck implements CachedWebDataSource {
47
48
49
50
51 private static final Logger LOGGER = LoggerFactory.getLogger(EngineVersionCheck.class);
52
53
54
55 public static final String ENGINE_VERSION_CHECKED_ON = "VersionCheckOn";
56
57
58
59 public static final String CURRENT_ENGINE_RELEASE = "CurrentEngineRelease";
60
61
62
63 private CveDB cveDB = null;
64
65
66
67
68
69 private String updateToVersion;
70
71
72
73
74
75
76
77 protected String getUpdateToVersion() {
78 return updateToVersion;
79 }
80
81
82
83
84
85
86
87 protected void setUpdateToVersion(String version) {
88 updateToVersion = version;
89 }
90
91
92
93
94
95
96
97
98
99 @Override
100 public void update() throws UpdateException {
101 try {
102 final boolean autoupdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE, true);
103 final boolean enabled = Settings.getBoolean(Settings.KEYS.UPDATE_VERSION_CHECK_ENABLED, true);
104 final String original = Settings.getString(Settings.KEYS.CVE_ORIGINAL_MODIFIED_20_URL);
105 final String current = Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL);
106
107
108
109
110
111 if (enabled && autoupdate && original != null && original.equals(current)) {
112 openDatabase();
113 LOGGER.debug("Begin Engine Version Check");
114 final DatabaseProperties properties = cveDB.getDatabaseProperties();
115 final long lastChecked = Long.parseLong(properties.getProperty(ENGINE_VERSION_CHECKED_ON, "0"));
116 final long now = System.currentTimeMillis();
117 updateToVersion = properties.getProperty(CURRENT_ENGINE_RELEASE, "");
118 final String currentVersion = Settings.getString(Settings.KEYS.APPLICATION_VERSION, "0.0.0");
119 LOGGER.debug("Last checked: {}", lastChecked);
120 LOGGER.debug("Now: {}", now);
121 LOGGER.debug("Current version: {}", currentVersion);
122 final boolean updateNeeded = shouldUpdate(lastChecked, now, properties, currentVersion);
123 if (updateNeeded) {
124 LOGGER.warn("A new version of dependency-check is available. Consider updating to version {}.",
125 updateToVersion);
126 }
127 }
128 } catch (DatabaseException ex) {
129 LOGGER.debug("Database Exception opening databases to retrieve properties", ex);
130 throw new UpdateException("Error occurred updating database properties.");
131 } catch (InvalidSettingException ex) {
132 LOGGER.debug("Unable to determine if autoupdate is enabled", ex);
133 } finally {
134 closeDatabase();
135 }
136 }
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 protected boolean shouldUpdate(final long lastChecked, final long now, final DatabaseProperties properties,
152 String currentVersion) throws UpdateException {
153
154 final int checkRange = 30;
155 if (!DateUtil.withinDateRange(lastChecked, now, checkRange)) {
156 LOGGER.debug("Checking web for new version.");
157 final String currentRelease = getCurrentReleaseVersion();
158 if (currentRelease != null) {
159 final DependencyVersion v = new DependencyVersion(currentRelease);
160 if (v.getVersionParts() != null && v.getVersionParts().size() >= 3) {
161 updateToVersion = v.toString();
162 if (!currentRelease.equals(updateToVersion)) {
163 properties.save(CURRENT_ENGINE_RELEASE, updateToVersion);
164 }
165 properties.save(ENGINE_VERSION_CHECKED_ON, Long.toString(now));
166 }
167 }
168 LOGGER.debug("Current Release: {}", updateToVersion);
169 }
170 if (updateToVersion == null) {
171 LOGGER.debug("Unable to obtain current release");
172 return false;
173 }
174 final DependencyVersion running = new DependencyVersion(currentVersion);
175 final DependencyVersion released = new DependencyVersion(updateToVersion);
176 if (running.compareTo(released) < 0) {
177 LOGGER.debug("Upgrade recommended");
178 return true;
179 }
180 LOGGER.debug("Upgrade not needed");
181 return false;
182 }
183
184
185
186
187
188
189 protected final void openDatabase() throws DatabaseException {
190 if (cveDB != null) {
191 return;
192 }
193 cveDB = new CveDB();
194 cveDB.open();
195 }
196
197
198
199
200 protected void closeDatabase() {
201 if (cveDB != null) {
202 try {
203 cveDB.close();
204 cveDB = null;
205 } catch (Throwable ignore) {
206 LOGGER.trace("Error closing the cveDB", ignore);
207 }
208 }
209 }
210
211
212
213
214
215
216
217 protected String getCurrentReleaseVersion() {
218 HttpURLConnection conn = null;
219 try {
220 final String str = Settings.getString(Settings.KEYS.ENGINE_VERSION_CHECK_URL, "http://jeremylong.github.io/DependencyCheck/current.txt");
221 final URL url = new URL(str);
222 conn = URLConnectionFactory.createHttpURLConnection(url);
223 conn.connect();
224 if (conn.getResponseCode() != 200) {
225 return null;
226 }
227 final String releaseVersion = IOUtils.toString(conn.getInputStream(), "UTF-8");
228 if (releaseVersion != null) {
229 return releaseVersion.trim();
230 }
231 } catch (MalformedURLException ex) {
232 LOGGER.debug("Unable to retrieve current release version of dependency-check - malformed url?");
233 } catch (URLConnectionFailureException ex) {
234 LOGGER.debug("Unable to retrieve current release version of dependency-check - connection failed");
235 } catch (IOException ex) {
236 LOGGER.debug("Unable to retrieve current release version of dependency-check - i/o exception");
237 } finally {
238 if (conn != null) {
239 conn.disconnect();
240 }
241 }
242 return null;
243 }
244 }