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).

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

报告相同问题?

悬赏问题

  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化
  • ¥15 Mirare PLUS 进行密钥认证?(详解)
  • ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证
  • ¥20 想用ollama做一个自己的AI数据库
  • ¥15 关于qualoth编辑及缝合服装领子的问题解决方案探寻
  • ¥15 请问怎么才能复现这样的图呀