Après la mise à niveau vers PHP 5.6, un message d'erreur lorsque je tente de me connecter à un serveur via fsockopen()
..
Le certificat sur le serveur (hôte) est auto-signé
Avertissement PHP: fsockopen (): l'opération SSL a échoué avec le code 1. OpenSSL Messages d'erreur: erreur: 14090086: routines SSL: SSL3_GET_SERVER_CERTIFICATE: échec de la vérification du certificat
if($fp = fsockopen($Host, $port, $errno, $errstr, 20)){
$this->request = 'POST '.substr($this->url, strlen($this->Host)).' HTTP/1.1'.$crlf
.'Host: '.$this->Host.$crlf
.'Content-Length: '.$content_length.$crlf
.'Connection: Close'.$crlf.$crlf
.$body;
fwrite($fp, $this->request);
while($line = fgets($fp)){
if($line !== false){
$this->response .= $line;
}
}
fclose($fp);
}
# cd /etc/ssl/certs/
# wget http://curl.haxx.se/ca/cacert.pem
php.ini
openssl.cafile = "/etc/ssl/certs/cacert.pem"
Mais le script ne fonctionne toujours pas
Cela marche
echo file_get_contents("/etc/ssl/certs/cacert.pem");
$contextOptions = array(
'ssl' => array(
'verify_peer' => true, // You could skip all of the trouble by changing this to false, but it's WAY uncool for security reasons.
'cafile' => '/etc/ssl/certs/cacert.pem',
//'CN_match' => 'example.com', // Change this to your certificates Common Name (or just comment this line out if not needed)
'ciphers' => 'HIGH:!SSLv2:!SSLv3',
'disable_compression' => true,
)
);
$context = stream_context_create($contextOptions);
$fp = stream_socket_client("{$Host}:{$port}", $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $context);
erreur
Avertissement PHP: stream_socket_client (): l'opération SSL a échoué avec le code 1. OpenSSL Messages d'erreur: erreur: 14090086: routines SSL: SSL3_GET_SERVER_CERTIFICATE: échec de la vérification du certificat
Le fichier que vous avez téléchargé ( http://curl.haxx.se/ca/cacert.pem ) est un ensemble de certificats racine émanant des principales autorités de certification de confiance. Vous avez dit que l'hôte distant dispose d'un certificat SSL auto-signé, il n'a donc pas utilisé de certificat de confiance. Le paramètre openssl.cafile
doit pointer sur le certificat de l'autorité de certification utilisé pour signer le certificat SSL sur l'hôte distant. PHP 5.6 a été amélioré par rapport aux versions précédentes de PHP pour vérifier les certificats des homologues et les noms d’hôte par défaut ( http://php.net/manual/en/migration56.openssl.php )
Vous devez localiser le certificat de l'autorité de certification généré sur le serveur qui a signé le certificat SSL et le copier sur ce serveur. La seule autre option consiste à désactiver la vérification de l'homologue, mais cela nuit à la sécurité SSL. Si vous ne voulez PAS essayer de désactiver la vérification, essayez ce tableau avec le code de ma réponse précédente:
$contextOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false
)
);
Dans les deux cas, si vous utilisez des certificats auto-signés, vous devez ajouter le certificat CA utilisé pour signer le certificat SSL de l'hôte distant au magasin approuvé sur le serveur que vous vous connectez à partir de OR. diffuser les contextes pour utiliser ce certificat pour chaque requête individuelle. L'ajouter aux certificats de confiance est la solution la plus simple. Ajoutez simplement le contenu du certificat de l'autorité de certification de l'hôte distant à la fin du fichier cacert.pem que vous avez téléchargé.
Précédent:
fsockopen ne supporte pas les contextes de flux, utilisez donc stream_socket_client. Il retourne une ressource qui peut être utilisée avec toutes les commandes que les ressources fsockopen peuvent.
Cela devrait remplacer le fragment que vous avez dans votre question:
<?php
$contextOptions = array(
'ssl' => array(
'verify_peer' => true, // You could skip all of the trouble by changing this to false, but it's WAY uncool for security reasons.
'cafile' => '/etc/ssl/certs/cacert.pem',
'CN_match' => 'example.com', // Change this to your certificates Common Name (or just comment this line out if not needed)
'ciphers' => 'HIGH:!SSLv2:!SSLv3',
'disable_compression' => true,
)
);
$context = stream_context_create($contextOptions);
$fp = stream_socket_client("tcp://{$Host}:{$port}", $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $context);
if (!$fp) {
echo "$errstr ({$errno})<br />\n";
}else{
$this->request = 'POST '.substr($this->url, strlen($this->Host)).' HTTP/1.1'.$crlf
.'Host: '.$this->Host.$crlf
.'Content-Length: '.$content_length.$crlf
.'Connection: Close'.$crlf.$crlf
.$body;
fwrite($fp, $this->request);
while (!feof($fp)) {
$this->response .= fgets($fp);
}
fclose($fp);
}
Le problème est dans la nouvelle version PHP dans macOS Sierra
S'il-vous-plait ajoutez
stream_context_set_option($ctx, 'ssl', 'verify_peer', false);
J'ai eu à faire face à un problème similaire lors du travail avec Ubuntu 16.04 en utilisant Docker. Dans mon cas, c'était un problème avec Composer, mais le message d'erreur (et donc le problème) était le même.
À cause de l'image de base minimaliste orientée Docker, il me manquait le paquet ca-certificates
et le simple apt-get install ca-certificates
m'a aidé.
Ajouter
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
));
avant
mail->send()
et remplacer
require "mailer/class.phpmailer.php";
avec
require "mailer/PHPMailerAutoload.php";
Vous dites que le certificat est auto-signé (par vous)? Ensuite, vous avez deux choix:
cacert.pem
sur le site Web de cURL ne fera rien car il est auto-signé)Voici une liste des options de contexte SSL en PHP: https://secure.php.net/manual/fr/context.ssl.php
Définissez allow_self_signed
si vous importez votre certificat dans votre magasin de données de confiance ou définissez verify_peer
sur false pour ignorer la vérification.
La raison pour laquelle nous faisons confiance à un certificat spécifique est parce que nous faisons confiance à son émetteur . Étant donné que votre certificat est auto-signé, aucun client n'acceptera le certificat car le signataire (vous) n'est pas approuvé. Si vous avez créé votre propre autorité de certification lors de la signature du certificat, vous pouvez l'ajouter à votre magasin de données de confiance. Si votre certificat ne contient aucune autorité de certification, vous ne pouvez vous attendre à ce que personne ne se connecte à votre serveur.
Dans mon cas, j'étais sur CentOS 7 et mon installation php pointait vers un certificat généré par update-ca-trust
. Le lien symbolique était /etc/pki/tls/cert.pem
pointant vers /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
. C'était juste un serveur de test et je voulais que mon CERT auto-signé fonctionne correctement. Donc dans mon cas ...
# My root ca-trust folder was here. I coped the .crt file to this location
# and renamed it to a .pem
/etc/pki/ca-trust/source/anchors/self-signed-cert.pem
# Then run this command and it will regenerate the certs for you and
# include your self signed cert file.
update-ca-trust
Ensuite, certains de mes appels api ont commencé à fonctionner car mon certificat était désormais approuvé. De plus, si votre ca-trust est mis à jour via yum ou autre chose, cela reconstruira vos certificats racine et inclura tout de même votre certificat auto-signé. Exécutez man update-ca-trust
pour plus d'informations sur ce qu'il faut faire et comment le faire. :)
Si vous utilisez macOS sierra, une mise à jour est disponible dans la version PHP. vous devez ajouter le fichier Entrust.net Certificate Authority (2048) au code PHP. plus d'infos vérifier réponse acceptée ici Notification Push dans PHP à l'aide d'un fichier PEM
Tout d’abord, assurez-vous que votre logiciel antivirus ne bloque pas SSL2.
Parce que je n'ai pas pu résoudre un problème pendant longtemps et que seule la désactivation de l'antivirus m'a aidé