Make the plugin shut down properly.

Moved SecurityManager from a static to a Singleton design.
This commit is contained in:
dev
2011-08-03 11:44:56 +00:00
parent 0ea28c8b5b
commit b043b4b589
6 changed files with 83 additions and 32 deletions

View File

@ -55,12 +55,13 @@ public class I2PControlController{
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PControlController.class);
private static String _pluginDir = "";
private static ConfigurationManager _conf;
private static SecurityManager _secMan;
private static Server _server;
public static void main(String args[]) {
if (args.length != 3 || (!"-d".equals(args[0])))
throw new IllegalArgumentException("Usage: PluginController -d $PLUGIN [start|stop]");
throw new IllegalArgumentException("Usage: PluginController -d $PLUGINDIR [start|stop]");
if ("start".equals(args[2])){
File pluginDir = new File(args[1]);
@ -69,12 +70,14 @@ public class I2PControlController{
_pluginDir = pluginDir.getAbsolutePath();
ConfigurationManager.setConfDir(pluginDir.getAbsolutePath());
_conf = ConfigurationManager.getInstance();
_secMan = SecurityManager.getInstance();
start(args);
//stop(); // Delete Me
} else if ("stop".equals(args[2]))
stop();
else
throw new IllegalArgumentException("Usage: PluginController -d $PLUGIN [start|stop]");
throw new IllegalArgumentException("Usage: PluginController -d $PLUGINDIR [start|stop]");
}
@ -141,14 +144,14 @@ public class I2PControlController{
}
SslListener ssl = new SslListener();
ssl.setProvider(SecurityManager.getSecurityProvider());
ssl.setCipherSuites(SecurityManager.getSupprtedSSLCipherSuites());
ssl.setProvider(_secMan.getSecurityProvider());
ssl.setCipherSuites(_secMan.getSupprtedSSLCipherSuites());
ssl.setHost(address);
ssl.setPort(port);
ssl.setWantClientAuth(false); // Don't care about client authentication.
ssl.setPassword(SecurityManager.getKeyStorePassword());
ssl.setKeyPassword(SecurityManager.getKeyStorePassword());
ssl.setKeystoreType(SecurityManager.getKeyStoreType());
ssl.setPassword(_secMan.getKeyStorePassword());
ssl.setKeyPassword(_secMan.getKeyStorePassword());
ssl.setKeystoreType(_secMan.getKeyStoreType());
ssl.setKeystore(KeyStoreFactory.getKeyStoreLocation());
ssl.setName("SSL Listener-" + ++listeners);
@ -247,13 +250,45 @@ public class I2PControlController{
private static void stop() {
ConfigurationManager.writeConfFile();
_secMan.stopTimedEvents();
try {
if (_server != null)
if (_server != null){
_server.stop();
_server = null;
for (HttpListener listener : _server.getListeners()){
listener.stop();
}
_server.destroy();
_server = null;
}
} catch (InterruptedException e) {
_log.error("Stopping server" + e);
}
// Get and stop all running threads
ThreadGroup threadgroup = Thread.currentThread().getThreadGroup();
Thread[] threads = new Thread[threadgroup.activeCount()+3];
threadgroup.enumerate(threads, true);
for (Thread thread : threads){
// System.out.println("Active thread: " + thread.getName());
if (thread != null ){//&& thread.isAlive()){
thread.interrupt();
}
}
for (Thread thread : threads){
if (thread != null){
System.out.println("Active thread: " + thread.getName());
//if (thread != null && thread.isAlive()){
// thread.interrupt();
//}
}
}
//Thread.currentThread().getName()
threadgroup.interrupt();
//Thread.currentThread().getThreadGroup().destroy();
}
public static String getPluginDir(){

View File

@ -8,12 +8,14 @@ import java.util.Date;
public class AuthToken {
private static final int VALIDITY_TIME = 1; // Measured in days
private SecurityManager _secMan;
private String id;
private Date expiry;
public AuthToken(String password){
String hash = SecurityManager.getPasswdHash(password);
this.id = SecurityManager.getHash(hash + Calendar.getInstance().getTimeInMillis());
_secMan = SecurityManager.getInstance();
String hash = _secMan.getPasswdHash(password);
this.id = _secMan.getHash(hash + Calendar.getInstance().getTimeInMillis());
Calendar expiry = Calendar.getInstance();
expiry.add(Calendar.DAY_OF_YEAR, VALIDITY_TIME);
this.expiry = expiry.getTime();

View File

@ -44,17 +44,25 @@ public class SecurityManager {
private final static String SSL_PROVIDER = "SunJSSE";
private final static String DEFAULT_AUTH_BCRYPT_SALT = "$2a$11$5aOLx2x/8i4fNaitoCSSWu";
private final static String DEFAULT_AUTH_PASSWORD = "$2a$11$5aOLx2x/8i4fNaitoCSSWuut2wEl3Hupuca8DCT.NXzvH9fq1pBU.";
private final static HashMap<String,AuthToken> authTokens;
private final static Timer timer;
private static String[] SSL_CIPHER_SUITES;
private static KeyStore _ks;
private static Log _log;
private HashMap<String,AuthToken> authTokens;
private Timer timer;
private String[] SSL_CIPHER_SUITES;
private KeyStore _ks;
private Log _log;
private static SecurityManager _securityManager;
static {
public static SecurityManager getInstance(){
if (_securityManager == null){
_securityManager = new SecurityManager();
}
return _securityManager;
}
private SecurityManager(){
_log = I2PAppContext.getGlobalContext().logManager().getLog(SecurityManager.class);
authTokens = new HashMap<String,AuthToken>();
timer = new Timer();
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);
@ -70,27 +78,31 @@ public class SecurityManager {
_ks = KeyStoreInitializer.getKeyStore();
}
public static String[] getSupprtedSSLCipherSuites(){
public String[] getSupprtedSSLCipherSuites(){
return SSL_CIPHER_SUITES;
}
public static String getSecurityProvider(){
public String getSecurityProvider(){
return SSL_PROVIDER;
}
public static String getKeyStorePassword(){
public String getKeyStorePassword(){
return KeyStoreFactory.DEFAULT_KEYSTORE_PASSWORD;
}
public static String getKeyStoreType(){
public String getKeyStoreType(){
return KeyStoreFactory.DEFAULT_KEYSTORE_TYPE;
}
public void stopTimedEvents(){
timer.cancel();
}
/**
* Return the X509Certificate of the server as a Base64 encoded string.
* @return base64 encode of X509Certificate
*/
public static String getBase64Cert(){
public String getBase64Cert(){
X509Certificate caCert = KeyStoreFactory.readCert(_ks,
CERT_ALIAS,
KeyStoreFactory.DEFAULT_KEYSTORE_PASSWORD);
@ -118,7 +130,7 @@ public class SecurityManager {
* @param pwd
* @return BCrypt hash of salt and input string
*/
public static String getPasswdHash(String pwd){
public String getPasswdHash(String pwd){
return BCrypt.hashpw(pwd, ConfigurationManager.getInstance().getConf("auth.salt", DEFAULT_AUTH_BCRYPT_SALT));
}
@ -127,7 +139,7 @@ public class SecurityManager {
* @param string
* @return
*/
public static String getHash(String string) {
public String getHash(String string) {
SHA256Generator hashGen = new SHA256Generator(I2PAppContext.getGlobalContext());
byte[] bytes = string.getBytes();
bytes = hashGen.calculateHash(bytes).toByteArray();
@ -140,7 +152,7 @@ public class SecurityManager {
* The token will be valid for one day.
* @return Returns AuthToken if password is valid. If password is invalid null will be returned.
*/
public static AuthToken validatePasswd(String pwd){
public AuthToken validatePasswd(String pwd){
String storedPass = ConfigurationManager.getInstance().getConf("auth.password", DEFAULT_AUTH_PASSWORD);
if (getPasswdHash(pwd).equals(storedPass)){
AuthToken token = new AuthToken(pwd);
@ -156,7 +168,7 @@ public class SecurityManager {
* @param newPasswd
* @return Returns true if a new password was set.
*/
public static boolean setPasswd(String newPasswd){
public boolean setPasswd(String newPasswd){
String newHash = getPasswdHash(newPasswd);
String oldHash = ConfigurationManager.getInstance().getConf("auth.password", DEFAULT_AUTH_PASSWORD);
@ -174,7 +186,7 @@ public class SecurityManager {
* @throws InvalidAuthTokenException
* @throws ExpiredAuthTokenException
*/
public static void verifyToken(String tokenID) throws InvalidAuthTokenException, 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.");
@ -192,7 +204,8 @@ public class SecurityManager {
* @author hottuna
*
*/
private static class Sweeper extends TimerTask{
private class Sweeper extends TimerTask{
@Override
public void run(){
_log.debug("Starting cleanup job..");

View File

@ -51,7 +51,8 @@ public class AuthenticateHandler implements RequestHandler {
String pwd = (String) inParams.get("Password");
// Try get an AuthToken
AuthToken token = SecurityManager.validatePasswd(pwd);
AuthToken token = SecurityManager.getInstance().validatePasswd(pwd);
if (token == null){
return new JSONRPC2Response(JSONRPC2ExtendedError.INVALID_PASSWORD, req.getID());
}

View File

@ -145,7 +145,7 @@ public class I2PControlHandler implements RequestHandler {
if(inParams.containsKey("i2pcontrol.password")){
if ((inParam = (String) inParams.get("i2pcontrol.password")) != null){
if (SecurityManager.setPasswd(inParam)){
if (SecurityManager.getInstance().setPasswd(inParam)){
outParams.put("i2pcontrol.password", null);
settingsSaved = true;
}

View File

@ -94,7 +94,7 @@ public class JSONRPC2Helper {
return JSONRPC2ExtendedError.NO_TOKEN;
}
try {
SecurityManager.verifyToken(tokenID);
SecurityManager.getInstance().verifyToken(tokenID);
} catch (InvalidAuthTokenException e){
return JSONRPC2ExtendedError.INVALID_TOKEN;
} catch (ExpiredAuthTokenException e){