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
This commit is contained in:
zzz
2018-02-02 13:50:14 +00:00
parent d5c2f6b8e3
commit 55199e666a
4 changed files with 45 additions and 37 deletions

View File

@ -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;

View File

@ -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<String, AuthToken> 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<String, AuthToken>();
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<String> arr = new ArrayList<String>();
for (Map.Entry<String, AuthToken> 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<AuthToken> iter = authTokens.values().iterator(); iter.hasNext(); ) {
AuthToken token = iter.next();
if (!token.isValid())
iter.remove();
}
}
_log.debug("Cleanup job done.");
schedule(30*60*1000L);
}
}
}

View File

@ -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));
}

View File

@ -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<String, Object> 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());
}
****/
}