在PHP cURL中使用Windows AD Cert身份验证证书

在PHP cURL中使用Windows AD Cert身份验证证书,php,ssl,curl,Php,Ssl,Curl,我在WindowsServer2008R2服务器上运行PHP5.6。我正在尝试使TLS v1.2通信在此服务器和另一个内部服务器(运行Windows server 2003x64)之间正常工作。我们使用内部Windows AD根和颁发证书机构,因此我们的证书链是根CA-颁发CA-服务器证书。当我尝试连接时,出现以下错误: * Trying 192.168.1.10... * Connected to targetserver.example.com (192.168.1.10) port 4

我在WindowsServer2008R2服务器上运行PHP5.6。我正在尝试使TLS v1.2通信在此服务器和另一个内部服务器(运行Windows server 2003x64)之间正常工作。我们使用内部Windows AD根和颁发证书机构,因此我们的证书链是根CA-颁发CA-服务器证书。当我尝试连接时,出现以下错误:

*   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
我已经将根CA证书和颁发CA证书转换为PEM格式(使用openssl),并将它们添加到cacert.PEM文件的末尾

<?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");
?>
(注意:ca-bundle.crt是上面的cacert.pem的重命名副本)

如果我连接到另一台运行server 2008R2的服务器,但该服务器的证书也由我们的内部CA颁发,我将获得以下信息:

E:\openssl>curl-Iv--tlsv1.0”https://int-winsrv2008.example.com"
*重新生成的URL到:https://int-winsrv2008.example.com/
*正在尝试192.168.1.6。。。
*已连接到int-winsrv2008.example.com(192.168.1.6)端口443(#0)
*阿尔卑斯山,提供h2
*ALPN,提供http/1.1
*密码选择:全部:!出口:!出口40:!出口56:!阿努尔:!低:!RC4:@强度
*已成功设置证书验证位置:
*CAfile:E:\openssl\curl-ca-bundle.crt
卡帕斯:没有
*TLSv1.0(输出),TLS标头,证书状态(22):
*TLSv1.0(输出),TLS握手,客户端问候(1):
*TLSv1.0(IN)、TLS握手、服务器hello(2):
*TLSv1.0(IN)、TLS握手、证书(11):
*TLSv1.0(IN)、TLS握手、服务器密钥交换(12):
*TLSv1.0(IN),TLS握手,服务器完成(14):
*TLSv1.0(OUT)、TLS握手、客户端密钥交换(16):
*TLSv1.0(OUT),TLS更改密码,客户端hello(1):
*TLSv1.0(输出),TLS握手,完成(20):
*TLSv1.0(IN),TLS更改密码,客户端hello(1):
*TLSv1.0(英寸),TLS握手,完成(20):
*使用TLSv1.0/ECDHE-RSA-AES256-SHA的SSL连接
*ALPN,服务器不同意协议
*服务器证书:
*主题:C=KY;ST=大开曼群岛;L=乔治镇;O=开曼群岛港务局;OU=IT部门;CN=int-winsrv2008.example.com
*开始日期:2015年8月10日15:26:14 GMT
*到期日期:2017年8月9日15:26:14 GMT
*通用名称:int-winsrv2008.example.com(匹配)
*发行人:DC=com;DC=示例;CN=发布CA的示例
*SSL证书验证正常。
>HEAD/HTTP/1.1
>主持人:int-winsrv2008.example.com
>用户代理:curl/7.47.1
>接受:*/*
>
*TLSv1.0(IN)、TLS握手、问候请求(0):
*TLSv1.0(输出),TLS握手,客户端问候(1):
*TLSv1.0(IN)、TLS握手、服务器hello(2):
*TLSv1.0(IN)、TLS握手、证书(11):
*TLSv1.0(IN)、TLS握手、服务器密钥交换(12):
*TLSv1.0(IN),TLS握手,请求证书(13):
*TLSv1.0(IN),TLS握手,服务器完成(14):
*TLSv1.0(输出),TLS握手,证书(11):
*TLSv1.0(OUT)、TLS握手、客户端密钥交换(16):
*TLSv1.0(OUT),TLS更改密码,客户端hello(1):
*TLSv1.0(输出),TLS握手,完成(20):
*TLSv1.0(IN),TLS更改密码,客户端hello(1):
*TLSv1.0(英寸),TLS握手,完成(20):

因此,这似乎与Win Server 2003有关。我遗漏了什么?

为了完整起见,我想我会用我发现的来回答这个问题


这里发生了一些不同的错误。首先,我尝试使用Windows Server 2003不支持的TLS1.2。其次,我使用的主机头在证书握手时不会进行评估(除非您使用的SNI仅受IIS 8/Win Serv 2012支持),因此我没有获得我们的内部证书,而是获得由Comodo颁发的默认通配符证书。最后,我们服务器上的Comodo证书链似乎有问题(似乎缺少一个根证书或中间证书)。

为了完整性起见,我想我会用我发现的来回答这个问题


这里发生了一些不同的错误。首先,我尝试使用Windows Server 2003不支持的TLS1.2。其次,我使用的主机头在证书握手时不会进行评估(除非您使用的SNI仅受IIS 8/Win Serv 2012支持),因此我没有获得我们的内部证书,而是获得由Comodo颁发的默认通配符证书。最后,我们服务器上的Comodo证书链似乎有问题(似乎缺少一个根证书或中间证书)。

1)我会尝试将代码指向ca-bundle.rt(以确保cacert.pem正常)和2)您的2k3服务器真的支持TLS 1.2吗?(第二条错误消息听起来像是一个协商错误,但我可能错了)。您是对的,Win Serv 2003不支持1.2。我假设它有,如果没有,旋度会自动计算出哪个。我想不是。不管怎么说,我强制1.0,我们更接近了一点,因为至少现在它似乎在谈判。我还将ca bundle文件重命名为cURLs default(您现在注意到“成功设置证书验证位置”消息)。但是仍然无法正确连接。您的方法似乎是有效的,我能想到的唯一合理解释是您的cacert.pem文件不包含您认为应该存在的cacert(或者它们的格式错误)。@Caynadian在以前的版本中,您使用的是ca-bundle.crt,并且证书验证正在工作。。。使用tls1.0和此捆绑包应该可以。它看起来像c
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.
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