简体   繁体   English

查找或初始化解决“证书中的主机名不匹配”所需的密钥库

[英]Find or initialize the keystore needed to solve “hostname in certificate didn't match”

I recently inherited a lab Ubuntu LAMP server that has been relatively neglected and still running a Struts 1.0 application. 我最近继承了一个实验室的Ubuntu LAMP服务器,该服务器相对被忽略了,并且仍在运行Struts 1.0应用程序。 We are preping for a complete overhaul, but in the mean time the only error that is being thrown in the logs is a javax.net.ssl.SSLException: hostname in certificate didn't match error. 我们正在准备进行彻底的检查,但是与此同时,日志中抛出的唯一错误是javax.net.ssl.SSLException: hostname in certificate didn't match错误。 It's our hope to patch this temporarily while we write the replacement. 我们希望在编写替换内容时临时对此进行修补。 I've read several SO questions on the mater (eg 1 , 2 , 3 , 4 ) and it seemed like Will Sargent's solution was the best choice. 我读过一些等等母校问题(如1234 ),它似乎像威尔·萨金特的解决方案是最好的选择。

Unfortunately I'm going into the server with utterly no documentation or returned email from the group that set it up (luckily none of the Java was obfuscated per policy). 不幸的是,我进入服务器时没有任何文档,也没有返回来自设置该服务器的小组的电子邮件(幸运的是,每个策略都没有混淆Java)。 I looked for any keystore files (searching for "keystore" in the file name or .jks files), but I didn't find any. 我寻找了任何密钥库文件(在文件名或.jks文件中搜索“ keystore”),但没有找到任何文件。 Which lead me think that I needed to make a new one and initialize it prior to calling the webClient.getPage . 这导致我认为我需要制作一个新的并且调用webClient.getPage 之前对其进行初始化 So far I have been able to make the .jks file just fine, it's just it doesn't change the hostname match error. 到目前为止,我已经能够使.jks文件正常,只是它不会更改hostname匹配错误。

Is there a way to see what keystore if any is being used by a servlet, and what its location happens to be? 有没有办法查看servlet正在使用什么密钥库,以及它的位置是什么? Alternatively, what is the proper way to make a new one and have it be used/initialized? 另外,制作一个新的并且被使用/初始化的正确方法是什么?


Additional Details 额外细节

There are a few things about this that are odd to me. 关于这一点,我有些奇怪。 The main one is I don't understand why the hostname wouldn't be correct. 最主要的是我不明白为什么主机名不正确。 The site being pulled is https://www.ncbi.nlm.nih.gov/account/ which if you navigate to it in a browser certainly pulls the correct certificate. 要提取的站点是https://www.ncbi.nlm.nih.gov/account/ ,如果您在浏览器中导航到该站点,则肯定会提取正确的证书。 I'm wondering if it's because the WebClient(BrowserVersion.FIREFOX_17) is set to the archaic FIREFOX_17 . 我想知道是否是因为WebClient(BrowserVersion.FIREFOX_17)设置为FIREFOX_17 Should I just change that from 17 to 31? 我应该将其从17更改为31吗? There are plenty of things that could be upgraded, but as we're going to start from scratch to have documentation, I want to change as little as possible on the old instance to hopefully keep it running for a few more months. 有很多事情可以升级,但是随着我们从头开始编写文档,我希望对旧实例进行尽可能少的更改,以期使其运行几个月。 The FIREFOX version installed on the server isn't close to current ether (not that it's used), but I was thinking changing the BrowserVersion just changed how the reply was formatted. 安装在服务器上的FIREFOX版本与当前的以太BrowserVersion并不接近(不是使用它),但是我当时想更改BrowserVersion只是改变了回复的格式。

Here is the code, ending on the line throwing the error: 这是代码,在引发错误的行上结束:

  private Vector updateRDLpubs(Vector orderList, DataSource dataSource)
    throws Exception
  {
    Vector removeList = new Vector();
    Vector historyList = new Vector();
    try
    {
      SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
      Calendar cal = Calendar.getInstance();
      cal.add(5, -5);
      Date days5Back = cal.getTime();

      WebClient webClient = new WebClient(BrowserVersion.FIREFOX_17);
      webClient.setThrowExceptionOnFailingStatusCode(false);
      HtmlPage page = (HtmlPage)webClient.getPage("https://www.ncbi.nlm.nih.gov/account/");

And here is the stack trace on the error: 这是关于错误的堆栈跟踪:

at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:227)
at org.apache.http.conn.ssl.BrowserCompatHostnameVerifier.verify(BrowserCompatHostnameVerifier.java:54)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:147)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572)
at com.gargoylesoftware.htmlunit.HtmlUnitSSLSocketFactory.connectSocket(HtmlUnitSSLSocketFactory.java:171)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:645)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:480)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at com.gargoylesoftware.htmlunit.HttpWebConnection.getResponse(HttpWebConnection.java:172)
at com.gargoylesoftware.htmlunit.WebClient.loadWebResponseFromWebConnection(WebClient.java:1486)
at com.gargoylesoftware.htmlunit.WebClient.loadWebResponse(WebClient.java:1403)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:305)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:374)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:359)
at tanklab.UpdateRDLJob2.updateRDLpubs(UpdateRDLJob2.java:241)
at tanklab.UpdateRDLJob2.execute(UpdateRDLJob2.java:79)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:525)

