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 if (Settings.getBoolean(Settings.KEYS.AUTO_UPDATE)) {
103 openDatabase();
104 LOGGER.debug("Begin Engine Version Check");
105 final DatabaseProperties properties = cveDB.getDatabaseProperties();
106 final long lastChecked = Long.parseLong(properties.getProperty(ENGINE_VERSION_CHECKED_ON, "0"));
107 final long now = System.currentTimeMillis();
108 updateToVersion = properties.getProperty(CURRENT_ENGINE_RELEASE, "");
109 final String currentVersion = Settings.getString(Settings.KEYS.APPLICATION_VERSION, "0.0.0");
110 LOGGER.debug("Last checked: {}", lastChecked);
111 LOGGER.debug("Now: {}", now);
112 LOGGER.debug("Current version: {}", currentVersion);
113 final boolean updateNeeded = shouldUpdate(lastChecked, now, properties, currentVersion);
114 if (updateNeeded) {
115 LOGGER.warn("A new version of dependency-check is available. Consider updating to version {}.",
116 updateToVersion);
117 }
118 }
119 } catch (DatabaseException ex) {
120 LOGGER.debug("Database Exception opening databases to retrieve properties", ex);
121 throw new UpdateException("Error occured updating database properties.");
122 } catch (InvalidSettingException ex) {
123 LOGGER.debug("Unable to determine if autoupdate is enabled", ex);
124 } finally {
125 closeDatabase();
126 }
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 protected boolean shouldUpdate(final long lastChecked, final long now, final DatabaseProperties properties,
143 String currentVersion) throws UpdateException {
144
145 final int checkRange = 30;
146 if (!DateUtil.withinDateRange(lastChecked, now, checkRange)) {
147 LOGGER.debug("Checking web for new version.");
148 final String currentRelease = getCurrentReleaseVersion();
149 if (currentRelease != null) {
150 final DependencyVersion v = new DependencyVersion(currentRelease);
151 if (v.getVersionParts() != null && v.getVersionParts().size() >= 3) {
152 updateToVersion = v.toString();
153 if (!currentRelease.equals(updateToVersion)) {
154 properties.save(CURRENT_ENGINE_RELEASE, updateToVersion);
155 }
156 properties.save(ENGINE_VERSION_CHECKED_ON, Long.toString(now));
157 }
158 }
159 LOGGER.debug("Current Release: {}", updateToVersion);
160 }
161 if (updateToVersion == null) {
162 LOGGER.debug("Unable to obtain current release");
163 return false;
164 }
165 final DependencyVersion running = new DependencyVersion(currentVersion);
166 final DependencyVersion released = new DependencyVersion(updateToVersion);
167 if (running.compareTo(released) < 0) {
168 LOGGER.debug("Upgrade recommended");
169 return true;
170 }
171 LOGGER.debug("Upgrade not needed");
172 return false;
173 }
174
175
176
177
178
179
180 protected final void openDatabase() throws DatabaseException {
181 if (cveDB != null) {
182 return;
183 }
184 cveDB = new CveDB();
185 cveDB.open();
186 }
187
188
189
190
191 protected void closeDatabase() {
192 if (cveDB != null) {
193 try {
194 cveDB.close();
195 cveDB = null;
196 } catch (Throwable ignore) {
197 LOGGER.trace("Error closing the cveDB", ignore);
198 }
199 }
200 }
201
202
203
204
205
206
207
208 protected String getCurrentReleaseVersion() {
209 HttpURLConnection conn = null;
210 try {
211 final String str = Settings.getString(Settings.KEYS.ENGINE_VERSION_CHECK_URL, "http://jeremylong.github.io/DependencyCheck/current.txt");
212 final URL url = new URL(str);
213 conn = URLConnectionFactory.createHttpURLConnection(url);
214 conn.connect();
215 if (conn.getResponseCode() != 200) {
216 return null;
217 }
218 final String releaseVersion = IOUtils.toString(conn.getInputStream(), "UTF-8");
219 if (releaseVersion != null) {
220 return releaseVersion.trim();
221 }
222 } catch (MalformedURLException ex) {
223 LOGGER.debug("Unable to retrieve current release version of dependency-check - malformed url?");
224 } catch (URLConnectionFailureException ex) {
225 LOGGER.debug("Unable to retrieve current release version of dependency-check - connection failed");
226 } catch (IOException ex) {
227 LOGGER.debug("Unable to retrieve current release version of dependency-check - i/o exception");
228 } finally {
229 if (conn != null) {
230 conn.disconnect();
231 }
232 }
233 return null;
234 }
235 }