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