EDIT : Ahh, you are using HTMLUnit. 编辑 :啊,您正在使用HTMLUnit。 Your problem is probably that your HTMLUnit is severely out of date -- check against the server using https://tersesystems.com/2014/03/31/testing-hostname-verification/ and then upgrade HTMLUnit to the latest if nothing shows up. 您的问题可能是您的HTMLUnit已严重过时-使用https://tersesystems.com/2014/03/31/testing-hostname-verification/检查服务器,然后将HTMLUnit升级到最新(如果没有显示) 。

MORE EDIT : Why is HTMLUnit being used from Quartz? 更多编辑 :为什么从Quartz使用HTMLUnit? Are they trying to use it as a general HTTP Client? 他们是否正在尝试将其用作常规HTTP客户端? It's not designed for that. 它不是为此设计的。

The best reference on this is going to be Bulletproof TLS, which has a chapter about JSSE and Tomcat. 最好的参考将是Bulletproof TLS,其中有一章是关于JSSE和Tomcat的。

Is there a way to see what keystore if any is being used by a servlet, and what its location happens to be? 有没有办法查看servlet正在使用什么密钥库,以及它的位置是什么?

This depends on an SSLEngine being set up -- if you're running inside a servlet, most likely the app server has already set up your SSL configuration already. 这取决于是否设置了SSLEngine-如果您正在Servlet中运行,则很可能是应用服务器已经设置了SSL配置。 However, you can debug your JVM by turning on -Djavax.net.debug=ALL , but it doesn't tell you what location on the filesystem the certificate came from unless you coded a custom KeyStore and TrustManager (which is lame). 但是,可以通过打开-Djavax.net.debug=ALL来调试JVM,但是除非您编写了自定义的KeyStore和TrustManager((脚),否则它不会告诉您证书来自文件系统的哪个位置。 Here's the debug info though: 这是调试信息:

Alternatively, what is the proper way to make a new one and have it be used/initialized? 另外,制作一个新的并且被使用/初始化的正确方法是什么?

This depends on your application server. 这取决于您的应用程序服务器。 If you just need to provide a custom SSLEngine, you can do something like this (from https://github.com/wsargent/activator-play-tls-example/blob/master/app/https/CustomSSLEngineProvider.scala ): 如果只需要提供自定义SSLEngine,则可以执行以下操作(来自https://github.com/wsargent/activator-play-tls-example/blob/master/app/https/CustomSSLEngineProvider.scala ):

class CustomSSLEngineProvider(appProvider: ApplicationProvider) extends SSLEngineProvider {

  def readPassword(): Array[Char] = {
    val passwordPath = FileSystems.getDefault.getPath("certs", "password")
    Files.readAllLines(passwordPath).get(0).toCharArray
  }

  def readKeyInputStream(): java.io.InputStream = {
    val keyPath = FileSystems.getDefault.getPath("certs", "example.com.jks")
    Files.newInputStream(keyPath)
  }

  def readTrustInputStream(): java.io.InputStream = {
    val keyPath = FileSystems.getDefault.getPath("certs", "clientca.jks")
    Files.newInputStream(keyPath)
  }

  def readKeyManagers(): Array[KeyManager] = {
    val password = readPassword()
    val keyInputStream = readKeyInputStream()
    try {
      val keyStore = KeyStore.getInstance(KeyStore.getDefaultType)
      keyStore.load(keyInputStream, password)
      val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm)
      kmf.init(keyStore, password)
      kmf.getKeyManagers
    } finally {
      keyInputStream.close()
    }
  }

  def readTrustManagers(): Array[TrustManager] = {
    val password = readPassword()
    val trustInputStream = readTrustInputStream()
    try {
      val keyStore = KeyStore.getInstance(KeyStore.getDefaultType)
      keyStore.load(trustInputStream, password)
      val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
      tmf.init(keyStore)
      tmf.getTrustManagers
    } finally {
      trustInputStream.close()
    }
  }

  def createSSLContext(applicationProvider: ApplicationProvider): SSLContext = {
    val keyManagers = readKeyManagers()
    val trustManagers = readTrustManagers()

    // Configure the SSL context to use TLS
    val sslContext = SSLContext.getInstance("TLS")
    sslContext.init(keyManagers, trustManagers, null)
    sslContext
  }

  override def createSSLEngine(): SSLEngine = {
    val sslContext = createSSLContext(appProvider)

    // Start off with a clone of the default SSL parameters...
    val sslParameters = sslContext.getDefaultSSLParameters

    // Tells the server to ignore client's cipher suite preference.
    // http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#cipher_suite_preference
    sslParameters.setUseCipherSuitesOrder(true)

    // http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#SSLParameters
    val needClientAuth = java.lang.System.getProperty("play.ssl.needClientAuth")
    sslParameters.setNeedClientAuth(java.lang.Boolean.parseBoolean(needClientAuth))

    // Clone and modify the default SSL parameters.
    val engine = sslContext.createSSLEngine
    engine.setSSLParameters(sslParameters)

    engine
  }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM