web-dev-qa-db-fra.com

Erreur lors de l'utilisation de PHP cURL avec des certificats SSL

J'essaie d'écrire un script PHP utilisant cURL qui peut autoriser un utilisateur via une page qui utilise un certificat SSL, en plus du nom d'utilisateur et du mot de passe, et je n'arrive pas à passer l'étape du certificat SSL.

Dans ce cas, curl_setopt($handle, CURLOPT_VERIFYPEER, 0) n'est malheureusement pas une option. Le certificat est une partie requise de l'authentification, sinon j'obtiens l'erreur mentionnée dans cet autre similaire SO post .

J'ai essayé quelques exécutions en ligne de commande avec cURL:

> curl --url https://website

Cela renvoie le (60) SLL certificate problem Erreur. Si j'ajuste la commande pour inclure le --cacert option:

> curl --url https://website --cacert /path/to/servercert.cer

Cela fonctionne très bien; le site Web d'authentification est retourné.

Cependant, j'ai essayé le code PHP PHP suivant:

$handle = curl_init();
$options = array( 
                  CURLOPT_RETURNTRANSFER => false,
                  CURLOPT_HEADER         => true,
                  CURLOPT_FOLLOWLOCATION => false,
                  CURLOPT_SSL_VERIFYHOST => '0',
                  CURLOPT_SSL_VERIFYPEER => '1',
                  CURLOPT_CAINFO         => '/path/to/servercert.cer',
                  CURLOPT_USERAGENT      => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)',
                  CURLOPT_VERBOSE        => true,
                  CURLOPT_URL            => 'https://website'
           );

curl_setopt_array($handle, $options);
curl_exec($handle);
if (curl_errno($handle)) {
  echo 'Error: ' . curl_error($handle);
}
curl_close($handle);

J'aurais pensé que le code était essentiellement analogue aux commandes Shell, mais à la place, je suis accueilli avec le message d'erreur suivant:

Erreur: erreur lors de la définition du certificat, vérifiez les emplacements: CAfile: /path/to/servercert.cer CApath: aucun

J'ai lu toute la littérature que je peux trouver (en particulier sur php.net et curl.haxx) et je n'arrive pas à trouver quoi que ce soit qui résout ce problème. Aucune suggestion?

ÉDITER: J'ai essayé chmod 777 servercert.cer sans succès. Cependant, lors de l'exécution du script PHP avec le code ci-dessus à partir de la ligne de commande au lieu du navigateur via php test.php, cela fonctionne parfaitement. Une explication pour pourquoi cela ne fonctionne pas dans le navigateur?

EDIT 2: Ces votes négatifs sur les seules âmes assez courageuses pour répondre à cette question vieillissent. Soit contribuer quelque chose de significatif ou passer, s'il vous plaît.

26
Magsol

Parce que les choses fonctionnent via la ligne de commande mais pas via php en utilisant curl alors je continuerais à curl étant le problème.

Selon cette URL, http://curl.haxx.se/docs/sslcerts.html , qui faisait référence dans un SO message que vous avez cité ci-dessus (- lecture de la page SSL avec CURL (php) ) ...

"Jusqu'au 7.18.0, curl regroupait un fichier de bundle ca très obsolète qui était installé par défaut. De nos jours, les archives curl ne contiennent aucun certificat ca. Vous devez les obtenir ailleurs. Voir ci-dessous par exemple.

Si le serveur distant utilise un certificat auto-signé, si vous n'installez pas de bundle de cert CA, si le serveur utilise un certificat signé par une CA qui n'est pas inclus dans le bundle que vous utilisez ou si l'hôte distant est un imposteur emprunter l'identité de votre site préféré et que vous souhaitez transférer des fichiers depuis ce serveur, effectuez l'une des opérations suivantes: "

Il énumère ensuite un certain nombre d'étapes que vous pouvez essayer.

Étant donné que votre version de curl 7.16.3 est antérieure à 7.18.0, si vous ne l'avez pas déjà fait, je vous recommande de mettre à jour vos composants curl et openssl, puis de parcourir la liste référencée ci-dessus.

13
Night Owl

Après 6 ans de question, je rencontre le même problème sur un Host partagé, et apparemment il n'y a pas de réponse satisfaisante. J'ai trouvé pour moi une solution, j'espère qu'elle sera utile à tout le monde.

Vous pouvez essayer cette configuration:

curl_setopt($config,CURLOPT_SSL_VERIFYHOST,0);
curl_setopt($config,CURLOPT_SSL_VERIFYPEER,1);
curl_setopt($config,CURLOPT_CAINFO,'ca-bundle.crt');
curl_setopt($config,CURLOPT_CAPATH,'ca-bundle.crt');

J'ai rencontré la même erreur avec @Magsol: Error: error setting certificate verify locations: CAfile: /path/to/servercert.cer CApath: none; j'ai donc ajouté la 4ème ligne pour définir CAPath.

Ça marche avec moi. Mais notez que le fichier CA doit être placé dans un répertoire accessible (avec chmod 755 ou 777) et il vaut mieux que le fichier CA soit dans le même répertoire avec PHP file.

7
Davuz

Pour élaborer et résumer ceci:

si vous avez un fichier PHP en utilisant PHP curl et placez le certificat ca pour vos systèmes dans le même répertoire, le code ci-dessous vous donnera un coup de pouce)

    $url = "https://myserver.mydomain.local/get_somedata.php";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);

//These next lines are for the magic "good cert confirmation"
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_VERBOSE, true);

//for local domains:
//you need to get the pem cert file for the root ca or intermediate CA that you signed all the domain certificates with so that PHP curl can use it...sorry batteries not included
//place the pem or crt ca certificate file in the same directory as the php file for this code to work
    curl_setopt($ch, CURLOPT_CAINFO, __DIR__.'/cafile.pem');
    curl_setopt($ch, CURLOPT_CAPATH, __DIR__.'/cafile.pem');

//DEBUG: remove slashes on the next line to prove "SSL verify" is the cause       
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

//Error handling and return result
    if (curl_exec($ch) === false)
      {
       $result = curl_error($ch);
      }
    else
      {
       $result = curl_exec($ch);
      }
    // Close handle
    curl_close($ch);
    return $result;
5
A-Train

Maintenant que cette question est très ancienne, elle pourrait être utile pour certains utilisateurs à la recherche d'une réponse actuellement.

J'ai un problème similaire à propos d'une API avec SSL, ayant des problèmes avec CURL (pas avec les navigateurs) mon problème était que je viens de mettre le certificat mais pas la chaîne/bundle ceritifcates. Ensuite, j'ai mis ça et les choses ont commencé à fonctionner. C'est donc important pour éviter les problèmes.

J'espère que cela peut être utile à quelqu'un.

3