Initial commit to support provisioning. It provides the DHCP provisioning discovery method, the provisioning URL can also be retrieved from configuration.

cusax-fix
Sebastien Vincent 15 years ago
parent 5024715207
commit 3d77efb36f

@ -931,7 +931,9 @@
bundle-replacement,bundle-youtube,bundle-dailymotion,bundle-smiley,
bundle-vimeo,bundle-vbox7,bundle-metacafe,bundle-flickr,bundle-hulu,
bundle-twitpic,bundle-directimage,bundle-bliptv,bundle-viddler,
bundle-plugin-chatconfig,bundle-certificate"/>
bundle-plugin-chatconfig,bundle-certificate,
bundle-provdisc,bundle-provdisc-dhcp,
bundle-provisioning"/>
<!--BUNDLE-SC-LAUNCHER-->
<target name="bundle-sc-launcher">
@ -2526,6 +2528,35 @@ org.apache.http.util"/>
</jar>
</target>
<!-- BUNDLE-PROVDISC-->
<target name="bundle-provdisc">
<!-- Creates a bundle containing the provisioning discovery service.-->
<jar compress="false" destfile="${bundles.dest}/provdisc.jar"
manifest="${src}/net/java/sip/communicator/service/provdisc/provdisc.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/service/provdisc"
prefix="net/java/sip/communicator/service/provdisc"/>
</jar>
</target>
<!--BUNDLE-PROVDISC-DHCP -->
<target name="bundle-provdisc-dhcp">
<jar compress="false" destfile="${bundles.dest}/provdisc-dhcp.jar"
manifest="${src}/net/java/sip/communicator/impl/provdisc/dhcp/dhcp.provdisc.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/impl/provdisc/dhcp"
prefix="net/java/sip/communicator/impl/provdisc/dhcp" />
<zipfileset src="${lib.noinst}/dhcp4java-1.00.jar"/>
</jar>
</target>
<!--BUNDLE-PROVISIONING -->
<target name="bundle-provisioning">
<jar compress="false" destfile="${bundles.dest}/provisioning.jar"
manifest="${src}/net/java/sip/communicator/plugin/provisioning/provisioning.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/plugin/provisioning"
prefix="net/java/sip/communicator/plugin/provisioning" />
</jar>
</target>
<target name="bundle-certificate">
<jar compress="false" destfile="${bundles.dest}/certificate.jar"
manifest="${src}/net/java/sip/communicator/impl/certificate/certificate.manifest.mf">

@ -38,8 +38,10 @@ felix.auto.start.30= \
felix.auto.start.40= \
reference:file:sc-bundles/configuration.jar \
reference:file:sc-bundles/provdisc.jar \
reference:file:sc-bundles/resourcemanager.jar \
reference:file:sc-bundles/jfontchooserlib.jar \
reference:file:sc-bundles/netaddr.jar \
reference:file:sc-bundles/browserlauncher.jar
felix.auto.start.42= \
@ -52,9 +54,11 @@ felix.auto.start.45= \
reference:file:sc-bundles/version.jar \
reference:file:sc-bundles/version-impl.jar \
reference:file:sc-bundles/branding.jar \
reference:file:sc-bundles/provdisc-dhcp.jar \
reference:file:sc-bundles/certificate.jar
felix.auto.start.49= \
reference:file:sc-bundles/provisioning.jar \
reference:file:sc-bundles/bouncycastle.jar \
reference:file:sc-bundles/zrtp4j.jar \
reference:file:sc-bundles/protocol.jar \
@ -81,7 +85,6 @@ felix.auto.start.52= \
reference:file:sc-bundles/protocol-yahoo.jar \
reference:file:sc-bundles/protocol-gibberish.jar \
reference:file:sc-bundles/protocol-ssh.jar \
reference:file:sc-bundles/netaddr.jar \
reference:file:sc-bundles/reconnectplugin.jar \
reference:file:sc-bundles/protocol-zeroconf.jar \
reference:file:sc-bundles/protocol-irc.jar \

