How do I add SASL External to my openfire server (s2s communication)

Hello,

I would greatly appreciate any insight or help on this aspect.

I have installed and have been running Openfire servers (2 of them running 3.6.4) successfully for sometime now. For s2s communications it was unencrypted and now I want it encrypted, so I have been trying to add encryption.

i created certificates for both from StartSSL.com and added them into the servers succesffully. Looks like these certificates are being provided to each other.

I set the following properties:

xmpp.server.tls.enabled = true.

xmpp.server.certificate.verify=false. (Tried with true also and had teh same result).

xmpp.server.dialback = false.

The TLS negotiation goes well and succeeds but then the sending openfire server tries to use SASL and looks like the receiving openfire server does not offer EXTERNAL SASL.

I added the PLAIN,ANONYMOUS,EXTERNAL to the config file and that presents the EXTERNAL thing as an option to clients, however my s2s logs still complains that EXTERNAL is not being offerered.

What am I missing, is there some other configuration that I need to do or perform some other things to get this to accept the certificates…or is it not supported ?

Thanks

Nagesh

ok…hopefully someone can quickly make some recommendations…I am planning to document all my findings with respect to SSL including c2s and s2s shortly after I finish and make it one posting…so that people can find this information quickly.

Here is more information. After debugging for a long time , I found the following:

The Stream:features stanza from the servers are not offering any SASL mechanisms. so the stanza looks like :

stream:features
</stream:features>

So when the software in LocalOutgoingServerSession.java goes to perform EXTERNAL SASL , there are no features and hence does not go through with performing the EXTERNAL authentication as required.

This looks a bug because if we are dependent on the features being offered and by default if the server does not offer any features to perform TLS + SASL then it fails like expected. So I am still trying to figure out how to force the server to send out these features.

Is this a real bug ir is it just that I am not doing something right ??

On a different debugging session I tried TLS + Dialback just to see how that works.

The funny thing is that even though Dialback validation was successful, the connection is still not encrypted because the session gets closed prematurely according to the logs thus enabling only a s2s connection in the clear which can be sniffed easily on the wire.

Here is the log for example:

2010.05.27 06:30:23 LocalOutgoingServerSession: OS - TLS negotiation with dragon1.harriscess.com was successful
2010.05.27 06:30:23 LocalOutgoingServerSession: OS - Error, EXTERNAL SASL and SERVER DIALBACK were not offered by dragon1.harriscess.com
2010.05.27 06:30:23 LocalOutgoingServerSession: OS - Going to try connecting using server dialback with: dragon1.harriscess.com
2010.05.27 06:30:23 ServerDialback: OS - Trying to connect to dragon1.harriscess.com:5269(DNS lookup: dragon1.harriscess.com:5269)
2010.05.27 06:30:23 ServerDialback: OS - Connection to dragon1.harriscess.com:5269 successful
2010.05.27 06:30:23 ServerDialback: OS - Sent dialback key to host: dragon1.harriscess.com id: 4f051049 from domain: dragon3.harriscess.com
2010.05.27 06:30:23 Connect Socket[addr=/67.202.20.11,port=2336,localport=5269]
2010.05.27 06:30:23 ServerDialback: AS - Verifying key for host: dragon1.harriscess.com id: 4f051049
2010.05.27 06:30:23 ServerDialback: AS - Key was: VALID for host: dragon1.harriscess.com id: 4f051049
2010.05.27 06:30:23 ServerDialback: AS - Connection closed for host: dragon1.harriscess.com id: 4f051049
2010.05.27 06:30:23 Connection closed before session established
Socket[addr=/67.202.20.11,port=2336,localport=5269]
2010.05.27 06:30:23 ServerDialback: OS - Validation GRANTED from: dragon1.harriscess.com id: 4f051049 for domain: dragon3.harriscess.com

I’m seeing the same issues creating an encrpyted session between openfire and ejabberd.

Traffic that is from sessions opened by ejabberd is encrypted, but sessions opened by openfire fail. Communication works with dialback turned on, but only over a clear channel.

http://www.igniterealtime.org/community/message/203634#203634

Ok…here is an update…

I debugged this further and here is what I found:

If you look at Local Outgoing Session .java source code (around lines 473 where the features are being checked to see if EXTERNAL is being offered…) . This is where it breaks (alteast the symptom). The stream:features obtained at that point in the code does not have any features and hence does not execute the EXTERNAL SASL authentication.

I forced the software to execute External SASL by commenting to see what happens and everything works like a charm.

So I thought let me figure out where the stream is coming from.

I found a few more things:

  • In SASLAuthentication.java where getSASLMechanisms is invoked it checks to see if the connection is secure before offering EXTERNAL as a SASL mechanism for s2s connections.

This follows the specification , and hence we dont see SASL being offered in the first pass before TLS is negotiated.

Once TLS is negotiated, the interaction should be to open a new stream and offere the features that are valid for that stream. I know the TLS negotiation succeeds, but my suscpicion is :

  • Either the new stream with features is not being requested or if it is being requested the “is Secure” flag on the session is not set.

I dont have a good packet debugger to see the packets apart from wireshark …where once TLS is negotiated nothing is visible. So I am not able to pin-point where the exact issue is, but someone who is familiar with the code could probably find it in a jiffy and tell us what we are doing wrong…

This has been a great education going through a lot of debugging figuring out how s2s and c2s works…with certificates…especially.

Hopefully someone can help.

We are having the exact same issue as described in the original post.

Secure server to server is a requirement for us, and we may not be able to continue using Openfore unless a solution is found.

We also have problems with s2s communication (two openfire server) and signed certificates, it’s not possible to establish a secure connection.
As nobody could give some hints how to solve the problem I spent many hours to understand and debug the source code.
I think I found the reason why EXTERNAL isn’t sent as SASL mechanism :

In SASLAuthentication.getSASLMechanisms() the complete certificate chain of the current TLS connection is retrieved ( session.getConnection().getLocalCertificates())
Afterwards the following steps for every certificate of the chain are done:

  1. get certificate alias of the certificate from local keystore
  2. get chain size of the certificate from local keystore

As a signed certificate has a chain size of at least 2 the two steps above are ok for the first certificate (user certificate) but step 1 will fail for the root certificate because it is not possible to get an alias for it.
This failure leads to the problem that openfire assumes that a self-signed certificate is installed and therefore EXTERNAL-SASL is not possible.

From my point of view the two steps should/must be done only for the user’s certificate (not for the intermediate and root certificates).

I changed my openfire code and s2s communication works perfectly.

I believe Openfire 3.7.0 Beta has the same problem. Will these s2s problems ever be fixed in the official code?

This solution looks promising - would you be willing to post your modified code - i’m not much of a coder and would appreciate it greatly.

Thanks

I added this thread as a comment to a currently open issue ( OF-405 ) as it seems they are related, the patch to the source would be greatly appreciated so i can get my setup up an running with TLS.

Sorry for the delay, but I had a lot of other problems…

I did the following modification (I’m not a security expert and therefore I’m not sure if the modifications are security conform):

File: org.jivesoftware.openfire.net.SASLAuthentication

Method: getSASLMechanisms(LocalSession session)

if (session.isSecure()) {
boolean usingCASigned = false;
Certificate[] certificates = session.getConnection().getLocalCertificates();

            // don't check complete certificate chain, check only top level certificate
            try {
                if (!CertificateManager.isSelfSignedCertificate(SSLConfig.getKeyStore(), (X509Certificate) certificates[0])) {
                    usingCASigned = true;
                }

            } catch (Exception e) {
                Log.debug("getSASLMechanisms: Got exception " + e.getClass().getCanonicalName());
            }
           
            if (usingCASigned) {
                // Offer SASL EXTERNAL only if TLS has already been negotiated and we are not
                // using a self-signed certificate
                sb.append("<mechanism>EXTERNAL</mechanism>");
            }

}

I can confirm this solution works perfectly and it enables s2s with TLS/SSL!

Tho, this should be investigated fully on how it will affect all other code segments that uses this segment so it wont break anything else in by changing this for s2s

The patch in this thread is wrong (and dangerous in security terms); however I believe I have a fix for this, as a fix for OF-405.