Commit 528f8cd8 authored by Dave Cridland's avatar Dave Cridland Committed by Guus der Kinderen

OF-1309 Authenticate based on domain pairs

Openfire considers that if a session has authenticated as A, and has
authenticated to B, then the session is already authorized to send stanzas
from A to B. This is not always the case.

This patch stores domain pairs (encapsulated as a DomainPair object) for a
session, and always authenticates if it has previously not requested
authorization for this domain pair.

This should be sufficient to fix OF-1309, but testing is tricky.
parent b2d5616f
package org.jivesoftware.openfire.session;
/**
* Holds a (possibly authenticated) domain pair.
*/
public class DomainPair {
private final String local;
private final String remote;
public DomainPair(String local, String remote) {
this.local = local;
this.remote = remote;
}
public int hashCode() {
return toString().hashCode();
}
public boolean equals(Object other) {
if (other instanceof DomainPair) {
DomainPair domainPair = (DomainPair)other;
return domainPair.local.equals(this.local) && domainPair.remote.equals(this.remote);
}
return false;
}
public String toString() {
return "{" + local + " -> " + remote + "}";
}
public String getLocal() {
return local;
}
public String getRemote() {
return remote;
}
}
......@@ -88,6 +88,7 @@ public class LocalOutgoingServerSession extends LocalServerSession implements Ou
private Collection<String> authenticatedDomains = new HashSet<>();
private final Collection<String> hostnames = new HashSet<>();
private OutgoingServerSocketReader socketReader;
private Collection<DomainPair> outgoingDomainPairs = new HashSet<>();
/**
* Authenticates the local domain to the remote domain. Once authenticated the remote domain can be expected to
......@@ -172,7 +173,7 @@ public class LocalOutgoingServerSession extends LocalServerSession implements Ou
if ( session != null )
{
log.debug( "A pre-existing session can be re-used. The session was established using server dialback so it is possible to do piggybacking to authenticate more domains." );
if ( session.getAuthenticatedDomains().contains( localDomain ) && session.getHostnames().contains( remoteDomain ) )
if ( session.checkOutgoingDomainPair(localDomain, remoteDomain) )
{
// Do nothing since the domain has already been authenticated.
log.debug( "Authentication successful (domain was already authenticated in the pre-existing session)." );
......@@ -609,6 +610,7 @@ public class LocalOutgoingServerSession extends LocalServerSession implements Ou
// Add the validated domain as an authenticated domain
addAuthenticatedDomain(localDomain);
addHostname(remoteDomain);
addOutgoingDomainPair(localDomain, remoteDomain);
return true;
}
return false;
......@@ -698,4 +700,13 @@ public class LocalOutgoingServerSession extends LocalServerSession implements Ou
// Nothing special to add
return null;
}
public void addOutgoingDomainPair(String localDomain, String remoteDomain) {
outgoingDomainPairs.add(new DomainPair(localDomain, remoteDomain));
}
@Override
public boolean checkOutgoingDomainPair(String localDomain, String remoteDomain) {
return outgoingDomainPairs.contains(new DomainPair(localDomain, remoteDomain));
}
}
......@@ -79,4 +79,6 @@ public interface OutgoingServerSession extends ServerSession {
* @return True if the subdomain was authenticated by the remote server.
*/
boolean authenticateSubdomain(String domain, String hostname);
boolean checkOutgoingDomainPair(String local, String remote);
}
......@@ -71,6 +71,11 @@ public class RemoteOutgoingServerSession extends RemoteSession implements Outgoi
return usingServerDialback == 1;
}
public boolean checkOutgoingDomainPair(String localDomain, String remoteDomain) {
ClusterTask task = new CheckOutgoingDomainPairTask(address, localDomain, remoteDomain);
return (Boolean)doSynchronousClusterTask(task);
}
RemoteSessionTask getRemoteSessionTask(RemoteSessionTask.Operation operation) {
return new OutgoingServerSessionTask(address, operation);
}
......@@ -167,4 +172,35 @@ public class RemoteOutgoingServerSession extends RemoteSession implements Outgoi
hostname = ExternalizableUtil.getInstance().readSafeUTF(in);
}
}
private static class CheckOutgoingDomainPairTask extends OutgoingServerSessionTask {
private String local;
private String remote;
public CheckOutgoingDomainPairTask() {
super();
}
protected CheckOutgoingDomainPairTask(JID address, String local, String remote) {
super(address, null);
this.local = local;
this.remote = remote;
}
public void run() {
result = ((OutgoingServerSession) getSession()).checkOutgoingDomainPair(local, remote);
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
ExternalizableUtil.getInstance().writeSafeUTF(out, local);
ExternalizableUtil.getInstance().writeSafeUTF(out, remote);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
local = ExternalizableUtil.getInstance().readSafeUTF(in);
remote = ExternalizableUtil.getInstance().readSafeUTF(in);
}
}
}
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