/**************************************************************************** * Copyright (c) 2005, 2010 Jan S. Rellermeyer, Systems Group, * Department of Computer Science, ETH Zurich and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jan S. Rellermeyer - initial API and implementation * Markus Alexander Kuppe - enhancements and bug fixes * *****************************************************************************/ package ch.ethz.iks.slp.impl; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; /** * SLPConfiguration object holds all configurable properties. * * @author Jan S. Rellermeyer, ETH Zurich * @since 0.1 */ class SLPConfiguration { private static final String USE_SCOPES_PROP = "net.slp.useScopes"; private static final String USE_SCOPES_DEFAULT = "DEFAULT"; private static final String DA_ADDRESSES_PROP = "net.slp.DAAddresses"; private static final String DA_ADDRESSES_DEFAULT = null; private static final String WAIT_TIME_PROP = "net.slp.waitTime"; private static final String WAIT_TIME_DEFAULT = "1000"; private static final String TRACE_DATRAFFIC_PROP = "net.slp.traceDATraffic"; private static final String TRACE_DATRAFFIC_DEFAULT = "false"; private static final String TRACE_MESSAGE_PROP = "net.slp.traceMsg"; private static final String TRACE_MESSAGE_DEFAULT = "false"; private static final String TRACE_DROP_PROP = "net.slp.traceDrop"; private static final String TRACE_DROP_DEFAULT = "false"; private static final String TRACE_REG_PROP = "net.slp.traceReg"; private static final String TRACE_REG_DEFAULT = "false"; private static final String MCAST_TTL_PROP = "net.slp.multicastTTL"; private static final String MCAST_TTL_DEFAULT = "255"; private static final String MCAST_MAX_WAIT_PROP = "net.slp.multicastMaximumWait"; private static final String MCAST_MAX_WAIT_DEFAULT = "15000"; private static final String MCAST_TIMEOUTS_PROP = "net.slp.multicastTimeouts"; private static final String MCAST_TIMEOUTS_DEFAULT = "3000,2000,1500,1000,750,500"; private static final String DATAGRAM_MAX_WAIT_PROP = "net.slp.datagramMaximumWait"; private static final String DATAGRAM_MAX_WAIT_DEFAULT = "5000"; private static final String DATAGRAM_TIMEOUTS_PROP = "net.slp.datagramTimeouts"; private static final String DATAGRAM_TIMEOUTS_DEFAULT = "3000,3000,3000,3000,3000"; private static final String MTU_PROP = "net.slp.MTU"; private static final String MTU_DEFAULT = "1400"; private static final String SECURITY_ENABLED_PROP = "net.slp.securityEnabled"; private static final String SECURITY_ENABLED_DEFAULT = "false"; private static final String SPI_PROP = "net.slp.spi"; private static final String SPI_DEFAULT = ""; private static final String PRIVATE_KEY_PROP = "net.slp.privateKey."; private static final String PUBLIC_KEY_PROP = "net.slp.publicKey."; private static final String INTERFACES_PROP = "net.slp.interfaces"; private static final String INTERFACES_DEFAULT = null; private static final String NO_DA_DISCOVERY_PROP = "net.slp.noDADiscovery"; private static final String PORT_PROP = "net.slp.port"; private static final String DEFAULT_PORT = "427"; private static final String DEFAULT_CONVERGENCE_FAILERCOUNT = "2"; private static final String CONVERGENCE_FAILERCOUNT_PROP = "net.slp.failercount"; private static final String DEBUG_ENABLED_PROP = "ch.ethz.iks.slp.debug"; private static String[] INTERFACES; private static int PORT; private static String SCOPES; private static boolean NO_DA_DISCOVERY; private static String[] DA_ADDRESSES; private static boolean TRACE_DA_TRAFFIC; private static boolean TRACE_MESSAGES; private static boolean TRACE_DROP; private static boolean TRACE_REG; private static int MCAST_TTL; private static int MCAST_MAX_WAIT; private static int[] MCAST_TIMEOUTS; private static int DATAGRAM_MAX_WAIT; private static int[] DATAGRAM_TIMEOUTS; private static int MTU; private static boolean SECURITY_ENABLED; private static String SPI; private static int WAIT_TIME; private static Map PUBLIC_KEY_CACHE; private static Map PRIVATE_KEY_CACHE; private static int CONVERGENCE_FAILERCOUNT; private static boolean DEBUG_ENABLED; /** * create a new SLPConfiguration from properties. * * @param properties * properties. */ SLPConfiguration() { processProperties(System.getProperties()); } /** * create a new SLPConfiguration from config file. * * @param file * the file. * @throws IOException * in case of IO errors. */ SLPConfiguration(final File file) throws IOException { Properties props = new Properties(); props.load(new FileInputStream(file)); props.putAll(System.getProperties()); processProperties(props); } private static void processProperties(final Properties props) { String ifaces = props.getProperty(INTERFACES_PROP, INTERFACES_DEFAULT); if (ifaces == null) { INTERFACES = null; } else { INTERFACES = (String[]) SLPMessage.stringToList(ifaces, ",") .toArray(new String[0]); } PORT = Integer.parseInt(props.getProperty(PORT_PROP, DEFAULT_PORT)); SCOPES = props.getProperty(USE_SCOPES_PROP, USE_SCOPES_DEFAULT); NO_DA_DISCOVERY = new Boolean(props.getProperty(NO_DA_DISCOVERY_PROP, "false")).booleanValue(); final String dAs = props.getProperty(DA_ADDRESSES_PROP, DA_ADDRESSES_DEFAULT); if (dAs == null) { DA_ADDRESSES = null; } else { DA_ADDRESSES = (String[]) SLPMessage.stringToList(dAs, ",") .toArray(new String[0]); } TRACE_DA_TRAFFIC = new Boolean(props.getProperty(TRACE_DATRAFFIC_PROP, TRACE_DATRAFFIC_DEFAULT)).booleanValue(); TRACE_MESSAGES = new Boolean(props.getProperty(TRACE_MESSAGE_PROP, TRACE_MESSAGE_DEFAULT)).booleanValue(); TRACE_DROP = new Boolean(props.getProperty(TRACE_DROP_PROP, TRACE_DROP_DEFAULT)).booleanValue(); TRACE_REG = new Boolean(props.getProperty(TRACE_REG_PROP, TRACE_REG_DEFAULT)).booleanValue(); MCAST_TTL = Integer.parseInt(props.getProperty(MCAST_TTL_PROP, MCAST_TTL_DEFAULT)); MCAST_MAX_WAIT = Integer.parseInt(props.getProperty( MCAST_MAX_WAIT_PROP, MCAST_MAX_WAIT_DEFAULT)); DATAGRAM_MAX_WAIT = Integer.parseInt(props.getProperty( DATAGRAM_MAX_WAIT_PROP, DATAGRAM_MAX_WAIT_DEFAULT)); MCAST_TIMEOUTS = parseTimeouts(props.getProperty(MCAST_TIMEOUTS_PROP, MCAST_TIMEOUTS_DEFAULT)); DATAGRAM_TIMEOUTS = parseTimeouts(props.getProperty( DATAGRAM_TIMEOUTS_PROP, DATAGRAM_TIMEOUTS_DEFAULT)); MTU = Integer.parseInt(props.getProperty(MTU_PROP, MTU_DEFAULT)); SECURITY_ENABLED = new Boolean(props.getProperty(SECURITY_ENABLED_PROP, SECURITY_ENABLED_DEFAULT)).booleanValue(); SPI = props.getProperty(SPI_PROP, SPI_DEFAULT); WAIT_TIME = Integer.parseInt(props.getProperty(WAIT_TIME_PROP, WAIT_TIME_DEFAULT)); CONVERGENCE_FAILERCOUNT = Integer.parseInt(props.getProperty(CONVERGENCE_FAILERCOUNT_PROP, DEFAULT_CONVERGENCE_FAILERCOUNT)); DEBUG_ENABLED = new Boolean(props.getProperty(DEBUG_ENABLED_PROP, "false")).booleanValue(); if (SECURITY_ENABLED) { PUBLIC_KEY_CACHE = new HashMap(0); PRIVATE_KEY_CACHE = new HashMap(0); } } /** * returns the network interfaces. * * @return interfaces */ String[] getInterfaces() { return INTERFACES; } /** * get the port. * * @return the port */ int getPort() { return PORT; } /** * get the scopes. * * @return the scopes. */ String getScopes() { return SCOPES; } /** * get the predefined DA addresses. * * @return the DA addresses. */ String[] getDaAddresses() { return DA_ADDRESSES; } /** * get no DA discovery * * @return true, if DA discovery is disabled */ boolean getNoDaDiscovery() { return NO_DA_DISCOVERY; } /** * trace DA traffic ? * * @return true if trace is enabled. */ boolean getTraceDaTraffic() { return TRACE_DA_TRAFFIC; } /** * trace messages ? * * @return true if trace is enabled. */ boolean getTraceMessage() { return TRACE_MESSAGES; } /** * trace dropped messages ? * * @return true if trace is enabled. */ boolean getTraceDrop() { return TRACE_DROP; } /** * trace registrations ? * * @return true if trace is enabled. */ boolean getTraceReg() { return TRACE_REG; } /** * get the multicast TTL. * * @return the multicast TTL. */ int getMcastTTL() { return MCAST_TTL; } /** * get the multicast max wait time. * * @return the max wait time. */ int getMcastMaxWait() { return MCAST_MAX_WAIT; } /** * get the datagram max wait time. * * @return the datagram max wait time. */ int getDatagramMaxWait() { return DATAGRAM_MAX_WAIT; } /** * parse timeout lists. * * @param s * a timeout list string. * @return the timeout int array. */ private static int[] parseTimeouts(final String s) { StringTokenizer st = new StringTokenizer(s, ","); int[] timeouts = new int[st.countTokens()]; for (int i = 0; i < timeouts.length; i++) { timeouts[i] = Integer.parseInt(st.nextToken()); } return timeouts; } /** * get the multicast timeouts. * * @return the multicast timeouts. */ int[] getMcastTimeouts() { return MCAST_TIMEOUTS; } /** * get the datagram timeouts. * * @return the datagram timeouts. */ int[] getDatagramTimeouts() { return DATAGRAM_TIMEOUTS; } /** * get the MTU. * * @return the MTU. */ int getMTU() { return MTU; } /** * is security enabled ? * * @return true if security is enabled. */ boolean getSecurityEnabled() { return SECURITY_ENABLED; } /** * get the SPIs. * * @return the SPI string list. */ String getSPI() { return SPI; } /** * get the public key for a certain SPI. * * @param spi * the SPI. * @return the location of the public key. * @throws IOException * @throws GeneralSecurityException */ PublicKey getPublicKey(final String spi) throws IOException, GeneralSecurityException { PublicKey key = (PublicKey) PUBLIC_KEY_CACHE.get(spi); if (key != null) { return key; } FileInputStream keyfis = new FileInputStream(System .getProperty(PUBLIC_KEY_PROP + spi)); byte[] encKey = new byte[keyfis.available()]; keyfis.read(encKey); keyfis.close(); X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey); KeyFactory keyFactory = KeyFactory.getInstance("DSA"); key = keyFactory.generatePublic(pubKeySpec); PUBLIC_KEY_CACHE.put(spi, key); return key; } /** * get the private key for a certain SPI. * * @param spi * the SPI. * @return the location of the private key. * @throws IOException * @throws GeneralSecurityException */ PrivateKey getPrivateKey(final String spi) throws IOException, GeneralSecurityException { PrivateKey key = (PrivateKey) PRIVATE_KEY_CACHE.get(spi); if (key != null) { return key; } FileInputStream keyfis = new FileInputStream(System .getProperty(PRIVATE_KEY_PROP + spi)); byte[] encKey = new byte[keyfis.available()]; keyfis.read(encKey); keyfis.close(); PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(encKey); KeyFactory keyFactory = KeyFactory.getInstance("DSA"); key = keyFactory.generatePrivate(privKeySpec); PRIVATE_KEY_CACHE.put(spi, key); return key; } /** * get the default wait time. * * @return the default wait time. */ int getWaitTime() { return WAIT_TIME; } /** * Defines after how many inconclusive multicastConvergence cycles the attempt is aborted. * It indirectly defines how many multicast convergence {@link SLPMessage}.SRVTYPERQST get send during an attempt. * * This value can be seen as an heuristical optimization to stop multicast convergence early if inconclusive * @return how many inconclusive cycles are allowed */ int getConvergenceFailerCount() { return CONVERGENCE_FAILERCOUNT; } /** * Whether Debug mode is turned on or off * @return true if debug mode is enabled */ boolean getDebugEnabled() { return DEBUG_ENABLED; } /** * @return int defining when a TCP send should time out */ int getTCPTimeout() { // TODO wire this to the properties if necessary return 5000; // 5sec } }