Skip to content

Commit

Permalink
WHACK-21: Add encryption option
Browse files Browse the repository at this point in the history
This commit adds an option to have the connection between the XMPP server and
the external component be encrypted. Note that this does not employ STARTTLS,
but 'natively' born encrypted sockets.
  • Loading branch information
guusdk committed Nov 29, 2016
1 parent 5b0c28c commit c3ddc1a
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class ExternalWeatherComponent {
public static void main(String[] args) {
// Create a manager for the external components that will connect to the server "localhost"
// at the port 5225
final ExternalComponentManager manager = new ExternalComponentManager("localhost", 5275);
final ExternalComponentManager manager = new ExternalComponentManager("localhost", 5275, false);
// Set the secret key for this component. The server must be using the same secret key
// otherwise the component won't be able to authenticate with the server. Check that the
// server has the property "component.external.secretKey" defined and that it is using the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
import org.jivesoftware.whack.ExternalComponentManager;
import org.xmpp.component.ComponentException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
* This is an example of how to make a component run as an external component. This examples
* requires that the server be running in the same computer where this application will run and
Expand All @@ -14,8 +22,8 @@ public class ExternalWeatherComponent {

public static void main(String[] args) {
// Create a manager for the external components that will connect to the server "localhost"
// at the port 5225
final ExternalComponentManager manager = new ExternalComponentManager("localhost", 5275);
// at the port 5276, using encryption.
final ExternalComponentManager manager = new ExternalComponentManager("localhost", 5276, true);
// Set the secret key for this component. The server must be using the same secret key
// otherwise the component won't be able to authenticate with the server. Check that the
// server has the property "component.external.secretKey" defined and that it is using the
Expand Down
28 changes: 26 additions & 2 deletions source/java/org/jivesoftware/whack/ExternalComponent.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
import org.xmpp.packet.Packet;
import org.xmpp.packet.StreamError;

import javax.net.ssl.SSLSocketFactory;

/**
* ExternalComponents are responsible for connecting and authenticating with a remote server and
* for sending and processing received packets. In fact, an ExternalComponent is a wrapper on a
Expand Down Expand Up @@ -107,6 +109,8 @@ public class ExternalComponent implements Component {
private String host;
private int port;

private boolean startEncrypted;

/**
* Pool of threads that are available for processing the requests.
*/
Expand Down Expand Up @@ -144,10 +148,29 @@ public ExternalComponent(Component component, ExternalComponentManager manager,
* @param subdomain the subdomain that this component will be handling.
* @throws ComponentException if an error happens during the connection and authentication steps.
*/
@Deprecated
public void connect(String host, int port, String subdomain) throws ComponentException {
connect(host,port,subdomain,false);
}

/**
* Generates a connection with the server and tries to authenticate. If an error occurs in any
* of the steps then a ComponentException is thrown.
*
* @param host the host to connect with.
* @param port the port to use.
* @param subdomain the subdomain that this component will be handling.
* @param startEncrypted true if sockets are started in TLS/SSL mode, otherwise false.
* @throws ComponentException if an error happens during the connection and authentication steps.
*/
public void connect(String host, int port, String subdomain, boolean startEncrypted) throws ComponentException {
try {
// Open a socket to the server
this.socket = new Socket();
if ( startEncrypted ) {
this.socket = SSLSocketFactory.getDefault().createSocket();
} else {
this.socket = new Socket();
}
socket.connect(new InetSocketAddress(host, port), manager.getConnectTimeout());
if (manager.getServerName() != null) {
this.domain = subdomain + "." + manager.getServerName();
Expand All @@ -159,6 +182,7 @@ public void connect(String host, int port, String subdomain) throws ComponentExc
// Keep these variables that will be used in case a reconnection is required
this.host= host;
this.port = port;
this.startEncrypted = startEncrypted;

try {
factory = XmlPullParserFactory.newInstance();
Expand Down Expand Up @@ -432,7 +456,7 @@ public void connectionLost() {
}
while (!isConnected && !shutdown) {
try {
connect(host, port, subdomain);
connect(host, port, subdomain, startEncrypted);
isConnected = true;
// It may be possible that while a new connection was being established the
// component was required to shutdown so in this case we need to close the new
Expand Down
23 changes: 22 additions & 1 deletion source/java/org/jivesoftware/whack/ExternalComponentManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ public class ExternalComponentManager implements ComponentManager {
* Port of the server used for establishing new connections.
*/
private int port;

/**
* Defines if sockets are started in encrypted mode ("old-style" TLS/SSL, non-STARTTLS
*/
private boolean startEncrypted;

/**
* Keeps the domain of the XMPP server. The domain may or may not match the host. The domain
* will be used mainly for the XMPP packets while the host is used mainly for creating
Expand Down Expand Up @@ -117,6 +123,7 @@ public ExternalComponentManager(String host) {
* @param host the IP address or name of the XMPP server to connect to (e.g. "example.com").
* @param port the port to connect on.
*/
@Deprecated
public ExternalComponentManager(String host, int port) {
if (host == null) {
throw new IllegalArgumentException("Host of XMPP server cannot be null");
Expand All @@ -130,6 +137,20 @@ public ExternalComponentManager(String host, int port) {
ComponentManagerFactory.setComponentManager(this);
}

public ExternalComponentManager(String host, int port, boolean startEncrypted) {
if (host == null) {
throw new IllegalArgumentException("Host of XMPP server cannot be null");
}
this.host = host;
this.port = port;
this.startEncrypted = startEncrypted;

createDummyLogger();

// Set this ComponentManager as the current component manager
ComponentManagerFactory.setComponentManager(this);
}

/**
* Sets a secret key for a sub-domain, for future use by a component
* connecting to the server. Keys are used as an authentication mechanism
Expand Down Expand Up @@ -218,7 +239,7 @@ public void addComponent(String subdomain, Component component, Integer port) th
componentsByDomain.put(subdomain, externalComponent);
components.put(component, externalComponent);
// Ask the ExternalComponent to connect with the remote server
externalComponent.connect(host, port, subdomain);
externalComponent.connect(host, port, subdomain, startEncrypted);
// Initialize the component
JID componentJID = new JID(null, externalComponent.getDomain(), null);
externalComponent.initialize(componentJID, this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public void start() {
String xmppServerHost = properties.getProperty("xmppServer.host");
port = properties.getProperty("xmppServer.port");
int xmppServerPort = (port == null ? 10015 : Integer.parseInt(port));
manager = new ExternalComponentManager(xmppServerHost, xmppServerPort);
manager = new ExternalComponentManager(xmppServerHost, xmppServerPort, false);
String serverDomain = properties.getProperty("xmppServer.domain");
if (serverDomain != null) {
manager.setServerName(serverDomain);
Expand Down

0 comments on commit c3ddc1a

Please sign in to comment.