@ -163,7 +163,6 @@ public synchronized InetAddress getLocalHost(
}
else
{
//no point in making sure that the localHostFinderSocket is
//initialized.
//better let it through a NullPointerException.

@ -0,0 +1,252 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.provdisc.dhcp;
import java.net.*;
import java.util.*;
import net.java.sip.communicator.service.provdisc.event.*;
import net.java.sip.communicator.service.netaddr.*;
import net.java.sip.communicator.util.*;
import org.dhcp4java.*;
/**
* Class that will perform DHCP provisioning discovery.
*
* @author Sebastien Vincent
*/
public class DHCPProvisioningDiscover
implements Runnable
{
/**
* Logger.
*/
private final Logger logger
= Logger.getLogger(DHCPProvisioningDiscover.class);
/**
* UDP socket.
*/
private DatagramSocket socket = null;
/**
* Listening port of the client. Note that the socket will send packet to
* DHCP server on port - 1.
*/
private int port = 6768;
/**
* Option code of the specific provisioning option.
*/
private byte option = (byte)120;
/**
* DHCP timeout (in milliseconds).
*/
private static final int DHCP_TIMEOUT = 5000;
/**
* List of <tt>ProvisioningListener</tt> that will be notified when
* a provisioning URL is retrieved.
*/
private List<DiscoveryListener> listeners =
new ArrayList<DiscoveryListener>();
/**
* Constructor.
*
* @param port port on which we will bound and listen for DHCP response
* @param option code of the specific provisioning option
* @throws Exception if anything goes wrong during initialization
*/
public DHCPProvisioningDiscover(int port, byte option) throws Exception
{
this.port = port;
this.option = option;
socket = new DatagramSocket(port);
/* set timeout so that we will not blocked forever if we
* have no response from DHCP server
*/
socket.setSoTimeout(DHCP_TIMEOUT);
}
/**
* It sends a DHCPINFORM message from all interfaces and wait for a
* response. Thread stops after first successful answer that contains
* specific option and thus the provisioning URL.
*
* @return provisioning URL
*/
public String discoverProvisioningURL()
{
DHCPPacket inform = new DHCPPacket();
byte macAddress[] = null;
byte zeroIPAddress[] = {0x00, 0x00, 0x00, 0x00};
byte broadcastIPAddr[] = {(byte)255, (byte)255, (byte)255, (byte)255};
DHCPOption dhcpOpts[] = new DHCPOption[1];
int xid = new Random().nextInt();
try
{
inform.setOp(DHCPConstants.BOOTREQUEST);
inform.setHtype(DHCPConstants.HTYPE_ETHER);
inform.setHlen((byte) 6);
inform.setHops((byte) 0);
inform.setXid(xid);
inform.setSecs((short) 0);
inform.setFlags((short) 0);
inform.setYiaddr(InetAddress.getByAddress(zeroIPAddress));
inform.setSiaddr(InetAddress.getByAddress(zeroIPAddress));
inform.setGiaddr(InetAddress.getByAddress(zeroIPAddress));
inform.setChaddr(macAddress);
inform.setDhcp(true);
inform.setDHCPMessageType(DHCPConstants.DHCPINFORM);
dhcpOpts[0] = new DHCPOption(
DHCPConstants.DHO_DHCP_PARAMETER_REQUEST_LIST,
new byte[] {option});
inform.setOptions(dhcpOpts);
Enumeration<NetworkInterface> en =
NetworkInterface.getNetworkInterfaces();
while(en.hasMoreElements())
{
NetworkInterface iface = en.nextElement();
Enumeration<InetAddress> enAddr = iface.getInetAddresses();
while(enAddr.hasMoreElements())
{
InetAddress addr = enAddr.nextElement();
/* just take IPv4 address */
if(addr instanceof Inet4Address)
{
NetworkAddressManagerService netaddr =
ProvisioningDiscoveryDHCPActivator.
getNetworkAddressManagerService();
if(!addr.isLoopbackAddress())
{
macAddress = netaddr.getHardwareAddress(iface);
DHCPPacket p = inform.clone();
p.setCiaddr(addr);
p.setChaddr(macAddress);
byte msg[] = inform.serialize();
DatagramPacket pkt = new DatagramPacket(msg,
msg.length,
InetAddress.getByAddress(broadcastIPAddr),
port - 1);
socket.send(pkt);
msg = null;
pkt = null;
p = null;
}
}
}
}
/* now see if we receive DHCP ACK response and if it contains
* our custom option
*/
boolean found = false;
try
{
DatagramPacket pkt2 = new DatagramPacket(new byte[1500], 1500);
while(!found)
{
/* we timeout after 5 seconds if no DHCP response are
* received
*/
socket.receive(pkt2);
DHCPPacket dhcp = DHCPPacket.getPacket(pkt2);
if(dhcp.getXid() != xid)
{
continue;
}
DHCPOption optProvisioning = dhcp.getOption(option);
/* notify */
if(optProvisioning != null)
{
found = true;
return new String(optProvisioning.getValue());
}
}
}
catch(SocketTimeoutException est)
{
logger.warn("Timeout, no DHCP answer received", est);
}
}
catch(Exception e)
{
logger.warn("Exception occurred during DHCP discover", e);
}
return null;
}
/**
* Thread entry point. It runs <tt>discoverProvisioningURL</tt> in a
* separate thread.
*/
public void run()
{
String url = discoverProvisioningURL();
if(url != null)
{
/* as we run in an asynchronous manner, notify the listener */
DiscoveryEvent evt = new DiscoveryEvent(this, url);
for(DiscoveryListener listener : listeners)
{
listener.notifyProvisioningURL(evt);
}
}
}
/**
* Add a listener that will be notified when the
* <tt>discoverProvisioningURL</tt> has finished.
*
* @param listener <tt>ProvisioningListener</tt> to add
*/
public void addDiscoveryListener(DiscoveryListener listener)
{
if(!listeners.contains(listener))
{
listeners.add(listener);
}
}
/**
* Add a listener that will be notified when the
* <tt>discoverProvisioningURL</tt> has finished.
*
* @param listener <tt>ProvisioningListener</tt> to add
*/
public void removeDiscoveryListener(DiscoveryListener listener)
{
if(listeners.contains(listener))
{
listeners.remove(listener);
}
}
}

@ -0,0 +1,106 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.provdisc.dhcp;
import org.osgi.framework.*;
import net.java.sip.communicator.service.provdisc.*;
import net.java.sip.communicator.service.netaddr.*;
import net.java.sip.communicator.util.*;
/**
* Implements <tt>BundleActivator</tt> for the DHCP provisioning bundle.
*
* @author Sebastien Vincent
*/
public class ProvisioningDiscoveryDHCPActivator
implements BundleActivator
{
/**
* <tt>Logger</tt> used by this <tt>DHCPProvisioningDiscoveryActivator</tt>
* instance for logging output.
*/
private final Logger logger
= Logger.getLogger(ProvisioningDiscoveryDHCPActivator.class);
/**
* DHCP provisioning service.
*/
private static ProvisioningDiscoveryServiceDHCPImpl provisioningService =
new ProvisioningDiscoveryServiceDHCPImpl();
/**
* A reference to the currently valid {@link NetworkAddressManagerService}.
*/
private static NetworkAddressManagerService
networkAddressManagerService = null;
/**
* Bundle context from OSGi.
*/
private static BundleContext bundleContext = null;
/**
* Starts the DHCP provisioning service
*
* @param bundleContext the <tt>BundleContext</tt> as provided by the OSGi
* framework.
* @throws Exception if anything goes wrong
*/
public void start(BundleContext bundleContext)
throws Exception
{
if (logger.isDebugEnabled())
logger.debug("DHCP provisioning discovery Service [STARTED]");
bundleContext.registerService(
ProvisioningDiscoveryService.class.getName(),
provisioningService,
null);
ProvisioningDiscoveryDHCPActivator.bundleContext = bundleContext;
if (logger.isDebugEnabled())
logger.debug("DHCP provisioning discovery Service [REGISTERED]");
}
/**
* Stops the DHCP provisioning service.
*
* @param bundleContext the <tt>BundleContext</tt> as provided by the OSGi
* framework.
* @throws Exception if anything goes wrong
*/
public void stop(BundleContext bundleContext) throws Exception
{
ProvisioningDiscoveryDHCPActivator.bundleContext = null;
if (logger.isInfoEnabled())
logger.info("DHCP provisioning discovery Service ...[STOPPED]");
}
/**
* Returns a reference to a NetworkAddressManagerService implementation
* currently registered in the bundle context or null if no such
* implementation was found.
*
* @return a currently valid implementation of the
* NetworkAddressManagerService .
*/
public static NetworkAddressManagerService getNetworkAddressManagerService()
{
if(networkAddressManagerService == null)
{
ServiceReference confReference
= bundleContext.getServiceReference(
NetworkAddressManagerService.class.getName());
networkAddressManagerService = (NetworkAddressManagerService)
bundleContext.getService(confReference);
}
return networkAddressManagerService;
}
}

@ -0,0 +1,109 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.provdisc.dhcp;
import net.java.sip.communicator.service.provdisc.*;
import net.java.sip.communicator.service.provdisc.event.*;
import net.java.sip.communicator.util.*;
/**
* Class that uses DHCP to retrieve provisioning URL. Basically it sends a
* DHCPINFORM message with a custom option code in parameters list.
*
* Note that DHCP server have to understand this option and thus configured to
* answer with a HTTP/HTTPS URL.
*
* @author Sebastien Vincent
*/
public class ProvisioningDiscoveryServiceDHCPImpl
extends AbstractProvisioningDiscoveryService
implements DiscoveryListener
{
/**
* Logger.
*/
private final Logger logger
= Logger.getLogger(ProvisioningDiscoveryServiceDHCPImpl.class);
/**
* DHCP provisioning discover object.
*/
private DHCPProvisioningDiscover discover = null;
/**
* Name of the method used to retrieve provisioning URL.
*/
private static final String METHOD_NAME = "DHCP";
/**
* Get the name of the method name used to retrieve provisioning URL.
*
* @return method name
*/
public String getMethodName()
{
return METHOD_NAME;
}
/**
* Constructor.
*/
public ProvisioningDiscoveryServiceDHCPImpl()
{
try
{
discover = new DHCPProvisioningDiscover(6768, (byte)120);
discover.addDiscoveryListener(this);
}
catch(Exception e)
{
logger.warn("Cannot create DHCP client socket", e);
}
}
/**
* Launch a discovery for a provisioning URL. This method is synchronous and
* may block for some time. Note that you don't have to call
* <tt>startDiscovery</tt> method prior to this one to retrieve URL.
*
* @return provisioning URL
*/
public String discoverURL()
{
if(discover != null)
{
return discover.discoverProvisioningURL();
}
return null;
}
/**
* Launch a discovery for a provisioning URL by sending a DHCP Inform
* with parameter list option containing a custom option code.
*
* This method is asynchronous, the response will be notified to any
* <tt>ProvisioningListener</tt> registered.
*/
public void startDiscovery()
{
if(discover != null)
{
new Thread(discover).start();
}
}
/**
* Notify the provisioning URL.
*
* @param event provisioning event
*/
public void notifyProvisioningURL(DiscoveryEvent event)
{
fireDiscoveryEvent(event);
}
}

@ -0,0 +1,11 @@
Bundle-Activator: net.java.sip.communicator.impl.provdisc.dhcp.ProvisioningDiscoveryDHCPActivator
Bundle-Name: DHCP provisioning discovery
Bundle-Description: A bundle providing support for DHCP provisioning discovery
Bundle-Vendor: sip-communicator.org
Bundle-Version: 0.0.1
System-Bundle: yes
Import-Package: org.osgi.framework,
net.java.sip.communicator.service.provdisc,
net.java.sip.communicator.service.provdisc.event,
net.java.sip.communicator.service.netaddr,
net.java.sip.communicator.util

@ -0,0 +1,800 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.provisioning;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.net.ssl.*;
import javax.swing.*;
import net.java.sip.communicator.service.configuration.*;
import net.java.sip.communicator.service.credentialsstorage.*;
import net.java.sip.communicator.service.certificate.*;
import net.java.sip.communicator.service.netaddr.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.provdisc.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;
import org.osgi.framework.*;
/**
* Activator the provisioning system. It will gather provisioning URL depending
* on the configuration (DHCP, manual, ...), retrieve configuration file and
* push properties to the <tt>ConfigurationService</tt>.
*/
public class ProvisioningPluginActivator
implements BundleActivator
{
/**
* Logger of this class
*/
private static final Logger logger
= Logger.getLogger(ProvisioningPluginActivator.class);
/**
* The current BundleContext.
*/
private static BundleContext bundleContext = null;
/**
* Name of the provisioning URL in the configuration service.
*/
private static final String PROPERTY_PROVISIONING_URL
= "net.java.sip.communicator.plugin.provisioning.URL";
/**
* Name of the username for the HTTP authentication.
*/
private static final String PROPERTY_HTTP_USERNAME
= "net.java.sip.communicator.plugin.provisioning.auth.http.USERNAME";
/**
* Name of the password for the HTTP authentication.
*/
private static final String PROPERTY_HTTP_PASSWORD
= "net.java.sip.communicator.plugin.provisioning.auth.http";
/**
* Name of the provisioning username in the configuration service
* authentication).
*/
private static final String PROPERTY_PROVISIONING_USERNAME
= "net.java.sip.communicator.plugin.provisioning.auth.access.USERNAME";
/**
* Name of the provisioning password in the configuration service (HTTP
* authentication).
*/
private static final String PROPERTY_PROVISIONING_PASSWORD
= "net.java.sip.communicator.plugin.provisioning.auth.access";
/**
* Name of the property that contains the provisioning method (i.e. DHCP,
* DNS, manual, ...).
*/
private static final String PROVISIONING_METHOD_PROP
= "net.java.sip.communicator.plugin.provisioning.METHOD";
/**
* A reference to the ConfigurationService implementation instance that
* is currently registered with the bundle context.
*/
private static ConfigurationService configurationService = null;
/**
* A reference to the CredentialsStorageService implementation instance
* that is registered with the bundle context.
*/
private static CredentialsStorageService credentialsService = null;
/**
* The service we use to interact with user for SSL certificate stuff.
*/
private static CertificateVerificationService certVerification = null;
/**
* A reference to the NetworkAddressManagerService implementation instance
* that is registered with the bundle context.
*/
private static NetworkAddressManagerService netaddrService = null;
/**
* User credentials to access URL (protected by HTTP authentication) if any.
*/
private static UserCredentials userCredentials = null;
/**
* User credentials that user have to provide to the provisioning server
* if any.
*/
private static UserCredentials provCredentials = null;
/**
* HTTP method to request a page.
*/
private String method = "POST";
/**
* Starts this bundle
*
* @param bundleContext BundleContext
* @throws Exception if anything goes wrong during the start of the bundle
*/
public void start(BundleContext bundleContext) throws Exception
{
String url = null;
if (logger.isDebugEnabled())
logger.debug("Provisioning discovery [STARTED]");
ProvisioningPluginActivator.bundleContext = bundleContext;
String method = getConfigurationService().getString(
PROVISIONING_METHOD_PROP);
if(method == null || method.equals("NONE"))
{
return;
}
ServiceReference serviceReferences[] = bundleContext.
getServiceReferences(ProvisioningDiscoveryService.class.getName(),
null);
/* search the provisioning discovery implementation that correspond to
* the method name
*/
if(serviceReferences != null)
{
for(ServiceReference ref : serviceReferences)
{
ProvisioningDiscoveryService provdisc =
(ProvisioningDiscoveryService)bundleContext.getService(ref);
if(provdisc.getMethodName().equals(method))
{
/* may block for sometime depending on the method used */
url = provdisc.discoverURL();
break;
}
}
}
if(url == null)
{
/* try to see if provisioning URL is stored in properties */
url = getConfigurationService().getString(
PROPERTY_PROVISIONING_URL);
}
if(url != null)
{
File file = retrieveConfigurationFile(url);
if(file != null)
{
updateConfiguration(file);
/* store the provisioning URL in local configuration in case
* the provisioning discovery failed (DHCP/DNS unavailable, ...)
*/
getConfigurationService().setProperty(
PROPERTY_PROVISIONING_URL, url);
}
}
if (logger.isDebugEnabled())
logger.debug("Provisioning discovery [REGISTERED]");
}
/**
* Stops this bundle
*
* @param bundleContext BundleContext
* @throws Exception if anything goes wrong during the stop of the bundle
*/
public void stop(BundleContext bundleContext) throws Exception
{
ProvisioningPluginActivator.bundleContext = null;
if (logger.isDebugEnabled())
logger.debug("Provisioning discovery [STOPPED]");
}
/**
* Configure HTTP connection to provide HTTP authentication and SSL
* truster.
*
* @param url provisioning URL
* @param connection the <tt>URLConnection</tt>
*/
private void configureHTTPConnection(URL url, HttpURLConnection connection)
{
try
{
connection.setRequestMethod(method);
if(method.equals("POST"))
{
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
}
if(connection instanceof HttpsURLConnection)
{
CertificateVerificationService vs =
getCertificateVerificationService();
int port = url.getPort();
/* if we do not specify port in the URL (http://domain.org:port)
* we have to set up the default port of HTTP (80) or
* HTTPS (443).
*/
if(port == -1)
{
if(url.getProtocol().equals("http"))
{
port = 80;
}
else if(url.getProtocol().equals("https"))
{
port = 443;
}
}
((HttpsURLConnection)connection).setSSLSocketFactory(
vs.getSSLContext(
url.getHost(), port).getSocketFactory());
}
}
catch (Exception e)
{
logger.warn("Failed to initialize secure connection", e);
}
Authenticator.setDefault(new Authenticator()
{
protected PasswordAuthentication getPasswordAuthentication()
{
// if there is something save return it
ConfigurationService config = getConfigurationService();
CredentialsStorageService credStorage =
getCredentialsStorageService();
String uName
= (String) config.getProperty(
PROPERTY_HTTP_USERNAME);
if(uName != null)
{
String pass = credStorage.loadPassword(
PROPERTY_HTTP_PASSWORD);
if(pass != null)
return new PasswordAuthentication(uName,
pass.toCharArray());
}
if(userCredentials != null)
{
return new PasswordAuthentication(
userCredentials.getUserName(),
userCredentials.getPassword());
}
else
{
return null;
}
}
});
}
/**
* Handle authentication with the provisioning server.
*/
private void handleProvisioningAuth()
{
ConfigurationService configService = getConfigurationService();
CredentialsStorageService credService =
getCredentialsStorageService();
String username = configService.getString(
PROPERTY_PROVISIONING_USERNAME);
String password = credService.loadPassword(
PROPERTY_PROVISIONING_PASSWORD);
if(username != null && password != null)
{
/* we have already the credentials stored so return them */
provCredentials = new UserCredentials();
provCredentials.setUserName(username);
provCredentials.setPassword(password.toCharArray());
provCredentials.setPasswordPersistent(true);
return;
}
AuthenticationWindow authWindow = new AuthenticationWindow(
"provisioning", true, null);
authWindow.setVisible(true);
if(!authWindow.isCanceled())
{
provCredentials = new UserCredentials();
provCredentials.setUserName(authWindow.getUserName());
provCredentials.setPassword(authWindow.getPassword());
provCredentials.setPasswordPersistent(authWindow.isRememberPassword());
if(provCredentials.getUserName() == null)
{
provCredentials = null;
}
}
else
{
provCredentials = null;
}
}
/**
* Retrieve configuration file from provisioning URL.
* This method is blocking until configuration file is retrieved from the
* network or if an exception happen
*
* @param url provisioning URL
* @return provisioning file downloaded
*/
private File retrieveConfigurationFile(String url)
{
File tmpFile = null;
try
{
String arg = null;
String args[] = null;
final File temp = File.createTempFile("provisioning",
".properties");
tmpFile = temp;
if(url.contains("?"))
{
/* do not handle URL of type http://domain/index.php? (no
* parameters)
*/
if((url.indexOf('?') + 1) != url.length())
{
arg = url.substring(url.indexOf('?') + 1);
args = arg.split("&");
}
url = url.substring(0, url.indexOf('?'));
}
URL u = new URL(url);
URLConnection uc = u.openConnection();
OutputStreamWriter out = null;
if(uc instanceof HttpURLConnection)
{
configureHTTPConnection(u, (HttpURLConnection)uc);
((HttpURLConnection)uc).setInstanceFollowRedirects(false);
uc.setDoInput(true);
uc.setDoOutput(true);
out = new OutputStreamWriter(uc.getOutputStream());
/* send out (via GET or POST) */
StringBuffer content = new StringBuffer();
InetAddress ipaddr = getNetworkAddressManagerService().
getLocalHost(InetAddress.getByName(u.getHost()));
if(args != null && args.length > 0)
{
for(String s : args)
{
if(s.equals("username"))
{
if(provCredentials == null)
{
handleProvisioningAuth();
}
if(provCredentials == null)
{
return null;
}
content.append("username=" +
URLEncoder.encode(
provCredentials.getUserName(),
"UTF-8"));
}
else if(s.equals("password"))
{
if(provCredentials == null)
{
handleProvisioningAuth();
}
if(provCredentials == null)
{
return null;
}
content.append("&password=" +
URLEncoder.encode(
provCredentials.
getPasswordAsString(),
"UTF-8"));
}
else if(s.equals("osname"))
{
content.append("&osname=" + URLEncoder.encode(
System.getProperty("os.name"), "UTF-8"));
}
else if(s.equals("build"))
{
content.append("&build=" + URLEncoder.encode(
System.getProperty("sip-communicator.version"),
"UTF-8"));
}
else if(s.equals("ipaddr"))
{
content.append("&ipaddr=" + URLEncoder.encode(
ipaddr.getHostAddress(), "UTF-8"));
}
else if(s.equals("hwaddr"))
{
String hwaddr = null;
if(ipaddr != null)
{
/* find the hardware address of the interface
* that has this IP address
*/
Enumeration<NetworkInterface> en =
NetworkInterface.getNetworkInterfaces();
while(en.hasMoreElements())
{
NetworkInterface iface = en.nextElement();
Enumeration<InetAddress> enInet =
iface.getInetAddresses();
while(enInet.hasMoreElements())
{
InetAddress inet = enInet.nextElement();
if(inet.equals(ipaddr))
{
byte hw[] =
getNetworkAddressManagerService().
getHardwareAddress(iface);
StringBuffer buf =
new StringBuffer();
for(byte h : hw)
{
int hi = h >= 0 ? h : h + 256;
String t = new String(
(hi <= 0xf) ? "0" : "");
t += Integer.toHexString(hi);
buf.append(t);
buf.append("-");
}
buf.deleteCharAt(buf.length() - 1);
hwaddr = buf.toString();
content.append("&hwaddr=" +
URLEncoder.encode(
hwaddr, "UTF-8"));
break;
}
}
}
}
}
}
}
out.write(content.toString());
out.flush();
int responseCode = ((HttpURLConnection)uc).getResponseCode();
if(responseCode == HttpURLConnection.HTTP_UNAUTHORIZED)
{
AuthenticationWindow authWindow = new AuthenticationWindow(
u.getHost(), true, null);
authWindow.setVisible(true);
userCredentials = new UserCredentials();
userCredentials.setUserName(authWindow.getUserName());
userCredentials.setPassword(authWindow.getPassword());
userCredentials.setPasswordPersistent(
authWindow.isRememberPassword());
if(userCredentials.getUserName() == null)
{
userCredentials = null;
}
else
{
tmpFile.delete();
return retrieveConfigurationFile(url);
}
}
else if(responseCode == HttpURLConnection.HTTP_MOVED_PERM ||
responseCode == HttpURLConnection.HTTP_MOVED_TEMP)
{
String loc =
((HttpURLConnection)uc).getHeaderField("Location");
if(loc != null && (loc.startsWith("http://") ||
loc.startsWith("https://")))
{
tmpFile.delete();
/* TODO detect loops */
return retrieveConfigurationFile(loc);
}
}
else if(responseCode == HttpURLConnection.HTTP_OK)
{
if(userCredentials != null &&
userCredentials.getUserName() != null &&
userCredentials.isPasswordPersistent())
{
// if save password is checked save the pass
getConfigurationService().setProperty(
PROPERTY_HTTP_USERNAME,
userCredentials.getUserName());
getCredentialsStorageService().storePassword(
PROPERTY_HTTP_PASSWORD,
userCredentials.getPasswordAsString());
}
if(provCredentials != null &&
provCredentials.getUserName() != null &&
provCredentials.isPasswordPersistent())
{
getConfigurationService().setProperty(
PROPERTY_PROVISIONING_USERNAME,
provCredentials.getUserName());
getCredentialsStorageService().storePassword(
PROPERTY_PROVISIONING_PASSWORD,
provCredentials.getPasswordAsString());
}
}
}
else
{
return null;
}
InputStream in = uc.getInputStream();
// Chain a ProgressMonitorInputStream to the
// URLConnection's InputStream
final ProgressMonitorInputStream pin
= new ProgressMonitorInputStream(null, u.toString(), in);
// Set the maximum value of the ProgressMonitor
ProgressMonitor pm = pin.getProgressMonitor();
pm.setMaximum(uc.getContentLength());
final BufferedOutputStream bout
= new BufferedOutputStream(new FileOutputStream(temp));
try
{
int read = -1;
byte[] buff = new byte[1024];
while((read = pin.read(buff)) != -1)
{
bout.write(buff, 0, read);
}
pin.close();
bout.flush();
bout.close();
out.close();
return temp;
}
catch (Exception e)
{
logger.error("Error saving", e);
try
{
pin.close();
bout.close();
out.close();
}
catch (Exception e1)
{
}
return null;
}
}
catch (Exception e)
{
if (logger.isInfoEnabled())
logger.info("Error retrieving provisioning file!", e);
tmpFile.delete();
return null;
}
}
/**
* Update configuration with properties retrieved from provisioning URL.
*
* @param file provisioning file
*/
private void updateConfiguration(final File file)
{
Properties fileProps = new Properties();
InputStream in = null;
try
{
in = new BufferedInputStream(new FileInputStream(file));
fileProps.load(in);
Iterator<Map.Entry<Object, Object> > it
= fileProps.entrySet().iterator();
while(it.hasNext())
{
Map.Entry<Object, Object> entry = it.next();
String key = (String)entry.getKey();
Object value = entry.getValue();
if(value instanceof String)
{
if(((String)value).equals("${null}"))
{
getConfigurationService().removeProperty(key);
continue;
}
}
/* password => credentials storage service */
if(key.endsWith(".PASSWORD"))
{
getCredentialsStorageService().storePassword(
key.substring(0, key.lastIndexOf(".")),
(String)value);
}
else
{
getConfigurationService().setProperty(key, value);
}
}
/* save the "new" configuration */
getConfigurationService().storeConfiguration();
try
{
getConfigurationService().reloadConfiguration();
}
catch(Exception e)
{
logger.error("Cannot reload configuration");
}
}
catch(IOException e)
{
logger.warn("Error during load of provisioning file");
}
finally
{
try
{
in.close();
file.delete();
}
catch(IOException e)
{
}
}
}
/**
* Return the certificate verification service impl.
* @return the CertificateVerification service.
*/
private static CertificateVerificationService
getCertificateVerificationService()
{
if(certVerification == null)
{
ServiceReference certVerifyReference
= bundleContext.getServiceReference(
CertificateVerificationService.class.getName());
if(certVerifyReference != null)
certVerification
= (CertificateVerificationService)bundleContext.getService(
certVerifyReference);
}
return certVerification;
}
/**
* Returns a reference to a ConfigurationService implementation currently
* registered in the bundle context or null if no such implementation was
* found.
*
* @return a currently valid implementation of the ConfigurationService.
*/
public static ConfigurationService getConfigurationService()
{
if (configurationService == null)
{
ServiceReference confReference
= bundleContext.getServiceReference(
ConfigurationService.class.getName());
configurationService
= (ConfigurationService)bundleContext.getService(confReference);
}
return configurationService;
}
/**
* Returns a reference to a CredentialsStorageService implementation
* currently registered in the bundle context or null if no such
* implementation was found.
*
* @return a currently valid implementation of the
* CredentialsStorageService.
*/
public static CredentialsStorageService getCredentialsStorageService()
{
if (credentialsService == null)
{
ServiceReference credentialsReference
= bundleContext.getServiceReference(
CredentialsStorageService.class.getName());
credentialsService
= (CredentialsStorageService) bundleContext
.getService(credentialsReference);
}
return credentialsService;
}
/**
* Returns a reference to a NetworkAddressManagerService implementation
* currently registered in the bundle context or null if no such
* implementation was found.
*
* @return a currently valid implementation of the
* NetworkAddressManagerService.
*/
public static NetworkAddressManagerService getNetworkAddressManagerService()
{
if (netaddrService == null)
{
ServiceReference netaddrReference
= bundleContext.getServiceReference(
NetworkAddressManagerService.class.getName());
netaddrService
= (NetworkAddressManagerService) bundleContext
.getService(netaddrReference);
}
return netaddrService;
}
}

@ -0,0 +1,17 @@
Bundle-Activator: net.java.sip.communicator.plugin.provisioning.ProvisioningPluginActivator
Bundle-Name: ProvisioningPlugin
Bundle-Description: A bundle that implements the Provisioning Plugin Package.
Bundle-Vendor: sip-communicator.org
Bundle-Version: 0.0.1
System-Bundle: yes
Import-Package: org.osgi.framework,
net.java.sip.communicator.service.configuration,
net.java.sip.communicator.service.credentialsstorage,
net.java.sip.communicator.service.protocol,
net.java.sip.communicator.service.provdisc,
net.java.sip.communicator.service.certificate,
net.java.sip.communicator.service.netaddr,
net.java.sip.communicator.util,
net.java.sip.communicator.util.swing,
javax.net.ssl,
javax.swing,

@ -147,6 +147,7 @@ protected void addCallPeer(T callPeer)
* also we can obtain the reason for the <tt>CallPeerChangeEvent</tt> if
* any. Use the event as cause for the call state change event..
*/
@SuppressWarnings("unchecked")
private void removeCallPeer(CallPeerChangeEvent evt)
{
T callPeer = (T)evt.getSourceCallPeer();

@ -0,0 +1,92 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.provdisc;
import java.util.*;
import net.java.sip.communicator.service.provdisc.event.*;
/**
* Abstract base class of ProvisioningDiscoveryService that ease implementation
*
* @author seb
*
*/
public abstract class AbstractProvisioningDiscoveryService
implements ProvisioningDiscoveryService
{
/**
* List of <tt>ProvisioningListener</tt> that will be notified when
* a provisioning URL is retrieved.
*/
private List<DiscoveryListener> listeners =
new ArrayList<DiscoveryListener>();
/**
* Get the name of the method name used to retrieve provisioning URL.
*
* @return method name
*/
public abstract String getMethodName();
/**
* Launch a discovery for a provisioning URL.
*
* This method is asynchronous, the response will be notified to any
* <tt>ProvisioningListener</tt> registered.
*/
public abstract void startDiscovery();
/**
* Launch a discovery for a provisioning URL. This method is synchronous and
* may block for some time.
*
* @return provisioning URL
*/
public abstract String discoverURL();
/**
* Add a listener that will be notified when the
* <tt>discoverProvisioningURL</tt> has finished.
*
* @param listener <tt>ProvisioningListener</tt> to add
*/
public void addDiscoveryListener(DiscoveryListener listener)
{
if(!listeners.contains(listener))
{
listeners.add(listener);
}
}
/**
* Add a listener that will be notified when the
* <tt>discoverProvisioningURL</tt> has finished.
*
* @param listener <tt>ProvisioningListener</tt> to add
*/
public void removeDiscoveryListener(DiscoveryListener listener)
{
if(listeners.contains(listener))
{
listeners.remove(listener);
}
}
/**
* Notify all listeners about a <tt>DiscoveryEvent</tt>.
*
* @param event <tt>DiscoveryEvent</tt> that contains provisioning URL
*/
public void fireDiscoveryEvent(DiscoveryEvent event)
{
for(DiscoveryListener listener : listeners)
{
listener.notifyProvisioningURL(event);
}
}
}

@ -0,0 +1,58 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.provdisc;
import net.java.sip.communicator.service.provdisc.event.*;
/**
* Service that allow to retrieve a provisioning URL to configure
* SIP Communicator. Implementations (not exhaustive) could use DHCP,
* DNS (A, AAAA, SRV, TXT) or mDNS (Bonjour).
*
* @author Sebastien Vincent
*/
public interface ProvisioningDiscoveryService
{
/**
* Get the name of the method name used to retrieve provisioning URL.
*
* @return method name
*/
public String getMethodName();
/**
* Launch a discovery for a provisioning URL.
*
* This method is asynchronous, the response will be notified to any
* <tt>ProvisioningListener</tt> registered.
*/
public void startDiscovery();
/**
* Launch a discovery for a provisioning URL. This method is synchronous and
* may block for some time.
*
* @return provisioning URL
*/
public String discoverURL();
/**
* Add a listener that will be notified when the
* <tt>startDiscovery</tt> has finished.
*
* @param listener <tt>ProvisioningListener</tt> to add
*/
public void addDiscoveryListener(DiscoveryListener listener);
/**
* Add a listener that will be notified when the
* <tt>discoverProvisioningURL</tt> has finished.
*
* @param listener <tt>ProvisioningListener</tt> to add
*/
public void removeDiscoveryListener(DiscoveryListener listener);
}

@ -0,0 +1,49 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.provdisc.event;
import java.util.*;
/**
* Event representing that a provisioning URL has been retrieved.
*
* @author Sebastien Vincent
*/
public class DiscoveryEvent extends EventObject
{
/**
* Serial version UID.
*/
private static final long serialVersionUID = 0L;
/**
* Provisioning URL.
*/
private String url = null;
/**
* Constructor.
*
* @param source object that have created this event
* @param url provisioning URL
*/
public DiscoveryEvent(Object source, String url)
{
super(source);
this.url = url;
}
/**
* Get the provisioning URL.
*
* @return provisioning URL
*/
public String getProvisioningURL()
{
return url;
}
}

@ -0,0 +1,25 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.provdisc.event;
import java.util.*;
/**
* Listener that will be notified when a provisioning URL is retrieved by the
* <tt>ProvisioningDiscoveryService</tt>.
*
* @author Sebastien Vincent
*/
public interface DiscoveryListener extends EventListener
{
/**
* Notify the provisioning URL.
*
* @param event provisioning event
*/
public void notifyProvisioningURL(DiscoveryEvent event);
}

@ -0,0 +1,7 @@
Bundle-Name: Provisioning Discovery Service
Bundle-Description: Provisioning Discovery Service.
Bundle-Vendor: sip-communicator.org
Bundle-Version: 0.0.1
System-Bundle: yes
Export-Package: net.java.sip.communicator.service.provdisc,
net.java.sip.communicator.service.provdisc.event

@ -126,7 +126,12 @@ public AuthenticationWindow(String server,
{
this.server = server;
Image logoImage = icon.getImage();
Image logoImage = null;
if(icon != null)
{
logoImage = icon.getImage();
}
if(!isUserNameEditable)
this.uinValue = new JLabel();

Loading…
Cancel
Save