web-dev-qa-db-fra.com

PHP cURL ne fonctionne pas avec HTTPS

J'ai eu des problèmes sur mon serveur de développement où cURL, tout en fonctionnant parfaitement avec quoi que ce soit HTTP, ne fonctionne pas correctement avec quoi que ce soit HTTPS - même la même ressource exacte avec différents protocoles (pour les tests, j'ai demandé à google.com d'utiliser les deux http et https).

L'erreur cURL renvoyée est 35: "Un problème s'est produit quelque part dans la négociation SSL/TLS."

J'ai peigné le Web et SO pour les solutions, et tous ont été de définir CURLOPT_SSL_VERIFYPEER sur false, ce qui ne change rien, ou de télécharger le fichier de certificat et de définir CURLOPT_CAINFO sur son chemin, qui ne change rien non plus.

Lors de la définition d'un certificat, j'ai suivi les instructions de ce tutoriel et ce tutoriel , en essayant à la fois de télécharger le certificat pour la ressource que je demande et de télécharger un ensemble de certificats.

J'ai également essayé de définir explicitement CURLOP_PORT sur 443. Pour approfondir ma question, les autres options que j'ai définies sont CURLOPT_VERBOSE = true, CURLOPT_RETURNTRANSFER = true et CURLOPT_SSL_VERIFYHOST = 2 (j'ai essayé toutes les combinaisons de 1 et 2 avec VERIFYPEER, toutes deux vraies et faux). J'ai également vérifié dans phpinfo () que j'ai OpenSSL et qu'il est activé.

J'utilise beaucoup d'ancien code qui fonctionnait parfaitement sur mon dernier serveur de production, donc ce code a déjà fonctionné. Mais cet hébergement était un hébergement partagé et je ne connais pas la plupart de la configuration là-bas.

20
spezied

Curl n'a pas de certificats racine intégrés (comme la plupart des navigateurs modernes). Vous devez le pointer explicitement vers un fichier cacert.pem:

  curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cert/file/cacert.pem');

Sans cela, curl ne peut pas vérifier le certificat renvoyé via ssl. Ce même fichier de certificat racine peut être utilisé chaque fois que vous utilisez SSL en boucle.

Vous pouvez obtenir le fichier cacert.pem ici: http://curl.haxx.se/docs/caextract.html

23
Ray

Que dis-tu de ça. Il récupère ce qui pourrait être la page d'accueil Google HTTPS. (Depuis que j'ai désactivé la vérification des certificats, je n'ai aucun moyen de savoir que c'est la vraie page d'accueil de Google.) Cela devrait faire l'affaire pour vous.

<?PHP

// connect via SSL, but don't check cert
$handle=curl_init('https://www.google.com');
curl_setopt($handle, CURLOPT_VERBOSE, true);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
$content = curl_exec($handle);

echo $content; // show target page
?>
12
Joseph Lust

Trouvez si votre système d'exploitation comprend un répertoire de certificats. Si tel est le cas, les certificats CA requis seront souvent déjà inclus. Sur Ubuntu, par exemple, c'est généralement /etc/ssl/certs. Si ce répertoire existe, définissez le paramètre de chemin d'accès de l'autorité de certification:

curl_setopt($ch, CURLOPT_CAPATH, '/etc/ssl/certs');

Vous pouvez également référencer un seul fichier de certificat CA. Incluez un fichier cacert.pem dans votre projet ou installez-le sur votre serveur. Téléchargez depuis une source de confiance, par ex. cacert.org. Pour un seul fichier, ne définissez pas le CAPATH et définissez plutôt CAINFO:

curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem');

La désactivation de la vérification des pairs et des hôtes est une solution rapide mais non sécurisée au problème réel. Ces fonctionnalités existent pour une bonne raison: vous pouvez donc avoir confiance, via une tierce partie, que le système auquel vous vous connectez est celui auquel vous vous attendez.

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
5
Matt S