From aecc95825be518a955f5ed86f30c6fdc646c0507 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Fri, 24 Apr 2015 16:08:08 +0000 Subject: [PATCH] Updates: Fail fast if HTTP proxy is not running (ticket #1530) Covers router, unsigned router, plugin, and news updates --- .../net/i2p/router/update/NewsFetcher.java | 8 +++++ .../router/update/PluginUpdateChecker.java | 14 ++++++++- .../i2p/router/update/PluginUpdateRunner.java | 17 ++++++++-- .../router/update/UnsignedUpdateChecker.java | 8 +++++ .../router/update/UnsignedUpdateRunner.java | 17 ++++++++-- .../net/i2p/router/update/UpdateRunner.java | 18 +++++++++-- .../i2p/router/web/ConfigClientsHandler.java | 31 +++++++++++++++++++ .../i2p/router/web/ConfigUpdateHandler.java | 11 +++++++ .../src/net/i2p/router/web/PluginStarter.java | 12 +++++++ 9 files changed, 127 insertions(+), 9 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java b/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java index fea9959f62..f34aa1bba4 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java @@ -36,6 +36,7 @@ import static net.i2p.update.UpdateMethod.*; import net.i2p.util.EepGet; import net.i2p.util.FileUtil; import net.i2p.util.Log; +import net.i2p.util.PortMapper; import net.i2p.util.ReusableGZIPInputStream; import net.i2p.util.SecureFileOutputStream; import net.i2p.util.SSLEepGet; @@ -82,6 +83,13 @@ class NewsFetcher extends UpdateRunner { boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY_NEWS, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY_NEWS); String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); int proxyPort = ConfigUpdateHandler.proxyPort(_context); + if (shouldProxy && proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT && + proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) && + _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) { + if (_log.shouldWarn()) + _log.warn("Cannot fetch news - HTTP client tunnel not running"); + return; + } for (URI uri : _urls) { _currentURI = uri; diff --git a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateChecker.java b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateChecker.java index fe8bf2d11a..f69fcfe245 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateChecker.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateChecker.java @@ -3,11 +3,13 @@ package net.i2p.router.update; import java.io.File; import java.net.URI; import java.util.List; + import net.i2p.crypto.TrustedUpdate; import net.i2p.router.RouterContext; import net.i2p.router.web.ConfigUpdateHandler; import net.i2p.update.*; import net.i2p.util.PartialEepGet; +import net.i2p.util.PortMapper; /** * Check for an updated version of a plugin. @@ -52,12 +54,22 @@ class PluginUpdateChecker extends UpdateRunner { protected void update() { // must be set for super _isPartial = true; - updateStatus("<b>" + _("Checking for update of plugin {0}", _appName) + "</b>"); // use the same settings as for updater // always proxy, or else FIXME //boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue(); String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); int proxyPort = ConfigUpdateHandler.proxyPort(_context); + if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT && + proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) && + _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) { + String msg = _("HTTP client proxy tunnel must be running"); + if (_log.shouldWarn()) + _log.warn(msg); + updateStatus("<b>" + msg + "</b>"); + _mgr.notifyCheckComplete(this, false, false); + return; + } + updateStatus("<b>" + _("Checking for update of plugin {0}", _appName) + "</b>"); _baos.reset(); try { _get = new PartialEepGet(_context, proxyHost, proxyPort, _baos, _currentURI.toString(), TrustedUpdate.HEADER_BYTES); diff --git a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java index 9b7143ed52..0a58ba9f66 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java @@ -26,6 +26,7 @@ import net.i2p.util.EepGet; import net.i2p.util.FileUtil; import net.i2p.util.Log; import net.i2p.util.OrderedProperties; +import net.i2p.util.PortMapper; import net.i2p.util.SecureDirectory; import net.i2p.util.SecureFile; import net.i2p.util.VersionComparator; @@ -98,11 +99,23 @@ class PluginUpdateRunner extends UpdateRunner { } } } else { - updateStatus("<b>" + _("Downloading plugin from {0}", _xpi2pURL) + "</b>"); // use the same settings as for updater - boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY); + //boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY); + // always proxy, or else FIXME + boolean shouldProxy = true; String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); int proxyPort = ConfigUpdateHandler.proxyPort(_context); + if (shouldProxy && proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT && + proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) && + _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) { + String msg = _("HTTP client proxy tunnel must be running"); + if (_log.shouldWarn()) + _log.warn(msg); + statusDone("<b>" + msg + "</b>"); + _mgr.notifyTaskFailed(this, msg, null); + return; + } + updateStatus("<b>" + _("Downloading plugin from {0}", _xpi2pURL) + "</b>"); try { if (shouldProxy) // 10 retries!! diff --git a/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateChecker.java b/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateChecker.java index 635d5d85ff..2024bacb1d 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateChecker.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateChecker.java @@ -8,6 +8,7 @@ import net.i2p.router.util.RFC822Date; import net.i2p.router.web.ConfigUpdateHandler; import net.i2p.update.*; import net.i2p.util.EepHead; +import net.i2p.util.PortMapper; /** * Does a simple EepHead to get the last-modified header. @@ -55,6 +56,13 @@ class UnsignedUpdateChecker extends UpdateRunner { //boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue(); String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); int proxyPort = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_PORT, ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT); + if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT && + proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) && + _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) { + if (_log.shouldWarn()) + _log.warn("Cannot check for unsigned update - HTTP client tunnel not running"); + return false; + } try { EepHead get = new EepHead(_context, proxyHost, proxyPort, 0, url); diff --git a/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java b/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java index 556d8b21a2..7a9519ff61 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java @@ -10,6 +10,7 @@ import net.i2p.router.web.ConfigUpdateHandler; import static net.i2p.update.UpdateType.*; import net.i2p.util.EepGet; import net.i2p.util.Log; +import net.i2p.util.PortMapper; /** @@ -30,13 +31,23 @@ class UnsignedUpdateRunner extends UpdateRunner { /** Get the file */ @Override protected void update() { - String zipURL = _currentURI.toString(); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Starting unsigned update URL: " + zipURL); // always proxy for now //boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue(); String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); int proxyPort = ConfigUpdateHandler.proxyPort(_context); + if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT && + proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) && + _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) { + String msg = _("HTTP client proxy tunnel must be running"); + if (_log.shouldWarn()) + _log.warn(msg); + updateStatus("<b>" + msg + "</b>"); + _mgr.notifyTaskFailed(this, msg, null); + return; + } + String zipURL = _currentURI.toString(); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Starting unsigned update URL: " + zipURL); try { // 40 retries!! _get = new EepGet(_context, proxyHost, proxyPort, 40, _updateFile, zipURL, false); diff --git a/apps/routerconsole/java/src/net/i2p/router/update/UpdateRunner.java b/apps/routerconsole/java/src/net/i2p/router/update/UpdateRunner.java index 7417749ff4..682b9b447b 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/UpdateRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/UpdateRunner.java @@ -16,6 +16,7 @@ import net.i2p.util.EepGet; import net.i2p.util.I2PAppThread; import net.i2p.util.Log; import net.i2p.util.PartialEepGet; +import net.i2p.util.PortMapper; import net.i2p.util.SSLEepGet; import net.i2p.util.VersionComparator; @@ -150,6 +151,16 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList if (shouldProxy) { proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); proxyPort = ConfigUpdateHandler.proxyPort(_context); + if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT && + proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) && + _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) { + String msg = _("HTTP client proxy tunnel must be running"); + if (_log.shouldWarn()) + _log.warn(msg); + updateStatus("<b>" + msg + "</b>"); + _mgr.notifyTaskFailed(this, msg, null); + return; + } } else { // TODO, wrong method, fail proxyHost = null; @@ -170,9 +181,10 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList if (_urls.isEmpty()) { // not likely, don't bother translating - updateStatus("<b>Update source list is empty, cannot download update</b>"); - _log.error("Update source list is empty - cannot download update"); - _mgr.notifyTaskFailed(this, "", null); + String msg = "Update source list is empty, cannot download update"; + updateStatus("<b>" + msg + "</b>"); + _log.error(msg); + _mgr.notifyTaskFailed(this, msg, null); return; } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java index dc0983ea29..605626211e 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java @@ -26,6 +26,7 @@ import net.i2p.router.startup.LoadClientAppsJob; import net.i2p.router.update.ConsoleUpdateManager; import static net.i2p.update.UpdateType.*; import net.i2p.util.SecureFileOutputStream; +import net.i2p.util.PortMapper; import org.eclipse.jetty.server.handler.ContextHandlerCollection; @@ -490,6 +491,8 @@ public class ConfigClientsHandler extends FormHandler { addFormError(_("Plugin or update download already in progress.")); return; } + if (!verifyProxy()) + return; addFormNotice(_("Updating all plugins")); PluginStarter.updateAll(_context); // So that update() will post a status to the summary bar before we reload @@ -500,6 +503,7 @@ public class ConfigClientsHandler extends FormHandler { /** * @param app null for a new install + * @param url http: or file: */ private void installPlugin(String app, String url) { ConsoleUpdateManager mgr = UpdateHandler.updateManager(_context); @@ -518,6 +522,10 @@ public class ConfigClientsHandler extends FormHandler { addFormError(_("Bad URL {0}", url)); return; } + if (!url.startsWith("file:")) { + if (!verifyProxy()) + return; + } if (mgr.installPlugin(app, uri)) { if (url.startsWith("file:")) addFormNotice(_("Installing plugin from {0}", uri.getPath())); @@ -538,6 +546,8 @@ public class ConfigClientsHandler extends FormHandler { addFormError("Update manager not registered, cannot check"); return; } + if (!verifyProxy()) + return; mgr.check(PLUGIN, app); addFormNotice(_("Checking plugin {0} for updates", app)); // So that update() will post a status to the summary bar before we reload @@ -546,6 +556,27 @@ public class ConfigClientsHandler extends FormHandler { } catch (InterruptedException ie) {} } + /** + * Plugin checks, updates, and installs are always proxied. + * See if the proxy tunnel is available, unless we're configured + * to use something else (probably not). + * Outputs form error if returning false. + * + * @return true if available + * @since 0.9.20 + */ + private boolean verifyProxy() { + String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); + int proxyPort = ConfigUpdateHandler.proxyPort(_context); + boolean rv = ! + (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT && + proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) && + _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0); + if (!rv) + addFormError(_("HTTP client proxy tunnel must be running")); + return rv; + } + private void startPlugin(String app) { try { PluginStarter.startPlugin(_context, app); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java index 3cd9adbf8f..134b727ef7 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java @@ -152,6 +152,17 @@ public class ConfigUpdateHandler extends FormHandler { addFormError(_("Update or check already in progress")); return; } + + boolean shouldProxy = _context.getProperty(PROP_SHOULD_PROXY_NEWS, DEFAULT_SHOULD_PROXY_NEWS); + String proxyHost = _context.getProperty(PROP_PROXY_HOST, DEFAULT_PROXY_HOST); + int proxyPort = proxyPort(_context); + if (shouldProxy && proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT && + proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) && + _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) { + addFormError(_("HTTP client proxy tunnel must be running")); + return; + } + boolean a1 = mgr.checkAvailable(NEWS, 30*1000) != null; boolean a2 = false; if ((!a1) && _updateUnsigned && _zipURL != null && _zipURL.length() > 0) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java index edcaf2f980..ec10c0fce8 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java @@ -32,6 +32,7 @@ import net.i2p.util.ConcurrentHashSet; import net.i2p.util.FileUtil; import net.i2p.util.I2PAppThread; import net.i2p.util.Log; +import net.i2p.util.PortMapper; import net.i2p.util.SimpleTimer2; import net.i2p.util.Translate; import net.i2p.util.VersionComparator; @@ -146,6 +147,17 @@ public class PluginStarter implements Runnable { } while (mgr.isUpdateInProgress(TYPE_DUMMY)); } + String proxyHost = ctx.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); + int proxyPort = ConfigUpdateHandler.proxyPort(ctx); + if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT && + proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) && + ctx.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) { + mgr.notifyComplete(null, Messages.getString("Plugin update check failed", ctx) + + " - " + + Messages.getString("HTTP client proxy tunnel must be running", ctx)); + return; + } + Log log = ctx.logManager().getLog(PluginStarter.class); int updated = 0; for (Map.Entry<String, String> entry : toUpdate.entrySet()) { -- GitLab