I/O exception (javax.net.ssl.SSLException) hostname in certificate didn't match - SNI problem with new MSTeams URLs
neil-greenwood opened this issue · 0 comments
Jenkins and plugins versions report
Environment
Jenkins: 2.277.4
OS: Linux - 3.13.0-40-generic
---
Office-365-Connector:4.15.2
What Operating System are you using (both controller, and any agents involved in the problem)?
Linux
Reproduction steps
- Configure Office-365-connector with a new-style MSTeams connector URL - like https://[COMPANY].webhook.office.com/webhookb2/[UUID]@[UUID]/IncomingWebhook/[ID]/[UUID]
- Execute a job that will post a message to MSTeams using the URL
Expected Results
The message will appear in the channel identified by the connector URL
Actual Results
javax.net.ssl.SSLException: hostname in certificate didn't match: <[COMPANY].webhook.office.com> != </*.internal.outlook.com/*.outlook.com/outlook.com/office365.com/*.office365.com/*.outlook.office365.com/*.office.com/outlook.office.com/substrate.office.com/attachment.outlook.live.net/attachment.outlook.office.net/attachment.outlook.officeppe.net/attachments.office.net/*.clo.footprintdns.com/*.nrb.footprintdns.com/ccs.login.microsoftonline.com/ccs-sdf.login.microsoftonline.com/substrate-sdf.office.com/attachments-sdf.office.net/*.live.com/mail.services.live.com/hotmail.com/*.hotmail.com/outlook.com>
at org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory.verifyHostName(SSLProtocolSocketFactory.java:339)
at org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory.verifyHostName(SSLProtocolSocketFactory.java:275)
at org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory.verifyHostName(SSLProtocolSocketFactory.java:258)
at org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory.createSocket(SSLProtocolSocketFactory.java:167)
at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:714)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:394)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:178)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:404)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:330)
at jenkins.plugins.office365connector.HttpWorker.run(HttpWorker.java:84)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Anything else?
This is re-opening issue #254. As I commented on that issue, after it was closed, I believe this is a problem with SNI.
The connector is not providing SNI information when making the connection to the connector URL, so it gets the incorrect TLS certificate (without a SAN that is valid for the [COMPANY].webhook.office.com domain).
If you provide SNI information, the correct TLS certificate is returned and I assume the message would be posted successfully.
Output from testssl.sh XX.webhook.office.com:
Common Name (CN) *.webhook.office.com (CN in response to request w/o SNI: outlook.com )
subjectAltName (SAN) *.webhook.office.com
Trust (hostname) Ok via SAN wildcard and CN wildcard (SNI mandatory)
Note the comment on the final line: SNI mandatory
I can almost see the fix, but it's about 10 years since I worked with Java more than 1 day every 6-9 months...
https://github.com/jenkinsci/office-365-connector-plugin/blob/master/src/main/java/jenkins/plugins/office365connector/HttpWorker.java#L68
Somewhere here, it needs to call httpclient.getHostConfiguration().setHost("www.whatever.com", 443, myhttps); but with the relevant host parsed from the string url.
I recommend not using regex or string parsing though; it needs to be done through the URL class, since there are waaaaaay too many edge cases.