doubi7306 2016-02-09 14:08
浏览 140
已采纳

在PHP cURL中使用Windows AD Cert Auth证书

I am running PHP 5.6 on a Windows Server 2008R2 server. I am trying to get TLS v1.2 communications working between this server and another internal server (running Windows Server 2003x64). We use internal Windows AD Root and Issuing Cert Authorities so our certificate chain is Root CA - Issuing CA - Server Cert. When I try and connect, I get the following error:

*   Trying 192.168.1.10...
* Connected to targetserver.example.com (192.168.1.10) port 443 (#0)
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: e:\php\cacert.pem
  CApath: none
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0

I have converted both the root CA cert and the issuing CA cert to PEM format (using openssl) and added them to the end of the cacert.pem file.

<?php
  function nxs_cURLTest($url, $msg, $testText){  
    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_URL, $url); 
    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36"); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_TIMEOUT, 10); 
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_VERBOSE, true);
    curl_setopt($ch, CURLOPT_CAINFO, "e:\\php\\cacert.pem");

    $verbose = fopen('php://temp', 'w+');
    curl_setopt($ch, CURLOPT_STDERR, $verbose);    

    $response = curl_exec($ch); 
    $errmsg = curl_error($ch); 
    $cInfo = curl_getinfo($ch); 
    curl_close($ch); 
    echo "<br />Testing ... ".$url." - ".$cInfo['url']."<br />";
    if (stripos($response, $testText)!==false) 
      echo "....<b style='color:green;'>".$msg." - OK</b><br />"; 
    else 
    { 
      echo "....<b style='color:red;'>".$msg." - Problem</b><br /><pre>"; 
      print_r($errmsg); 
      print_r($cInfo); 
      print_r(strlen($response) . " bytes received."); 
      print_r(htmlentities($response)); 

      rewind($verbose);
      $verboseLog = stream_get_contents($verbose);
      echo "<br />Verbose output:</br />";
      echo "<pre>", htmlspecialchars($verboseLog), "</pre>";    

      echo "</pre>There is a problem with cURL. You need to contact your server admin or hosting provider.<br />";
    }
  }

  nxs_cURLTest("https://targetserver.example.com/curl/", "HTTPS to TargetServer", "Document contents");
?>

If I try to just use cURL from the command line, then I get a different error (EDIT: forced tls 1.0 as Win Serv 2003 doesn't support anything higher):

E:\openssl>curl -Iv --tlsv1.0 "https://targetserver.example.com"
* Rebuilt URL to: https://targetserver.example.com/
*   Trying 192.168.1.10...
* Connected to targetserver.example.com (192.168.1.10) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: E:\openssl\curl-ca-bundle.crt
  CApath: none
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.0 (OUT), TLS handshake, Client hello (1):
* TLSv1.0 (IN), TLS handshake, Server hello (2):
* TLSv1.0 (IN), TLS handshake, Certificate (11):
* TLSv1.0 (OUT), TLS alert, Server hello (2):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
* TLSv1.0 (OUT), TLS alert, Client hello (1):
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

(note: ca-bundle.crt is a renamed copy of cacert.pem from above)

If I connect to a different server that runs Server 2008R2 but that also has its certificate issued from our internal CA I get the following:

E:\openssl>curl -Iv --tlsv1.0 "https://int-winsrv2008.example.com"
* Rebuilt URL to: https://int-winsrv2008.example.com/
*   Trying 192.168.1.6...
* Connected to int-winsrv2008.example.com (192.168.1.6) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: E:\openssl\curl-ca-bundle.crt
  CApath: none
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.0 (OUT), TLS handshake, Client hello (1):
* TLSv1.0 (IN), TLS handshake, Server hello (2):
* TLSv1.0 (IN), TLS handshake, Certificate (11):
* TLSv1.0 (IN), TLS handshake, Server key exchange (12):
* TLSv1.0 (IN), TLS handshake, Server finished (14):
* TLSv1.0 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.0 (OUT), TLS change cipher, Client hello (1):
* TLSv1.0 (OUT), TLS handshake, Finished (20):
* TLSv1.0 (IN), TLS change cipher, Client hello (1):
* TLSv1.0 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.0 / ECDHE-RSA-AES256-SHA
* ALPN, server did not agree to a protocol
* Server certificate:
*        subject: C=KY; ST=Grand Cayman; L=George Town; O=Port Authority of the Cayman Islands; OU=IT Department; CN=int-winsrv2008.example.com
*        start date: Aug 10 15:26:14 2015 GMT
*        expire date: Aug  9 15:26:14 2017 GMT
*        common name: int-winsrv2008.example.com (matched)
*        issuer: DC=com; DC=example; CN=example-Issuing-CA
*        SSL certificate verify ok.
> HEAD / HTTP/1.1
> Host: int-winsrv2008.example.com
> User-Agent: curl/7.47.1
> Accept: */*
>
* TLSv1.0 (IN), TLS handshake, Hello request (0):
* TLSv1.0 (OUT), TLS handshake, Client hello (1):
* TLSv1.0 (IN), TLS handshake, Server hello (2):
* TLSv1.0 (IN), TLS handshake, Certificate (11):
* TLSv1.0 (IN), TLS handshake, Server key exchange (12):
* TLSv1.0 (IN), TLS handshake, Request CERT (13):
* TLSv1.0 (IN), TLS handshake, Server finished (14):
* TLSv1.0 (OUT), TLS handshake, Certificate (11):
* TLSv1.0 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.0 (OUT), TLS change cipher, Client hello (1):
* TLSv1.0 (OUT), TLS handshake, Finished (20):
* TLSv1.0 (IN), TLS change cipher, Client hello (1):
* TLSv1.0 (IN), TLS handshake, Finished (20):
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Length: 689
Content-Length: 689
< Content-Type: text/html
Content-Type: text/html
< Last-Modified: Thu, 18 Jul 2013 15:46:23 GMT
Last-Modified: Thu, 18 Jul 2013 15:46:23 GMT
< Accept-Ranges: bytes
Accept-Ranges: bytes
< ETag: "f12a46f4cd83ce1:0"
ETag: "f12a46f4cd83ce1:0"
< Server: Microsoft-IIS/7.5
Server: Microsoft-IIS/7.5
< X-Powered-By: ASP.NET
X-Powered-By: ASP.NET
< Date: Tue, 09 Feb 2016 15:18:51 GMT
Date: Tue, 09 Feb 2016 15:18:51 GMT

<
* Connection #0 to host int-winsrv2008.example.com left intact

So it seems it's something to do with Win Server 2003. What am I missing?

  • 写回答

1条回答 默认 最新

  • duanjian9148 2016-02-12 14:22
    关注

    For completeness sake, I thought I would answer this with what I found out.

    There was a few different errors occurring here. First, I was trying to use TLS1.2 which is not supported by Windows Server 2003. Second, I am using host headers which are not evaluated at the point of the certificate handshake (unless you use SNI which is only supported by IIS 8/Win Serv 2012) so I was not getting our internal certificate but our default wildcard cert issued by Comodo. Finally, there seems to be an issue with the Comodo certificate chain on our server (seems to be missing one of the root or intermediate certs).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 Python安装cvxpy库出问题
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥15 python天天向上类似问题,但没有清零
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 C#调用python代码(python带有库)
  • ¥15 矩阵加法的规则是两个矩阵中对应位置的数的绝对值进行加和
  • ¥15 活动选择题。最多可以参加几个项目?
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题