Hi,

Problem
=======

I'm trying to obtain the certificate of an XMPP server using
  openssl s_client -connect server.domain.tld:5222 -starttls xmpp

However, the name of the server within the XMPP realm is only domain.tld
rather than server.domain.tld. The above command tries to start the TLS
connection as follows.
  <stream:stream xmlns:stream='http://etherx.jabber.org/streams' 
xmlns='jabber:client' to='server.domain.tld' version='1.0'>
But gets rejected with the following message.
  <stream:stream xmlns='jabber:client' 
xmlns:stream='http://etherx.jabber.org/streams' id='3729850247' 
from='domain.tld' xml:lang='en'>
    <stream:error>
      <host-unknown xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
    </stream:error>
Note that the message is sent to server.domain.tld, but the error comes
from domain.tld.

The solution to this problem seems to be the -servername option to
s_client:
  openssl s_client  -connect server.domain.tld:5222 -starttls xmpp -servername 
domain.tld
This however doesn't make any difference, and the stream is started by
OpenSSL the same as before:
  <stream:stream xmlns:stream='http://etherx.jabber.org/streams' 
xmlns='jabber:client' to='server.domain.tld' version='1.0'>


Cause
=====

Looking in apps/s_client.c (line 1181 for openssl-1.0.0e), there is
        if (starttls_proto == PROTO_XMPP)
                {
                int seen = 0;
                BIO_printf(sbio,"<stream:stream "
                    "xmlns:stream='http://etherx.jabber.org/streams' "
                    "xmlns='jabber:client' to='%s' version='1.0'>", host);

[Note: I believe this should be an else if rather than an if statement
(or maybe the whole conditionnal should be replaced by a switch
statement), though I don't think it would change anything to the
behaviour of the program either way.]

The string which is sent to the XMPP server uses host, which contains the
argument to -connect (from line 494), rather than that to -servername (the
aptly named servername variable, line 712).


Proposed Solution
=================

On line 429, servername is initialised to NULL. The problem could then
be solved quickly, but perhaps not very elegantly, by changing the
BIO_printf() above with
                BIO_printf(sbio,"<stream:stream "
                    "xmlns:stream='http://etherx.jabber.org/streams' "
                    "xmlns='jabber:client' to='%s' version='1.0'>", 
servername?servername:host);
(note the servername?servername:host towards the very end). See attached patch.

Variable servername is defined within an OPENSSL_NO_TLSEXT conditionnal block,
but, logically, so is the full starttls logic, so it shouldn't be a problem.

I have compiled and tested a version patched with this proposal. It works as I
would expect (i.e., it solves the very problem described above). This is such a
trivial change that I don't believe it introduces anything unintended).


Hope this helps.

-- 
Olivier Mehani <[email protected]>
PGP fingerprint: 4435 CF6A 7C8D DD9B E2DE  F5F9 F012 A6E2 98C6 6655

Index: openssl-1.0.0e/apps/s_client.c
===================================================================
--- openssl-1.0.0e.orig/apps/s_client.c
+++ openssl-1.0.0e/apps/s_client.c
@@ -1183,7 +1183,7 @@ SSL_set_tlsext_status_ids(con, ids);
                int seen = 0;
                BIO_printf(sbio,"<stream:stream "
                    "xmlns:stream='http://etherx.jabber.org/streams' "
-                   "xmlns='jabber:client' to='%s' version='1.0'>", host);
+                   "xmlns='jabber:client' to='%s' version='1.0'>", 
servername?servername:host);
                seen = BIO_read(sbio,mbuf,BUFSIZZ);
                mbuf[seen] = 0;
                while (!strstr(mbuf, "<starttls 
xmlns='urn:ietf:params:xml:ns:xmpp-tls'"))

Attachment: pgpjJT8qmGHVe.pgp
Description: PGP signature

Reply via email to