jadex.base.service.security.SecurityService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jadex-platform-base Show documentation
Show all versions of jadex-platform-base Show documentation
The Jadex platform base package contains
functionality useful for constructing platforms.
The newest version!
package jadex.base.service.security;
import jadex.base.service.remote.commands.AbstractRemoteCommand;
import jadex.bridge.ComponentIdentifier;
import jadex.bridge.IComponentIdentifier;
import jadex.bridge.IComponentStep;
import jadex.bridge.IExternalAccess;
import jadex.bridge.IInternalAccess;
import jadex.bridge.service.RequiredServiceInfo;
import jadex.bridge.service.annotation.SecureTransmission;
import jadex.bridge.service.annotation.Security;
import jadex.bridge.service.annotation.Service;
import jadex.bridge.service.annotation.ServiceComponent;
import jadex.bridge.service.annotation.ServiceShutdown;
import jadex.bridge.service.annotation.ServiceStart;
import jadex.bridge.service.types.context.IContextService;
import jadex.bridge.service.types.security.IAuthorizable;
import jadex.bridge.service.types.security.ISecurityService;
import jadex.bridge.service.types.settings.ISettingsService;
import jadex.commons.Base64;
import jadex.commons.IPropertiesProvider;
import jadex.commons.Properties;
import jadex.commons.Property;
import jadex.commons.SUtil;
import jadex.commons.Tuple2;
import jadex.commons.future.DelegationResultListener;
import jadex.commons.future.ExceptionDelegationResultListener;
import jadex.commons.future.Future;
import jadex.commons.future.IFuture;
import jadex.commons.future.IResultListener;
import jadex.xml.bean.JavaWriter;
import java.net.InetAddress;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@Service
public class SecurityService implements ISecurityService
{
//-------- constants --------
/** Properties id for the settings service. */
public static final String PROEPRTIES_ID = "securityservice";
//-------- attributes --------
/** The component. */
@ServiceComponent
protected IInternalAccess component;
/** Flag to enable / disable password protection. */
protected boolean usepass;
/** Determines if password was specified during creation. (i.e. in Platform Configuration) */
protected boolean argsusepass;
/** Print password on startup or change. */
protected boolean printpass;
/** The local password (if any). */
protected String password;
/** The stored passwords. */
protected Map platformpasses;
/** The stored passwords. */
protected Map networkpasses;
/** The trusted lan mode. */
protected boolean trustedlan;
/** Determines if trusted lan was specified during creation. */
protected boolean argstrustedlan;
/** The path to the keystore. */
protected String storepath;
/** The keystore password. */
protected String storepass;
/** The key password. */
protected String keypass;
/** The ContextService. */
protected IContextService contextser;
/** The currently valid digests. */
protected Map> digests;
//-------- setup --------
/**
* Create a security service.
*/
public SecurityService()
{
this(Boolean.TRUE, true, Boolean.FALSE, null, null);
}
/**
* Create a security service.
*/
public SecurityService(Boolean usepass, boolean printpass, Boolean trustedlan, String[] networknames, String[] networkpasses)
{
this.platformpasses = new LinkedHashMap();
this.networkpasses = new LinkedHashMap();
if(networknames!=null)
{
for(int i=0; i>();
this.usepass = usepass!=null? usepass.booleanValue(): true;
this.argsusepass = usepass != null;
this.printpass = printpass;
this.trustedlan = trustedlan!=null? trustedlan.booleanValue(): false;
this.argstrustedlan = trustedlan != null;
this.storepath = "./keystore";
this.storepass = "keystore";
this.keypass = "keystore";
}
/**
* Start the service.
*/
@ServiceStart
public IFuture start()
{
final Future ret = new Future();
// this.trustednets = new ArrayList();
component.getServiceContainer().searchService(IContextService.class, RequiredServiceInfo.SCOPE_PLATFORM)
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(IContextService result)
{
contextser = result;
setTrustedLanMode(trustedlan);
getSettingsService().addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(final ISettingsService settings)
{
if(settings==null)
{
// generate new password, if no security settings exist, yet.
password = UUID.randomUUID().toString().substring(0, 12);
// usepass = true;
ret.setResult(null);
}
else
{
settings.getProperties(PROEPRTIES_ID)
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(final Properties props)
{
// generate new password, if no security settings exist, yet.
final boolean genpass = props==null || props.getProperty("password")==null;
if(genpass)
{
password = UUID.randomUUID().toString().substring(0, 12);
// usepass = true;
}
final IExternalAccess access = component.getExternalAccess();
settings.registerPropertiesProvider(PROEPRTIES_ID, new IPropertiesProvider()
{
public IFuture setProperties(final Properties props)
{
return access.scheduleImmediate(new IComponentStep()
{
public IFuture execute(IInternalAccess ia)
{
String spa = props.getStringProperty("storepath");
if(spa!=null && spa.length()>0)
storepath = spa;
String sps = props.getStringProperty("storepass");
if(sps!=null && spa.length()>0)
storepass = sps;
String kp = props.getStringProperty("keypass");
if(kp!=null && kp.length()>0)
keypass = kp;
if(!argsusepass)
{
usepass = props.getBooleanProperty("usepass");
// System.out.println("usepass: "+usepass);
}
password = props.getStringProperty("password");
if(!argstrustedlan)
{
setTrustedLanMode(props.getBooleanProperty("trustedlan"));
}
Property[] passes = props.getProperties("passwords");
// platformpasses = new LinkedHashMap();
for(int i=0; i addrs = contextser.getNetworkIps();
Set trs = new HashSet();
for(InetAddress addr: addrs)
{
trs.add(addr.getHostAddress());
}
Property[] networks = props.getProperties("networks");
// networkpasses = new LinkedHashMap();
for(int i=0; i getProperties()
{
return access.scheduleImmediate(new IComponentStep()
{
public IFuture execute(IInternalAccess ia)
{
Properties ret = new Properties();
ret.addProperty(new Property("usepass", ""+usepass));
ret.addProperty(new Property("password", password));
if(platformpasses!=null)
{
for(String platform: platformpasses.keySet())
{
ret.addProperty(new Property(platform, "passwords", platformpasses.get(platform)));
}
}
if(networkpasses!=null)
{
for(String network: networkpasses.keySet())
{
ret.addProperty(new Property(network, "networks", platformpasses.get(network)));
}
}
ret.addProperty(new Property("trustedlan", ""+trustedlan));
ret.addProperty(new Property("storepath", storepath));
ret.addProperty(new Property("storepass", storepass));
ret.addProperty(new Property("keypass", keypass));
return new Future(ret);
}
});
}
}).addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
// If new password was generated, save settings such that new platform instances use it.
if(genpass)
{
if(printpass && usepass)
{
System.out.println("Generated platform password: "+password);
}
settings.saveProperties().addResultListener(new DelegationResultListener(ret));
}
else
{
if(printpass && usepass)
{
System.out.println("Using stored platform password: "+password);
}
super.customResultAvailable(result);
}
}
});
}
});
}
}
});
}
});
return ret;
}
/**
* Get the settings service.
*/
public IFuture getSettingsService()
{
final Future ret = new Future();
IFuture fut = component.getServiceContainer().searchService(ISettingsService.class, RequiredServiceInfo.SCOPE_PLATFORM);
fut.addResultListener(new DelegationResultListener(ret)
{
public void exceptionOccurred(Exception exception)
{
ret.setResult(null);
}
});
return ret;
}
/**
* Shutdown the service.
*/
@ServiceShutdown
public IFuture shutdown()
{
final Future ret = new Future();
component.getServiceContainer().searchService(ISettingsService.class, RequiredServiceInfo.SCOPE_PLATFORM)
.addResultListener(new IResultListener()
{
public void resultAvailable(ISettingsService settings)
{
settings.deregisterPropertiesProvider(PROEPRTIES_ID)
.addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
SecurityService.this.platformpasses = null;
ret.setResult(null);
}
});
}
public void exceptionOccurred(Exception exception)
{
// No settings service: ignore.
SecurityService.this.platformpasses = null;
ret.setResult(null);
}
});
return ret;
}
//-------- password management --------
/**
* Check if password protection is enabled.
* @return True, if password protection is enabled.
*/
public IFuture isUsePassword()
{
return new Future(usepass);
}
/**
* Enable / disable password protection.
* @param enable If true, password protection is enabled, otherwise disabled.
* @throws Exception, when enable is true and no password is set.
*/
public IFuture setUsePassword(boolean enable)
{
IFuture ret;
if(enable && password==null)
{
ret = new Future(new IllegalStateException("Cannot enable password protection, no password set."));
}
else
{
this.usepass = enable;
ret = IFuture.DONE;
if(printpass && usepass)
{
System.out.println("Using stored platform password: "+password);
}
}
return ret;
}
/**
* Get the local password.
* @return The password of the local platform (if any).
*/
@SecureTransmission
// Todo: password is transferred in plain text unless transport uses encryption.
public IFuture getLocalPassword()
{
return new Future(password);
}
/**
* Set the local password.
* @param password The password of the local platform.
* @throws Exception, when a null password is provided and use password is true.
*/
@SecureTransmission
// Todo: password is transferred in plain text unless transport uses encryption.
public IFuture setLocalPassword(String password)
{
IFuture ret;
if(password==null && usepass)
{
ret = new Future(new IllegalStateException("Cannot set password to null, when password protection is enabled."));
}
else
{
this.password = password;
ret = IFuture.DONE;
if(printpass && usepass)
{
System.out.println("Using new platform password: "+password);
}
}
return ret;
}
/**
* Get the password for a target component.
* @param target The id of the target component.
* @return The stored password. Returns null if no password is stored, unless the
* component is a local component in which case the local password (if any) is returned.
*/
@SecureTransmission
// Todo: password is transferred in plain text unless transport uses encryption.
public IFuture getPlatformPassword(IComponentIdentifier target)
{
String starget = target.getPlatformPrefix();
String ret = platformpasses.get(starget);
if(ret==null && starget.equals(component.getComponentIdentifier().getPlatformPrefix()))
{
ret = this.password;
}
return new Future(ret);
}
/**
* Set the password for a target component.
* Note that passwords are currently stored on a per platform basis,
* i.e. there is only one stored password for all components of the same platform.
* Moreover, the security service strips the auto-generated extension from the platform
* name and therefore can reuse the password for different instances of the same platform.
* @param target The id of the target component.
* @param password The password or null if no password should be used.
*/
@SecureTransmission
// Todo: password is transferred in plain text unless transport uses encryption.
public IFuture setPlatformPassword(IComponentIdentifier target, String password)
{
if(password!=null)
{
platformpasses.put(target.getPlatformPrefix(), password);
}
else
{
// Use remove to avoid keeping old mappings forever (name would still be stored otherwise)
platformpasses.remove(target.getPlatformPrefix());
}
return IFuture.DONE;
}
/**
* Get the password for a network.
* @param target The id of the target component.
* @return The stored password. Returns null if no password is stored, unless the
* component is a local component in which case the local password (if any) is returned.
*/
@SecureTransmission
// Todo: password is transferred in plain text unless transport uses encryption.
public IFuture getNetworkPassword(String network)
{
String ret = networkpasses.get(network);
return new Future(ret);
}
/**
* Set the password for a network.
* @param network The id of the network.
* @param password The password or null if no password should be used.
*/
@SecureTransmission
// Todo: password is transferred in plain text unless transport uses encryption.
public IFuture setNetworkPassword(String network, String password)
{
if(password!=null)
{
networkpasses.put(network, password);
}
else
{
// Use remove to avoid keeping old mappings forever (name would still be stored otherwise)
networkpasses.remove(network);
}
return IFuture.DONE;
}
/**
* Get all stored passwords.
* @return A map containing the stored passwords as pairs (platform name -> password).
*/
@SecureTransmission
// Todo: passwords are transferred in plain text unless transport uses encryption.
public IFuture