CURL запрос на https

Flyer

Новичок
CURL запрос на https

День добрый. Уже какой год черпаю тут ответы на свои вопросы за что всем огромное спасибо, но в этот раз ответа не нашел и решил задать вопрос.

Ситуация банальная.

Есть 2 сервера, 1 из которых шлет запросы ГЕТом с целью получить ответ от 2ого в виде XML, все бы хорошо но на 2ой сервер просит SSL ключ.
От второго сервера мне дали .p12 сертификат который был сгенерирован админом, его я разложил на cert.pem и priv.key и собственно начал стучаться к ним.

Вот параметры которые я передаю в CURL:
<?php

CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_URL => $type["check_url"].$our_request[$key]["link"],
CURLOPT_HEADER => 0,
CURLOPT_POST => 0,
CURLOPT_USERAGENT => "User-Agent=Mozilla/5.0 Firefox/1.0.7",
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_SSLCERT => "./certificates/cert.pem",
CURLOPT_SSLKEY => "./certificates/priv.key",

?>

в ответ получаю:
Errno:58 Error: unable to use client certificate (no key found or wrong pass phrase?)


Начал уже эксперементировать и добавлять то по очереди то вмете:
CURLOPT_SSLCERTPASSWD => "пароль ",
CURLOPT_SSLKEYPASSWD => "пароль ",

Но результат тот же. Выручайте пожалуйста, проект горит, а опыта с SSL нет =( Перепробовал все примеры что находил в сети и ничего не помогло.
 

tony2001

TeaM PHPClub
начать, вероятно, стОит с указания полного пути до ключа и сертификата.
 

Flyer

Новичок
Tony, пробовал, но к сожалению не помогает. =(

ставил проверку is_file, файлы эти он все видит.
 

kruglov

Новичок
Сделайте из .p12 -> .pem

Как из .p12 сделать .pem:
Качаем, найдя в гугле, openssl, запускаем
openssl pkcs12 -in filename.p12 -out filename.pem

И потом
curl_setopt($ch, CURLOPT_SSLCERT, 'сертификат.pem');

-~{}~ 03.04.08 16:07:

А, оно уже, хм.

curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $cert_password); должно, по идее, работать...

-~{}~ 03.04.08 16:09:

А CURLOPT_SSLKEY вообще не нужен, у меня без него работает.
 

Flyer

Новичок
да уже разбил его пхпшной функцией и с паролем игрался, но ничего не помогло =(

-~{}~ 03.04.08 16:15:

пробовал так же добавлять и в CURLOPT_CAINFO их рутовый сертификат и тоже ни в какую =(
 

tony2001

TeaM PHPClub
тогда выполнить в консоли под strace и проверить, что нужный файл читается.
 

Flyer

Новичок
Tony:
Нужный файл читается, вывели его на экран без проблем.

Kruglov:
Били .p12 не своей функций, стандартная пхпшная openssl_pkcs12_read, вроде можно доверять.
 

Flyer

Новичок
Да Tony, ты прав .... трабл в путях все же.

Меня сбила уверенность в том что если is_file видит их то значит и CURL видит, а оказывается это не так =(

Спасибо огромное всем за помощь!!!

-~{}~ 03.04.08 18:34:

В общем, 100% рабочий PHP код отправки при помощи CURL на https// (SSL)

$curl = curl_init();

curl_setopt($curl,CURLOPT_CUSTOMREQUEST,"GET");
curl_setopt($curl,CURLOPT_URL,"https://your_domain.com/?parametrs=$your_parametrs");
curl_setopt($curl,CURLOPT_HEADER,0);
curl_setopt($curl,CURLOPT_POST,0);
curl_setopt($curl,CURLOPT_USERAGENT,"User-Agent=Mozilla/5.0 Firefox/1.0.7");
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,1);
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,1);
curl_setopt($curl,CURLOPT_CAINFO,'C:/www/html/web_site/certificates/CA.cert');
curl_setopt($curl,CURLOPT_SSLCERT,C:/www/html/web_site/certificates/PEM_cert.pem');
curl_setopt($curl,CURLOPT_SSLKEY,'C:/www/html/web_site/certificates/KEY_cert.key');
curl_setopt($curl,CURLOPT_SSLCERTPASSWD,"");
curl_setopt($curl,CURLOPT_SSLKEYPASSWD,"");
curl_setopt($curl, CURLOPT_USERPWD, "$your_login:$your_password"); // если нужно авторизироваться логином и паролем

$_SITE_ANSWER = curl_exec($curl);
curl_close($curl);

echo $_SITE_ANSWER;

-~{}~ 03.04.08 18:39:

Так же, в данной задачке был получен .p12 контейнер с ключами, у кого проблемы с консолью как у меня может воспользоваться PHP функцией что бы получить .pem файл и сам собственно ключ. Файл CA.cert был выдан админом 2ого сервера.

$p12cert = array();
$file = './certificates/filename.p12';
$fd = fopen($file, 'r');
$p12buf = fread($fd, filesize($file));
fclose($fd);

if (openssl_pkcs12_read($p12buf, $p12cert,"пароль")){
echo 'Works!';
file_put_contents('./certificates/cert.pem', $p12cert['cert']);

$privKey = openssl_get_privatekey($p12cert['pkey']);
file_put_contents('./certificates/priv.key', $p12cert['pkey']);
}
else{
echo 'Fail';
}

Еще раз всем спасибо ;)
 

DiMoN_TD

Новичок
А как с помощью cURL можно принять передаваемый сертификат провайдером?
 

Flyer

Новичок
А вот такой вот еще вопрос:

Проблема похожа на описанную в первом посте. Только от 2ого сервера получен сертификат в формате x509, а не P12.

Как следствие не могу понять как в таком случае работать с тем сервером через CURL. так как в последнем примере требуется 3 файла, из этого x509 максимум что получилось выудить так это pem. При запросе на https:// тот в ответ ругается мол дайте еще key, а как его получить не могу понять.
 

kindjoker

Новичок
ТАКАЯ ЖЕ проблема как и у Flyer-а.

Мне нужно достучаться до веб-сервисов на IIS. Сервисы работают через https. Мне предоставили сертификат ***.cer (бинарный). Я его сконвертировал в PEM-формат. В итоге имею файл:
-----BEGIN CERTIFICATE-----
MIIFeDCCBSKgAwIBAgIKYQVeeQABAAAACTANBgkqhkiG9w0BAQUFADCBizEjMCEG
CSqGSIb3DQEJARYUYWRtaW5pc3RyYXRvckBsZGYucnUxCzAJBgNVBAYTAlJVMQ8w
*************************************************************
-----END CERTIFICATE-----

при попытке его использовать через а)SoapClient, б)cUrl, в)openssl s_client получаю ошибки вида:

