When connecting to an XMPP server with a self-signed certificate using Pidgin, you might encounter the "unable to validate certificate" error. The standard approach would be to retrieve the certificate chain using OpenSSL:
openssl s_client -connect my.jabber.server.net:5222 </dev/null
But surprisingly, this returns:
CONNECTED(00000003)
140472458057376:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177:
--- no peer certificate available
--- No client certificate CA names sent
--- SSL handshake has read 0 bytes and written 213 bytes
XMPP servers typically use STARTTLS rather than immediate SSL/TLS negotiation on port 5222. This explains why the direct OpenSSL connection fails - it's attempting standard SSL when the server expects XMPP protocol first.
To properly retrieve certificates from an XMPP server, we need to:
- Establish a plaintext connection
- Initiate STARTTLS
- Then perform the certificate retrieval
Here's a working method using OpenSSL:
openssl s_client -starttls xmpp -connect my.jabber.server.net:5222 </dev/null
The -starttls xmpp
flag tells OpenSSL to use XMPP's specific STARTTLS implementation.
If the above doesn't work, try these approaches:
Method 1: Using gnutls-cli
gnutls-cli --starttls --port 5222 my.jabber.server.net
Method 2: Python script
import socket
import ssl
from OpenSSL import SSL
context = SSL.Context(SSL.SSLv23_METHOD)
conn = SSL.Connection(context, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
conn.connect(('my.jabber.server.net', 5222))
conn.do_handshake()
cert = conn.get_peer_cert_chain()
for c in cert:
print(SSL.dump_certificate(SSL.FILETYPE_PEM, c))
Once you have the certificates, ensure they're in the correct chain order. The server certificate should come first, followed by intermediate CAs (if any), and finally the root CA.
For Pidgin specifically, you'll need to convert the certificates to the appropriate format and place them in Pidgin's certificate store, typically located at:
~/.purple/certificates/x509/tls_peers/
The file should be named using the SHA-1 fingerprint of the certificate. You can obtain this using:
openssl x509 -noout -fingerprint -sha1 -inform pem -in certificate.pem
When connecting to XMPP servers with self-signed certificates, Pidgin and other clients often throw "unable to validate certificate" errors. While some clients allow disabling validation, proper security practice requires importing the complete certificate chain.
The initial approach using:
openssl s_client -connect my.jabber.server.net:5222 </dev/null
fails because XMPP requires STARTTLS negotiation. Unlike HTTPS which immediately establishes TLS, XMPP begins with plaintext and upgrades to TLS.
To properly extract certificates from an XMPP server:
openssl s_client -connect my.jabber.server.net:5222 -starttls xmpp \
-showcerts </dev/null
Key parameters:
-starttls xmpp
: Performs XMPP protocol negotiation-showcerts
: Displays full certificate chain-servername
: Important for SNI-enabled servers
For server xmpp.example.com
:
openssl s_client -connect xmpp.example.com:5222 \
-starttls xmpp -showcerts -servername xmpp.example.com </dev/null \
| awk '/BEGIN CERT/,/END CERT/ {print $0}' > xmpp_chain.pem
If you encounter:
SSL handshake failure
Try forcing TLS 1.2:
openssl s_client -connect xmpp.example.com:5222 \
-starttls xmpp -tls1_2 -showcerts
After obtaining the chain, verify it with:
openssl verify -CAfile xmpp_chain.pem xmpp_chain.pem
1. Copy the certificate chain to ~/.purple/certificates/x509/tls_peers/
2. Rename the file to match the server's domain (e.g., xmpp_example_com.pem
)
3. Restart Pidgin