web-dev-qa-db-fra.com

Erreur SSL SSL3_GET_SERVER_CERTIFICATE: échec de la vérification du certificat

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

code

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);
}

Ont essayé

# 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

mettre à jour

Cela marche

echo file_get_contents("/etc/ssl/certs/cacert.pem");

mise à jour 2

$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

39
clarkk

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);

}
29
aecend

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);
7

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é.

4

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";
3
Himanshu Sharma

Vous dites que le certificat est auto-signé (par vous)? Ensuite, vous avez deux choix:

  • ajoutez le certificat à votre magasin de confiance (le cacert.pem sur le site Web de cURL ne fera rien car il est auto-signé)
  • ne vous embêtez pas à vérifier le certificat: vous vous faites confiance, n'est-ce pas?

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.

0
DavidS

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. :)

0
n0nag0n

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

0
Im Batman

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é

0
Igor Shumichenko