From 55199e666a4892c3d4d8b4a5cb986483a40a540c Mon Sep 17 00:00:00 2001 From: zzz Date: Fri, 2 Feb 2018 13:50:14 +0000 Subject: [PATCH] SecurityManager: Convert Timer to SimpleTimer2 Synch Sweeper cleanup, make more efficient Delay first Sweeper run until min expiration Re-enable changing password Synch fixes Clear tokens on shutdown --- .../i2p/i2pcontrol/security/AuthToken.java | 2 +- .../i2pcontrol/security/SecurityManager.java | 57 ++++++++++--------- .../i2pcontrol/servlets/JSONRPC2Servlet.java | 2 +- .../jsonrpc2handlers/I2PControlHandler.java | 21 ++++--- 4 files changed, 45 insertions(+), 37 deletions(-) diff --git a/src/java/net/i2p/i2pcontrol/security/AuthToken.java b/src/java/net/i2p/i2pcontrol/security/AuthToken.java index ae1bc1a..083c940 100644 --- a/src/java/net/i2p/i2pcontrol/security/AuthToken.java +++ b/src/java/net/i2p/i2pcontrol/security/AuthToken.java @@ -6,7 +6,7 @@ import java.util.Date; public class AuthToken { - private static final int VALIDITY_TIME = 1; // Measured in days + static final int VALIDITY_TIME = 1; // Measured in days private final SecurityManager _secMan; private final String id; private final Date expiry; diff --git a/src/java/net/i2p/i2pcontrol/security/SecurityManager.java b/src/java/net/i2p/i2pcontrol/security/SecurityManager.java index a26b683..0802187 100644 --- a/src/java/net/i2p/i2pcontrol/security/SecurityManager.java +++ b/src/java/net/i2p/i2pcontrol/security/SecurityManager.java @@ -20,9 +20,11 @@ import net.i2p.I2PAppContext; import net.i2p.crypto.SHA256Generator; import net.i2p.data.Base64; import net.i2p.data.DataHelper; +import net.i2p.util.Log; +import net.i2p.util.SimpleTimer2; + import net.i2p.i2pcontrol.security.jbcrypt.BCrypt; import net.i2p.i2pcontrol.servlets.configuration.ConfigurationManager; -import net.i2p.util.Log; import javax.net.SocketFactory; import javax.net.ssl.SSLSocket; @@ -30,7 +32,8 @@ import javax.net.ssl.SSLSocketFactory; import java.security.KeyStore; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; -import java.util.*; +import java.util.HashMap; +import java.util.Iterator; /** * Manage the password storing for I2PControl. @@ -38,7 +41,7 @@ import java.util.*; public class SecurityManager { private final static String DEFAULT_AUTH_PASSWORD = "itoopie"; private final HashMap authTokens; - private final Timer timer; + private final SimpleTimer2.TimedEvent timer; private final KeyStore _ks; private final Log _log; private final ConfigurationManager _conf; @@ -50,15 +53,16 @@ public class SecurityManager { _log = ctx.logManager().getLog(SecurityManager.class); authTokens = new HashMap(); - timer = new Timer("SecurityManager Timer Sweeper "); - // Start running periodic task after 20 minutes, run periodically every 10th minute. - timer.scheduleAtFixedRate(new Sweeper(), 1000 * 60 * 20, 1000 * 60 * 10); + timer = new Sweeper(); _ks = ksp.getDefaultKeyStore(); } public void stopTimedEvents() { timer.cancel(); + synchronized (authTokens) { + authTokens.clear(); + } } /** @@ -188,17 +192,16 @@ public class SecurityManager { * @throws ExpiredAuthTokenException */ public void verifyToken(String tokenID) throws InvalidAuthTokenException, ExpiredAuthTokenException { - AuthToken token = authTokens.get(tokenID); - if (token == null) { - throw new InvalidAuthTokenException("AuthToken with ID: " + tokenID + " couldn't be found."); - } else if (!token.isValid()) { - synchronized (authTokens) { - authTokens.remove(token.getId()); + synchronized (authTokens) { + AuthToken token = authTokens.get(tokenID); + if (token == null) + throw new InvalidAuthTokenException("AuthToken with ID: " + tokenID + " couldn't be found."); + if (!token.isValid()) { + authTokens.remove(tokenID); + throw new ExpiredAuthTokenException("AuthToken with ID: " + tokenID + " expired " + token.getExpiryTime(), token.getExpiryTime()); } - throw new ExpiredAuthTokenException("AuthToken with ID: " + tokenID + " expired " + token.getExpiryTime(), token.getExpiryTime()); - } else { - return; // Everything is fine. :) } + // Everything is fine. :) } /** @@ -206,23 +209,23 @@ public class SecurityManager { * @author hottuna * */ - private class Sweeper extends TimerTask { - @Override - public void run() { + private class Sweeper extends SimpleTimer2.TimedEvent { + // Start running periodic task after 1 day, run periodically every 30 minutes. + public Sweeper() { + super(_context.simpleTimer2(), AuthToken.VALIDITY_TIME * 24*60*60*1000L); + } + + public void timeReached() { _log.debug("Starting cleanup job.."); - ArrayList arr = new ArrayList(); - for (Map.Entry e : authTokens.entrySet()) { - AuthToken token = e.getValue(); - if (!token.isValid()) { - arr.add(e.getKey()); - } - } synchronized (authTokens) { - for (String s : arr) { - authTokens.remove(s); + for (Iterator iter = authTokens.values().iterator(); iter.hasNext(); ) { + AuthToken token = iter.next(); + if (!token.isValid()) + iter.remove(); } } _log.debug("Cleanup job done."); + schedule(30*60*1000L); } } } diff --git a/src/java/net/i2p/i2pcontrol/servlets/JSONRPC2Servlet.java b/src/java/net/i2p/i2pcontrol/servlets/JSONRPC2Servlet.java index e3c4a0e..448f963 100644 --- a/src/java/net/i2p/i2pcontrol/servlets/JSONRPC2Servlet.java +++ b/src/java/net/i2p/i2pcontrol/servlets/JSONRPC2Servlet.java @@ -105,7 +105,7 @@ public class JSONRPC2Servlet extends HttpServlet { disp.register(new NetworkSettingHandler(_context, _helper)); disp.register(new RouterInfoHandler(_context, _helper)); disp.register(new RouterManagerHandler(_context, _helper)); - disp.register(new I2PControlHandler(_context, _helper)); + disp.register(new I2PControlHandler(_context, _helper, _secMan)); disp.register(new AdvancedSettingsHandler(_context, _helper)); } diff --git a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/I2PControlHandler.java b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/I2PControlHandler.java index 69beedd..7126bb7 100644 --- a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/I2PControlHandler.java +++ b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/I2PControlHandler.java @@ -42,10 +42,12 @@ public class I2PControlHandler implements RequestHandler { private final RouterContext _context; private final Log _log; //private final ConfigurationManager _conf; + private final SecurityManager _secMan; private final JSONRPC2Helper _helper; - public I2PControlHandler(RouterContext ctx, JSONRPC2Helper helper) { + public I2PControlHandler(RouterContext ctx, JSONRPC2Helper helper, SecurityManager secMan) { _helper = helper; + _secMan = secMan; _context = ctx; if (ctx != null) _log = ctx.logManager().getLog(I2PControlHandler.class); @@ -62,8 +64,7 @@ public class I2PControlHandler implements RequestHandler { // Processes the requests public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) { if (req.getMethod().equals("I2PControl")) { - //return process(req); - return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID()); + return process(req); } else { // Method name not supported return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID()); @@ -71,18 +72,19 @@ public class I2PControlHandler implements RequestHandler { } -/**** private JSONRPC2Response process(JSONRPC2Request req) { JSONRPC2Error err = _helper.validateParams(null, req); if (err != null) return new JSONRPC2Response(err, req.getID()); +/**** only if we enable host/port changes if (_context == null) { return new JSONRPC2Response( new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(), "RouterContext was not initialized. Query failed"), req.getID()); } +****/ Map inParams = req.getNamedParams(); Map outParams = new HashMap(); @@ -90,6 +92,7 @@ public class I2PControlHandler implements RequestHandler { boolean settingsSaved = false; String inParam; +/**** if (inParams.containsKey("i2pcontrol.port")) { Integer oldPort = _conf.getConf("i2pcontrol.listen.port", 7650); if ((inParam = (String) inParams.get("i2pcontrol.port")) != null) { @@ -136,18 +139,20 @@ public class I2PControlHandler implements RequestHandler { } } } + outParams.put("RestartNeeded", restartNeeded); } +****/ if (inParams.containsKey("i2pcontrol.password")) { if ((inParam = (String) inParams.get("i2pcontrol.password")) != null) { - if (SecurityManager.getInstance().setPasswd(inParam)) { + if (_secMan.setPasswd(inParam)) { outParams.put("i2pcontrol.password", null); settingsSaved = true; } - ConfigurationManager.writeConfFile(); } } +/**** if (inParams.containsKey("i2pcontrol.address")) { String oldAddress = _conf.getConf("i2pcontrol.listen.address", "127.0.0.1"); if ((inParam = (String) inParams.get("i2pcontrol.address")) != null) { @@ -190,11 +195,11 @@ public class I2PControlHandler implements RequestHandler { } else { outParams.put("i2pcontrol.address", oldAddress); } + outParams.put("RestartNeeded", restartNeeded); } +****/ outParams.put("SettingsSaved", settingsSaved); - outParams.put("RestartNeeded", restartNeeded); return new JSONRPC2Response(outParams, req.getID()); } -****/ }