а) Unable to set local cert chain file (..) Check that your cafile/capath settings include details of your certificate and its issuer
б) unable to set private key file: '/..../****.pem' type PEM
в) unable to load client certificate private key file
9057:error:0906D06C:pEM routines:pEM_read_bio:no start line:pem_lib.c:647:Expecting: ANY PRIVATE KEY

Хотя сами сервисы доступны через браузер.

(Сертификат на IIS самоподписанный, мои скрипты работают из под linux, apache2)


Собственно мне не понятно - что это за private key, который все либы так рвутся передать серверу? На сколько я знаю, есть только один private key - тот что хранится на сервере, и он никуда передаваться не должен, на то он и private.

Буду благодарен за любые советы, т.к. излазил все форумы вдоль и поперек и не нашел ответа.
 

DiMoN_TD

Новичок
kindjoker,
на сколько я понимаю - это лишь обычный public key у вас, потому попробуйте следующий код:

<?

$curl = curl_init();
curl_setopt($curl,CURLOPT_CUSTOMREQUEST,"GET");

curl_setopt($curl,CURLOPT_URL,$url);

curl_setopt($curl,CURLOPT_USERAGENT,"User-Agent=Mozilla/5.0 Firefox/1.0.7");
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,false);
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);

curl_setopt($curl,CURLOPT_PORT,$port);

curl_exec($curl);

?>
 

kindjoker

Новичок
Спасибо DiMoN_TD за совет.
Оказалось, что лично моя проблема не была связана с сертификатами. Мне не надо было ничего передавать, а лишь просто одобрить предложенный сервером IIS. После чего тот с помощью ISA организовывал туннель.

А причина была в том, что этот самый IIS использует NTLM Authentication.
Поэтому, добавил в cURL параметр CURLOPT_HTTPAUTH = CURLAUTH_NTLM,
хочу обратить внимание, что в моем конкретном случае вариант с параметром CURLOPT_HTTPAUTH = CURLAUTH_ANY не работал, т.е. сам курл не догадывался, что надо выбрать именно этот тип (хотя это может быть и логично).

Но так как моей главной задачей было добраться до сервисов, то надо было заставить работать SOAPClient, который в данный момент НЕ поддерживает NTLM аутентификацию.

Выход был найден в статье Thomas Rabaix -а ("Using SOAP PHP with NTLM Authentication"), где он создает обертку вокруг SOAP клиента. Вот ссылка на ресурс: http://rabaix.net/articles/2008/3/13/using-soap-php-with-ntlm-authentication

Надеюсь, что это кому-то в будущем сэкономит время, я лично, из-за этой NTLM потерял его очень много.
 

nirex

Новичок
<?php
$link_page = 'URL';
$result;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$link_page);
curl_setopt($ch, CURLOPT_SSLCERT,'файл с полным путем, где лежит серт и кей в одном файле');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$xyz = curl_exec ($ch);

echo $xyz;
if ($xyz == NULL) {
echo "Error:\n";
echo curl_errno($ch) . " - " . curl_error($ch) . "\n";
}

curl_close ($ch);
?>
 
Сверху