I'm attempting to send a POST request from one server to another in PHP via SSL. It works correctly when i use CN_match
in my context options. However I get a deprecation message in my error log:
PHP Deprecated: the 'CN_match' SSL context option is deprecated in favor of 'peer_name'
The problem is that if I change CN_match
to peer_name
as suggested the request fails completely with this message:
failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request.
Using an invalid value for peer_name
results in an expected error:
Peer certificate CN='localhost' did not match expected CN='test'
Clearly it is matching correctly when I specify 'localhost'. Am I missing some other configuration that is required when using peer_name
instead of CN_match
?
Using MAMP, PHP 5.6.27
$userdata = array(
'action' => 'add-user',
'name' => $name,
'email' => $email,
'username' => $username,
'password' => $password);
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($userdata)
),
'ssl' => array(
'verify_peer' => true,
'cafile' => /path/to/file.pem,
'verify_depth' => 5,
'allow_self_signed' => true,
'peer_name' => 'localhost'
)
);
$context = stream_context_create($options);
$data = file_get_contents('https://localhost/add-user.php', false, $context);
Using curl was the only solution I could find:
$url = 'https://some.domain.com/file.php';
$pem_file = '/absolute/path/to/certificate.pem';
$userdata = array(
'action' => 'add-user',
'name' => $name,
'email' => $email,
'username' => $username,
'password' => $password);
$curl_req = curl_init();
curl_setopt($curl_req, CURLOPT_URL, $url);
curl_setopt($curl_req, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_req, CURLOPT_POST, true);
curl_setopt($curl_req, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
curl_setopt($curl_req, CURLOPT_POSTFIELDS, http_build_query($userdata));
curl_setopt($curl_req, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl_req, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl_req, CURLOPT_CAINFO, $pem_file);
$response = curl_exec($curl_req);
curl_close($curl_req);
In addition it took me a while to figure out how to structure the certificate.pem file. You need to stack the certificate(s) starting with your specific certificate and proceeding through any intermediate certificates and ending with the CA certificate:
-----BEGIN CERTIFICATE-----
<your site certificate>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<intermediate certificate>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<CA certificate>
-----END CERTIFICATE-----