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.Settings;
32 import org.owasp.dependencycheck.utils.URLConnectionFactory;
33 import org.owasp.dependencycheck.utils.URLConnectionFailureException;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37
38
39
40
41 public class EngineVersionCheck implements CachedWebDataSource {
42
43
44
45
46 private static final Logger LOGGER = LoggerFactory.getLogger(EngineVersionCheck.class);
47
48
49
50 public static final String ENGINE_VERSION_CHECKED_ON = "VersionCheckOn";
51
52
53
54 public static final String CURRENT_ENGINE_RELEASE = "CurrentEngineRelease";
55
56
57
58 private CveDB cveDB = null;
59
60
61
62
63 private String updateToVersion;
64
65
66
67
68
69
70 protected String getUpdateToVersion() {
71 return updateToVersion;
72 }
73
74
75
76
77
78
79 protected void setUpdateToVersion(String version) {
80 updateToVersion = version;
81 }
82
83 @Override
84 public void update() throws UpdateException {
85 try {
86 openDatabase();
87 LOGGER.debug("Begin Engine Version Check");
88 final DatabaseProperties properties = cveDB.getDatabaseProperties();
89 final long lastChecked = Long.parseLong(properties.getProperty(ENGINE_VERSION_CHECKED_ON, "0"));
90 final long now = System.currentTimeMillis();
91 updateToVersion = properties.getProperty(CURRENT_ENGINE_RELEASE, "");
92 final String currentVersion = Settings.getString(Settings.KEYS.APPLICATION_VERSION, "0.0.0");
93 LOGGER.debug("Last checked: {}", lastChecked);
94 LOGGER.debug("Now: {}", now);
95 LOGGER.debug("Current version: {}", currentVersion);
96 final boolean updateNeeded = shouldUpdate(lastChecked, now, properties, currentVersion);
97 if (updateNeeded) {
98 LOGGER.warn("A new version of dependency-check is available. Consider updating to version {}.",
99 updateToVersion);
100 }
101 } catch (DatabaseException ex) {
102 LOGGER.debug("Database Exception opening databases to retrieve properties", ex);
103 throw new UpdateException("Error occured updating database properties.");
104 } finally {
105 closeDatabase();
106 }
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120 protected boolean shouldUpdate(final long lastChecked, final long now, final DatabaseProperties properties,
121 String currentVersion) throws UpdateException {
122
123 int checkRange = 30;
124 if (updateToVersion.isEmpty()) {
125 checkRange = 7;
126 }
127 if (!DateUtil.withinDateRange(lastChecked, now, checkRange)) {
128 LOGGER.debug("Checking web for new version.");
129 final String currentRelease = getCurrentReleaseVersion();
130 if (currentRelease != null) {
131 final DependencyVersion v = new DependencyVersion(currentRelease);
132 if (v.getVersionParts() != null && v.getVersionParts().size() >= 3) {
133 updateToVersion = v.toString();
134 if (!currentRelease.equals(updateToVersion)) {
135 properties.save(CURRENT_ENGINE_RELEASE, updateToVersion);
136 } else {
137 properties.save(CURRENT_ENGINE_RELEASE, "");
138 }
139 properties.save(ENGINE_VERSION_CHECKED_ON, Long.toString(now));
140 }
141 }
142 LOGGER.debug("Current Release: {}", updateToVersion);
143 }
144 final DependencyVersion running = new DependencyVersion(currentVersion);
145 final DependencyVersion released = new DependencyVersion(updateToVersion);
146 if (running.compareTo(released) < 0) {
147 LOGGER.debug("Upgrade recommended");
148 return true;
149 }
150 LOGGER.debug("Upgrade not needed");
151 return false;
152 }
153
154
155
156
157
158
159 protected final void openDatabase() throws DatabaseException {
160 if (cveDB != null) {
161 return;
162 }
163 cveDB = new CveDB();
164 cveDB.open();
165 }
166
167
168
169
170 protected void closeDatabase() {
171 if (cveDB != null) {
172 try {
173 cveDB.close();
174 cveDB = null;
175 } catch (Throwable ignore) {
176 LOGGER.trace("Error closing the cveDB", ignore);
177 }
178 }
179 }
180
181
182
183
184
185
186 protected String getCurrentReleaseVersion() {
187 HttpURLConnection conn = null;
188 try {
189 final String str = Settings.getString(Settings.KEYS.ENGINE_VERSION_CHECK_URL, "http://jeremylong.github.io/DependencyCheck/current.txt");
190 final URL url = new URL(str);
191 conn = URLConnectionFactory.createHttpURLConnection(url);
192 conn.connect();
193 if (conn.getResponseCode() != 200) {
194 return null;
195 }
196 final String releaseVersion = IOUtils.toString(conn.getInputStream(), "UTF-8");
197 if (releaseVersion != null) {
198 return releaseVersion.trim();
199 }
200 } catch (MalformedURLException ex) {
201 LOGGER.debug("unable to retrieve current release version of dependency-check", ex);
202 } catch (URLConnectionFailureException ex) {
203 LOGGER.debug("unable to retrieve current release version of dependency-check", ex);
204 } catch (IOException ex) {
205 LOGGER.debug("unable to retrieve current release version of dependency-check", ex);
206 } finally {
207 if (conn != null) {
208 conn.disconnect();
209 }
210 }
211 return null;
212 }
213 }