Commit 8c9d8d79 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

server-2-server is now clusterable.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@8417 b35dd754-fafc-0310-a699-88a17e54d16e
parent 092b00b3
...@@ -17,12 +17,14 @@ import org.jivesoftware.openfire.XMPPServer; ...@@ -17,12 +17,14 @@ import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.session.LocalOutgoingServerSession; import org.jivesoftware.openfire.session.LocalOutgoingServerSession;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import org.jivesoftware.util.lock.LockManager;
import org.xmpp.packet.*; import org.xmpp.packet.*;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
/** /**
* An OutgoingSessionPromise provides an asynchronic way for sending packets to remote servers. * An OutgoingSessionPromise provides an asynchronic way for sending packets to remote servers.
...@@ -195,8 +197,16 @@ public class OutgoingSessionPromise implements RoutableChannelHandler { ...@@ -195,8 +197,16 @@ public class OutgoingSessionPromise implements RoutableChannelHandler {
private void sendPacket(Packet packet) throws Exception { private void sendPacket(Packet packet) throws Exception {
// Create a connection to the remote server from the domain where the packet has been sent // Create a connection to the remote server from the domain where the packet has been sent
boolean created = LocalOutgoingServerSession boolean created;
.authenticateDomain(packet.getFrom().getDomain(), packet.getTo().getDomain()); // Make sure that only one cluster node is creating the outgoing connection
Lock lock = LockManager.getLock(domain + "oss");
try {
lock.lock();
created = LocalOutgoingServerSession
.authenticateDomain(packet.getFrom().getDomain(), packet.getTo().getDomain());
} finally {
lock.unlock();
}
if (created) { if (created) {
// A connection to the remote server was created so get the route and send the packet // A connection to the remote server was created so get the route and send the packet
routingTable.routePacket(packet.getTo(), packet); routingTable.routePacket(packet.getTo(), packet);
......
...@@ -27,6 +27,9 @@ import org.jivesoftware.openfire.spi.BasicStreamIDFactory; ...@@ -27,6 +27,9 @@ import org.jivesoftware.openfire.spi.BasicStreamIDFactory;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import org.jivesoftware.util.StringUtils; import org.jivesoftware.util.StringUtils;
import org.jivesoftware.util.cache.Cache;
import org.jivesoftware.util.cache.CacheFactory;
import org.jivesoftware.util.lock.LockManager;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory; import org.xmlpull.v1.XmlPullParserFactory;
...@@ -37,6 +40,7 @@ import java.io.*; ...@@ -37,6 +40,7 @@ import java.io.*;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
/** /**
* Implementation of the Server Dialback method as defined by the RFC3920. * Implementation of the Server Dialback method as defined by the RFC3920.
...@@ -65,9 +69,11 @@ public class ServerDialback { ...@@ -65,9 +69,11 @@ public class ServerDialback {
*/ */
protected static String CHARSET = "UTF-8"; protected static String CHARSET = "UTF-8";
/** /**
* Secret key to be used for encoding and decoding keys used for authentication. * Cache (unlimited, never expire) that holds the secret key to be used for
* encoding and decoding keys used for authentication.
* Key: constant hard coded value, Value: random generated string
*/ */
private static final String secretKey = StringUtils.randomString(10); private static Cache<String, String> secretKeyCache;
private static XmlPullParserFactory FACTORY = null; private static XmlPullParserFactory FACTORY = null;
...@@ -78,6 +84,7 @@ public class ServerDialback { ...@@ -78,6 +84,7 @@ public class ServerDialback {
catch (XmlPullParserException e) { catch (XmlPullParserException e) {
Log.error("Error creating a parser factory", e); Log.error("Error creating a parser factory", e);
} }
secretKeyCache = CacheFactory.createCache("Secret Keys Cache");
} }
private Connection connection; private Connection connection;
...@@ -245,7 +252,7 @@ public class ServerDialback { ...@@ -245,7 +252,7 @@ public class ServerDialback {
*/ */
public boolean authenticateDomain(OutgoingServerSocketReader socketReader, String domain, public boolean authenticateDomain(OutgoingServerSocketReader socketReader, String domain,
String hostname, String id) { String hostname, String id) {
String key = AuthFactory.createDigest(id, secretKey); String key = AuthFactory.createDigest(id, getSecretkey());
Log.debug("OS - Sent dialback key to host: " + hostname + " id: " + id + " from domain: " + Log.debug("OS - Sent dialback key to host: " + hostname + " id: " + id + " from domain: " +
domain); domain);
...@@ -655,7 +662,7 @@ public class ServerDialback { ...@@ -655,7 +662,7 @@ public class ServerDialback {
// Verify the received key // Verify the received key
// Created the expected key based on the received ID value and the shared secret // Created the expected key based on the received ID value and the shared secret
String expectedKey = AuthFactory.createDigest(id, secretKey); String expectedKey = AuthFactory.createDigest(id, getSecretkey());
boolean verified = expectedKey.equals(key); boolean verified = expectedKey.equals(key);
// Send the result of the key verification // Send the result of the key verification
...@@ -673,5 +680,28 @@ public class ServerDialback { ...@@ -673,5 +680,28 @@ public class ServerDialback {
id); id);
return verified; return verified;
} }
/**
* Returns the secret key that was randomly generated. When running inside of a cluster
* the key will be unique to all cluster nodes.
*
* @return the secret key that was randomly generated.
*/
private static String getSecretkey() {
String key = "secretKey";
Lock lock = LockManager.getLock(key);
try {
lock.lock();
String secret = secretKeyCache.get(key);
if (secret == null) {
secret = StringUtils.randomString(10);
secretKeyCache.put(key, secret);
}
return secret;
}
finally {
lock.unlock();
}
}
} }
...@@ -73,6 +73,7 @@ public class DefaultLocalCacheStrategy implements CacheFactoryStrategy { ...@@ -73,6 +73,7 @@ public class DefaultLocalCacheStrategy implements CacheFactoryStrategy {
cacheNames.put("Connection Managers Sessions", "connManagerSessions"); cacheNames.put("Connection Managers Sessions", "connManagerSessions");
cacheNames.put("Incoming Server Sessions", "incServerSessions"); cacheNames.put("Incoming Server Sessions", "incServerSessions");
cacheNames.put("Sessions by Hostname", "sessionsHostname"); cacheNames.put("Sessions by Hostname", "sessionsHostname");
cacheNames.put("Secret Keys Cache", "secretKeys");
cacheProps.put("cache.fileTransfer.size", 128 * 1024l); cacheProps.put("cache.fileTransfer.size", 128 * 1024l);
cacheProps.put("cache.fileTransfer.expirationTime", 1000 * 60 * 10l); cacheProps.put("cache.fileTransfer.expirationTime", 1000 * 60 * 10l);
...@@ -122,6 +123,8 @@ public class DefaultLocalCacheStrategy implements CacheFactoryStrategy { ...@@ -122,6 +123,8 @@ public class DefaultLocalCacheStrategy implements CacheFactoryStrategy {
cacheProps.put("cache.incServerSessions.expirationTime", -1l); cacheProps.put("cache.incServerSessions.expirationTime", -1l);
cacheProps.put("cache.sessionsHostname.size", -1l); cacheProps.put("cache.sessionsHostname.size", -1l);
cacheProps.put("cache.sessionsHostname.expirationTime", -1l); cacheProps.put("cache.sessionsHostname.expirationTime", -1l);
cacheProps.put("cache.secretKeys.size", -1l);
cacheProps.put("cache.secretKeys.expirationTime", -1l);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment