I generated a letsencrypt certificate for my openfire server and ran into the same problem reported at Using cert in Openfire (XMPP-Server) - Let’s Encrypt Community Support. Even though the certificate has the XMPP domain as an alternate name, it doesn’t seem to pass validation. Complicating matters, the error reported in the admin console does not provide any details. Instead, you have to look in Openfire’s info.log:
2016.03.02 09:25:47 org.jivesoftware.openfire.keystore.IdentityStore - The supplied certificate chain does not cover the domain of this XMPP service (‘snurgle.org’). Instead, it covers [jabber.snurgle.org]
The code (Openfire/IdentityStore.java at master · igniterealtime/Openfire · GitHub) does seem to be trying to match the domain against a list of values returned by CertificateManager.getServerIdentities, but it seems to only be returning the Subject CommonName of the cert. Having done the workaround described in the discussion linked above, the cert does import and I can see in the admin console the expected Subject Alternative Names which include the XMPP service domain. Someone had reported in 2014 that they had trouble with a cert with more than 2 alternative names at [bug] Cannot import a certificate with 2 altsubject names, which also applies to my case (the cert I generated has three, snurgle.org, jabber.snurgle.org and conference.snurgle.org) but it sort of seems like that might be a red herring?
Previously I had used a StartCom cert which did NOT seem to have this problem. Looking at the two certs, the StartCom cert does not have the domain as the CommonName either (it uses conference.snurgle.org), but snurgle.org is listed as a “Subject Alternative Name (Other Name)” with a value of “xmppAddr snurgle.org” whereas the letsencrypt cert has only “Subject Alternative Name (DNS Name)” with a value of “snurgle.org”.
I’m not an SSL expert (apologies if I am using incorrect terminology in here) so it is very possible this is all expected somehow, but the fact that the cert seems to work ok once successfully imported seems to imply that there’s some confusion somewhere. Happy to provide more information or debugging.
Interesting post and letsencrypt forum link. I don’t have an answer here, but will take the liberty to tag @Guus der Kinderen to alert him to this thread.
Thanks for taking the time for the elaborate diagnostics, Chris. We’ve debated this issue in our open_chat MUC room for a bit. What we’ve come up with so far, is that Openfire correctly evaluates subjectAltName entries of type otherName with an ASN.1 Object Identifier of “id-on-xmppAddr”, but fails to evaluate other subjectAltName entries in a certificate. We’re tracking this issue in [OF-1100] SSL Certificate import should be more forgiving - Jive Software Open Source
Being a C developer and not having a ton of experience with large Java projects, if I do a ‘make’ in a git clone of Openfire, am I likely to get a jar that I can simply layer over my current installation to test? Pointers to documentation, wiki pages, etc, gladly appreciated.
There was an error while trying to import the private key and signed certificate. Internal server error: org.bouncycastle.cert.X509CertificateHolder cannot be cast to org.bouncycastle.openssl.PEMKeyPair
Possibly related stuff I see in debug.log
2016.03.04 18:31:59 org.jivesoftware.util.cert.SANCertificateIdentityMapping - Parsing otherName for subject alternative names: 1.3.6.1.5.5.7.8.5
2016.03.04 18:31:59 org.jivesoftware.util.cert.SANCertificateIdentityMapping - ... processing DERTaggedObject: [0][0]conference.snurgle.org
2016.03.04 18:31:59 org.jivesoftware.util.cert.SANCertificateIdentityMapping - Parsing otherName for subject alternative names: 1.3.6.1.5.5.7.8.7
2016.03.04 18:31:59 org.jivesoftware.util.cert.SANCertificateIdentityMapping - Parsing SRVName otherName...
2016.03.04 18:31:59 org.jivesoftware.util.cert.SANCertificateIdentityMapping - Cannot parse id-on-dnsSRV otherName, likely because of unknown record format. java.lang.IllegalArgumentException: illegal object in getInstance: org.bouncycastle.asn1.DERTaggedObject
at org.bouncycastle.asn1.DERUTF8String.getInstance(Unknown Source)
at org.jivesoftware.util.cert.SANCertificateIdentityMapping.parseOtherNameDnsSrv(SANCertificateIdentityMapping.java:157)
at org.jivesoftware.util.cert.SANCertificateIdentityMapping.parseOtherName(SANCertificateIdentityMapping.java:136)
at org.jivesoftware.util.cert.SANCertificateIdentityMapping.mapIdentity(SANCertificateIdentityMapping.java:75)
at org.jivesoftware.util.CertificateManager.getServerIdentities(CertificateManager.java:334)
at org.jivesoftware.openfire.keystore.IdentityStore.containsDomainCertificate(IdentityStore.java:364)
at org.jivesoftware.openfire.admin.security_002dkeystore_jsp._jspService(security_002dkeystore_jsp.java:180)
...
Ah, yes, this is helpful. Would you mind attaching your certificate (without the corresponding private key, obviously)? That’d be useful for reproducing the problem locally.